[pisa-src] r2944 - in trunk: Makefile.am pairing/README pairing/util pairing/util/pisa-pairing-date.c

  • From: Christoph Viethen <christoph.viethen@xxxxxxxxxxxxxx>
  • To: pisa-src@xxxxxxxxxxxxx
  • Date: Thu, 22 Mar 2012 14:02:18 +0100

Author: viethen
Date: Thu Mar 22 14:02:15 2012
New Revision: 2944

Log:
Add a little utility program needed within the shell scripts for the
webif GUI.

Added:
   trunk/pairing/util/
   trunk/pairing/util/pisa-pairing-date.c
Modified:
   trunk/Makefile.am
   trunk/pairing/README

Modified: trunk/Makefile.am
==============================================================================
--- trunk/Makefile.am   Thu Mar 22 13:55:33 2012        (r2943)
+++ trunk/Makefile.am   Thu Mar 22 14:02:15 2012        (r2944)
@@ -71,6 +71,7 @@
                pairing-legacy/management                 \
                pairing-legacy/passgen                    \
                pairing-legacy/send                       \
+               pairing/util/pisa-pairing-date            \
                pisacd/pisacdconf                         \
                pisasd/pisasdconf                         \
                test/checkhipd                            \
@@ -149,6 +150,8 @@
 pairing_legacy_passgen_SOURCES = pairing-legacy/hash.c    \
                                  pairing-legacy/passgen.c
 
+pairing_util_pisa_pairing_date = pairing/util/pisa-pairing-date.c
+
 pisabeacon_pisabeacon_SOURCES = pisabeacon/pisabeacon.c
 
 pisacd_pisacd_SOURCES = pisacd/cdconf.c         \

Modified: trunk/pairing/README
==============================================================================
--- trunk/pairing/README        Thu Mar 22 13:55:33 2012        (r2943)
+++ trunk/pairing/README        Thu Mar 22 14:02:15 2012        (r2944)
@@ -11,7 +11,11 @@
 webif           contains a number of scripts in order to extend the
                  webif GUI of a Trust Point with pairing functionality
 
-
+util            contains a few small utility programs that will be called
+                 by the shell scripts from the webif directory; these
+                 utility programs were written in C, to provide
+                 functionality that was hard to achieve with shell scripts
+                 alone
 
 
 C. Viethen, August 2011

