p = val->bv_val;
/* Ignore initial whitespace */
- while ( isspace( *p++ ) ) {
- /* EMPTY */ ;
+ while ( isspace( *p ) ) {
+ p++;
}
if( *p != '\0' ) {
*q++ = *p++;
/* Ignore the extra whitespace */
- while ( isspace( *p++ ) ) {
- /* EMPTY */ ;
+ while ( isspace( *p ) ) {
+ p++;
}
} else {
*q++ = *p++;
p = val->bv_val;
/* Ignore initial whitespace */
- while ( isspace( *p++ ) ) {
- /* EMPTY */ ;
+ while ( isspace( *p ) ) {
+ p++;
}
if( *p != '\0' ) {
return LDAP_SUCCESS;
}
+static int
+check_time_syntax (struct berval *val,
+ int start,
+ int *parts)
+{
+ static int ceiling[9] = { 99, 99, 11, 30, 23, 59, 59, 12, 59 };
+ static int mdays[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ char *p, *e;
+ int part, c, neg = 0;
+
+ if( val->bv_len == 0 )
+ return LDAP_INVALID_SYNTAX;
+
+ p = (char *)val->bv_val;
+ e = p + val->bv_len;
+
+ /* Ignore initial whitespace */
+ while ( ( p < e ) && isspace( *p ) ) {
+ p++;
+ }
+
+ if (e - p < 13 - (2 * start))
+ return LDAP_INVALID_SYNTAX;
+
+ for (part = 0; part < 9; part++)
+ parts[part] = 0;
+
+ for (part = start; part < 7; part++) {
+ c = *p;
+ if ((part == 6)
+ && (c == 'Z'
+ || c == '+'
+ || c == '-'))
+ {
+ part++;
+ break;
+ }
+ p++;
+ c -= '0';
+ if (p == e)
+ return LDAP_INVALID_SYNTAX;
+ if (c < 0 || c > 9)
+ return LDAP_INVALID_SYNTAX;
+ parts[part] = c;
+
+ c = *p++ - '0';
+ if (p == e)
+ return LDAP_INVALID_SYNTAX;
+ if (c < 0 || c > 9)
+ return LDAP_INVALID_SYNTAX;
+ parts[part] *= 10;
+ parts[part] += c;
+
+ if (part == 2 || part == 3)
+ parts[part]--;
+ if (parts[part] < 0)
+ return LDAP_INVALID_SYNTAX;
+ if (parts[part] > ceiling[part])
+ return LDAP_INVALID_SYNTAX;
+ }
+ if (parts[2] == 1) {
+ if (parts[3] > mdays[parts[2]])
+ return LDAP_INVALID_SYNTAX;
+ if (parts[1] & 0x03) {
+ /* FIXME: This is an incomplete leap-year
+ * check that fails in 2100, 2200, 2300,
+ * 2500, 2600, 2700, ...
+ */
+ if (parts[3] > mdays[parts[2]] - 1)
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+ c = *p++;
+ if (c == 'Z') {
+ /* all done */
+ } else if (c != '+' && c != '-') {
+ return LDAP_INVALID_SYNTAX;
+ } else {
+ if (c == '-')
+ neg = 1;
+ if (p > e - 4)
+ return LDAP_INVALID_SYNTAX;
+ for (part = 7; part < 9; part++) {
+ c = *p++ - '0';
+ if (c < 0 || c > 9)
+ return LDAP_INVALID_SYNTAX;
+ parts[part] = c;
+
+ c = *p++ - '0';
+ if (c < 0 || c > 9)
+ return LDAP_INVALID_SYNTAX;
+ parts[part] *= 10;
+ parts[part] += c;
+ if (parts[part] < 0 || parts[part] > ceiling[part])
+ return LDAP_INVALID_SYNTAX;
+ }
+ }
+
+ /* Ignore trailing whitespace */
+ while ( ( p < e ) && isspace( *p ) ) {
+ p++;
+ }
+ if (p != e)
+ return LDAP_INVALID_SYNTAX;
+
+ if (neg == 0) {
+ parts[4] += parts[7];
+ parts[5] += parts[8];
+ for (part = 7; --part > 0; ) {
+ if (part != 3)
+ c = ceiling[part];
+ else {
+ /* FIXME: This is an incomplete leap-year
+ * check that fails in 2100, 2200, 2300,
+ * 2500, 2600, 2700, ...
+ */
+ c = mdays[parts[2]];
+ if (parts[2] == 1)
+ c--;
+ }
+ if (parts[part] > c) {
+ parts[part] -= c + 1;
+ parts[part - 1]++;
+ }
+ }
+ } else {
+ parts[4] -= parts[7];
+ parts[5] -= parts[8];
+ for (part = 7; --part > 0; ) {
+ if (part != 3)
+ c = ceiling[part];
+ else {
+ /* FIXME: This is an incomplete leap-year
+ * check that fails in 2100, 2200, 2300,
+ * 2500, 2600, 2700, ...
+ */
+ c = mdays[(parts[2] - 1) % 12];
+ if (parts[2] == 2)
+ c--;
+ }
+ if (parts[part] < 0) {
+ parts[part] += c + 1;
+ parts[part - 1]--;
+ }
+ }
+ }
+
+ return LDAP_SUCCESS;
+}
+
+static int
+utcTimeNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval **normalized )
+{
+ struct berval *out;
+ int parts[9], rc;
+
+ rc = check_time_syntax(val, 1, parts);
+ if (rc != LDAP_SUCCESS) {
+ return rc;
+ }
+
+ *normalized = NULL;
+ out = ch_malloc( sizeof(struct berval) );
+ if( out == NULL )
+ return LBER_ERROR_MEMORY;
+
+ out->bv_val = ch_malloc( 14 );
+ if ( out->bv_val == NULL ) {
+ ch_free( out );
+ return LBER_ERROR_MEMORY;
+ }
+
+ sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ldZ",
+ parts[1], parts[2] + 1, parts[3] + 1,
+ parts[4], parts[5], parts[6] );
+ out->bv_len = 13;
+ *normalized = out;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+utcTimeValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int parts[9];
+
+ return check_time_syntax(in, 1, parts);
+}
+
+static int
+generalizedTimeNormalize(
+ Syntax *syntax,
+ struct berval *val,
+ struct berval **normalized )
+{
+ struct berval *out;
+ int parts[9], rc;
+
+ rc = check_time_syntax(val, 0, parts);
+ if (rc != LDAP_SUCCESS) {
+ return rc;
+ }
+
+ *normalized = NULL;
+ out = ch_malloc( sizeof(struct berval) );
+ if( out == NULL )
+ return LBER_ERROR_MEMORY;
+
+ out->bv_val = ch_malloc( 16 );
+ if ( out->bv_val == NULL ) {
+ ch_free( out );
+ return LBER_ERROR_MEMORY;
+ }
+
+ sprintf( out->bv_val, "%02ld%02ld%02ld%02ld%02ld%02ld%02ldZ",
+ parts[0], parts[1], parts[2] + 1, parts[3] + 1,
+ parts[4], parts[5], parts[6] );
+ out->bv_len = 15;
+ *normalized = out;
+
+ return LDAP_SUCCESS;
+}
+
+static int
+generalizedTimeValidate(
+ Syntax *syntax,
+ struct berval *in )
+{
+ int parts[9];
+
+ return check_time_syntax(in, 0, parts);
+}
+
struct syntax_defs_rec {
char *sd_desc;
int sd_flags;
{"( 1.3.6.1.4.1.1466.115.121.1.23 DESC 'Fax' " X_NOT_H_R ")",
SLAP_SYNTAX_BLOB, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.24 DESC 'Generalized Time' )",
- 0, NULL, NULL, NULL},
+ 0, generalizedTimeValidate, generalizedTimeNormalize, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.25 DESC 'Guide' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.26 DESC 'IA5 String' )",
{"( 1.3.6.1.4.1.1466.115.121.1.52 DESC 'Telex Number' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.53 DESC 'UTC Time' )",
- 0, NULL, NULL, NULL},
+ 0, utcTimeValidate, utcTimeNormalize, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.54 DESC 'LDAP Syntax Description' )",
0, NULL, NULL, NULL},
{"( 1.3.6.1.4.1.1466.115.121.1.55 DESC 'Modify Rights' )",