Added: trunk/pairing/util/pisa-pairing-date.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ trunk/pairing/util/pisa-pairing-date.c      Thu Mar 22 14:02:15 2012        
(r2944)
@@ -0,0 +1,222 @@
+/**
+ * @file
+ * This program will verify a date string of the format yyyy-mm-dd for
+ * validity. It will indicate success or failure by an appropriate result
+ * code.
+ *
+ * If the given date is valid, and if an optional offset value is provided,
+ * this offset will be interpreted as a number of months. The date will be
+ * moved into the future by this indicated number of months. The "day" of
+ * the date will then be set to correctly indicate the last day of the
+ * respective calender month. The offset value must be between 0 and 99.
+ *
+ * A date thus modified will be output to stdout, in the same yyyy-mm-dd
+ * format.
+ *
+ * Examples: 2012-03-31, with offset 6, will yield 2012-09-30.
+ *           2012-02-29, with offset 12, will yield 2013-02-28.
+ *           2011-01-14, with offset 6, will yield 2011-07-31.
+ *           2012-06-03, with offset 0, will yield 2012-06-30.
+ *
+ * @brief verify and increment date strings in yyyy-mm-dd format.
+ * @author Christoph Viethen <christoph.viethen@xxxxxxxxxxxxxx>
+ */
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define __USE_MISC
+#include <time.h>
+
+static void print_patched_date(char *input_date_string, char *offset_string)
+{
+    int       offset;
+    char      year_string[5]  = { 0 };
+    char      month_string[3] = { 0 };
+    int       year, month;
+    struct tm first_of_following_month;
+    struct tm last_of_target_month;
+    time_t    timestamp                = 0;
+
+    if (input_date_string == NULL || offset_string == NULL) {
+        return;
+    }
+
+    if (sscanf(offset_string, "%d", &offset) != 1) {
+        return;
+    }
+
+    /* extract year and month from the date string which was input */
+    strncpy(year_string, input_date_string, 4);
+    strncpy(month_string, input_date_string + 5, 2);
+
+    year  = atoi(year_string);
+    month = atoi(month_string);
+
+    /* add the offset plus one more month, yielding the month following
+     * the actual target ... */
+    month += (offset + 1);
+
+    if (month > 12) {
+        year += (month - 1) / 12;
+        month = ((month - 1) % 12) + 1;
+    }
+
+    /* ... and express the first day of that following month */
+    memset(&first_of_following_month, 0, sizeof(struct tm));
+    first_of_following_month.tm_year  = year - 1900;
+    first_of_following_month.tm_mon   = month - 1;
+    first_of_following_month.tm_mday  = 1;
+    first_of_following_month.tm_isdst = -1;
+
+    /* Calculate the timestamp of that day, 00:00:00 GMT */
+    timestamp = timegm(&first_of_following_month);
+
+    if (timestamp == -1 || timestamp == 0) {
+        return;
+    }
+
+    /* Go one second back, which should be equivalent to
+     * 23:59:59 GMT on the last day of the target month */
+    timestamp--;
+
+    if (gmtime_r(&timestamp, &last_of_target_month) == NULL) {
+        return;
+    }
+
+    printf("%04d-%02d-%02d\n", last_of_target_month.tm_year + 1900, 
last_of_target_month.tm_mon + 1, last_of_target_month.tm_mday);
+}
+
+static bool verify_offset(const char *offset_string)
+{
+    int len = 0;
+
+    if (offset_string == NULL) {
+        return false;
+    }
+
+    /* allow one leading '+' */
+    if (offset_string[0] == '+') {
+        offset_string++;
+    }
+
+    /* safely verify the length - count up to 3 chars, so strings which
+     * are too long can be distinguished from strings which have the
+     * desirable length of 2 chars max */
+    while (len < 3 && offset_string[len] != 0) {
+        len++;
+    }
+
+    /* ensure offset string consists of no more than 2 (decimal) digits */
+    if (len < 3 && len > 0) {
+        for (int i = 0; i < len; i++) {
+            if (offset_string[i] < '0' || offset_string[i] > '9') {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    return false;
+}
+
+static bool verify_date_semantics(char *date_string)
+{
+    struct tm input_date;
+    int       year, month, day;
+
+    if (date_string == NULL) {
+        return false;
+    }
+
+    if (sscanf(date_string, "%4d-%2d-%2d", &year, &month, &day) != 3) {
+        return false;
+    }
+
+    memset(&input_date, 0, sizeof(struct tm));
+    input_date.tm_year = year - 1900;
+    input_date.tm_mon  = month - 1;
+    input_date.tm_mday = day;
+//    input_date.tm_isdst = -1; /* don't know whether DST in force or not */
+
+    /* Use timegm() to convert a broken-down date into a timestamp value -
+     * conveniently, timegm() will normalize the values in the tm structure
+     * so they make sense, e.g., a 35th of January will be converted to
+     * the 4th of February. (If the date is "too broken", for whatever
+     * that means, timegm() will return -1.) */
+    if (timegm(&input_date) == -1) {
+        return false;
+    }
+
+    /* find out whether normalization was performed - if so, the specified
+     * date contained semantic errors */
+    if (year != input_date.tm_year + 1900 || month != input_date.tm_mon + 1
+        || day != input_date.tm_mday) {
+        return false;
+    }
+
+    return true;
+}
+
+static bool verify_date_format(char *date_string)
+{
+    int         i               = 0;
+    char        year_string[5]  = { 0 };
+    char        month_string[3] = { 0 };
+    char        day_string[3]   = { 0 };
+    const char *digits          = "0123456789";
+
+    if (date_string == NULL) {
+        return false;
+    }
+
+    /* safely verify the length - count up to 11 chars, so strings which
+     * are too long can be distinguished from strings which have the
+     * desirable length of 10 chars */
+    while (i < 11 && date_string[i] != 0) {
+        i++;
+    }
+
+    if (i != 10) {
+        return false;
+    }
+
+    /* verify that digits and hyphens are in the right places */
+    if (date_string[4] != '-' || date_string[7] != '-') {
+        return false;
+    }
+
+    strncpy(year_string, date_string, 4);
+    strncpy(month_string, date_string + 5, 2);
+    strncpy(day_string, date_string + 8, 2);
+
+    if (strspn(year_string, digits) != 4 || strspn(month_string, digits) != 2
+        || strspn(day_string, digits) != 2) {
+        return false;
+    }
+
+    return true;
+}
+
+int main(int argc, char *argv[])
+{
+    int exit_status = EXIT_FAILURE;
+
+    if (argc == 2 || argc == 3) {
+        if (verify_date_format(argv[1]) == true &&
+            verify_date_semantics(argv[1]) == true) {
+            exit_status = EXIT_SUCCESS;
+
+            if (argc == 3) {
+                if (verify_offset(argv[2]) == true) {
+                    print_patched_date(argv[1], argv[2]);
+                } else {
+                    exit_status = EXIT_FAILURE;
+                }
+            }
+        }
+    }
+
+    exit(exit_status);
+}
-- 
This is the pisa developer mailing list. Please also subscribe to the main pisa 
list at:
//www.freelists.org/list/pisa

Other related posts: