static int xsltNumberFormatGetValue(xmlXPathContextPtr context, xmlNodePtr node, xmlChar *value, double *number) { int amount = 0; xmlBufferPtr pattern; xmlXPathObjectPtr obj; pattern = xmlBufferCreate(); if (pattern != NULL) { xmlBufferCCat(pattern, "number("); xmlBufferCat(pattern, value); xmlBufferCCat(pattern, ")"); context->node = node; obj = xmlXPathEvalExpression(xmlBufferContent(pattern), context); if (obj != NULL) { *number = obj->floatval; amount++; xmlXPathFreeObject(obj); } xmlBufferFree(pattern); } return amount; }
static void xsltNumberFormatAlpha(xmlBufferPtr buffer, double number, int is_upper) { char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; char *pointer; int i; char *alpha_list; double alpha_size = (double)(sizeof(alpha_upper_list) - 1); /* Build buffer from back */ pointer = &temp_string[sizeof(temp_string)]; *(--pointer) = 0; alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list; for (i = 1; i < (int)sizeof(temp_string); i++) { number--; *(--pointer) = alpha_list[((int)fmod(number, alpha_size))]; number /= alpha_size; if (fabs(number) < 1.0) break; /* for */ } xmlBufferCCat(buffer, pointer); }
static void xsltNumberFormatAlpha(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper) { char temp_string[sizeof(double) * CHAR_BIT * sizeof(xmlChar) + 1]; char *pointer; int i; char *alpha_list; double alpha_size = (double)(sizeof(alpha_upper_list) - 1); /* * XSLT 1.0 isn't clear on how to handle zero, but XSLT 2.0 says: * * For all format tokens other than the first kind above (one that * consists of decimal digits), there may be implementation-defined * lower and upper bounds on the range of numbers that can be * formatted using this format token; indeed, for some numbering * sequences there may be intrinsic limits. [...] Numbers that fall * outside this range must be formatted using the format token 1. * * The "a" token has an intrinsic lower limit of 1. */ if (number < 1.0) { xsltNumberFormatDecimal(buffer, number, '0', 1, data->digitsPerGroup, data->groupingCharacter, data->groupingCharacterLen); return; } /* Build buffer from back */ pointer = &temp_string[sizeof(temp_string)]; *(--pointer) = 0; alpha_list = (is_upper) ? alpha_upper_list : alpha_lower_list; for (i = 1; i < (int)sizeof(temp_string); i++) { number--; *(--pointer) = alpha_list[((int)fmod(number, alpha_size))]; number /= alpha_size; if (number < 1.0) break; /* for */ } xmlBufferCCat(buffer, pointer); }
xmlChar* PmmFastEncodeString( int charset, const xmlChar *string, const xmlChar *encoding ) { xmlCharEncodingHandlerPtr coder = NULL; xmlChar *retval = NULL; xmlBufferPtr in = NULL, out = NULL; if ( charset == XML_CHAR_ENCODING_UTF8 ) { /* warn("use UTF8 for encoding ... %s ", string); */ return xmlStrdup( string ); } else if ( charset == XML_CHAR_ENCODING_ERROR ) { /* warn("no standard encoding %s\n", encoding); */ coder =xmlFindCharEncodingHandler( (const char *)encoding ); } else if ( charset == XML_CHAR_ENCODING_NONE ) { xs_warn("PmmFastEncodeString: no encoding found\n"); } else { /* warn( "use document encoding %s (%d)", encoding, charset ); */ coder= xmlGetCharEncodingHandler( charset ); } if ( coder != NULL ) { xs_warn("PmmFastEncodeString: coding machine found \n"); in = xmlBufferCreate(); out = xmlBufferCreate(); xmlBufferCCat( in, (const char *) string ); if ( xmlCharEncInFunc( coder, out, in ) >= 0 ) { retval = xmlStrdup( out->content ); /* warn( "encoded string is %s" , retval); */ } else { /* warn( "b0rked encoiding!\n"); */ } xmlBufferFree( in ); xmlBufferFree( out ); xmlCharEncCloseFunc( coder ); } return retval; }
void stats_set_conv (long handle, const char *name, const char *value, const char *charset) { if (charset) { xmlCharEncodingHandlerPtr encoding = xmlFindCharEncodingHandler (charset); if (encoding) { xmlBufferPtr in = xmlBufferCreate (); xmlBufferPtr conv = xmlBufferCreate (); xmlBufferCCat (in, value); if (xmlCharEncInFunc (encoding, conv, in) > 0) stats_set_entity_decode (handle, name, (void*)xmlBufferContent (conv)); xmlBufferFree (in); xmlBufferFree (conv); xmlCharEncCloseFunc (encoding); return; } WARN1 ("No charset found for \"%s\"", charset); return; } stats_set_entity_decode (handle, name, value); }
/*}}}*/ }; static int psize = sizeof (parseable) / sizeof (parseable[0]); tag_t * tag_alloc (void) /*{{{*/ { tag_t *t; if (t = (tag_t *) malloc (sizeof (tag_t))) { t -> name = xmlBufferCreate (); t -> cname = NULL; t -> hash = 0; t -> type = NULL; t -> topt = NULL; t -> value = xmlBufferCreate (); t -> parm = NULL; t -> used = false; t -> next = NULL; if ((! t -> name) || (! t -> value)) t = tag_free (t); } return t; }/*}}}*/ tag_t * tag_free (tag_t *t) /*{{{*/ { if (t) { if (t -> name) xmlBufferFree (t -> name); if (t -> cname) free (t -> cname); if (t -> type) free (t -> type); if (t -> value) xmlBufferFree (t -> value); if (t -> parm) var_free_all (t -> parm); free (t); } return NULL; }/*}}}*/ tag_t * tag_free_all (tag_t *t) /*{{{*/ { tag_t *tmp; while (tmp = t) { t = t -> next; tag_free (tmp); } return NULL; }/*}}}*/ static void xmlSkip (xmlChar **ptr, int *len) /*{{{*/ { int n; while (*len > 0) { n = xmlCharLength (**ptr); if ((n == 1) && isspace (**ptr)) { *(*ptr)++ = '\0'; *len -= 1; while ((*len > 0) && (xmlCharLength (**ptr) == 1) && isspace (**ptr)) ++(*ptr); break; } else { *ptr += n; *len -= n; } } }/*}}}*/ static int mkRFCdate (char *dbuf, size_t dlen) /*{{{*/ { time_t now; struct tm *tt; time (& now); if (tt = gmtime (& now)) { const char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }, *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; return sprintf (dbuf, "%s, %2d %s %d %02d:%02d:%02d GMT", weekday[tt -> tm_wday], tt -> tm_mday, month[tt -> tm_mon], tt -> tm_year + 1900, tt -> tm_hour, tt -> tm_min, tt -> tm_sec) > 0; } return 0; }/*}}}*/ static const char * find_default (tag_t *t) /*{{{*/ { const char *dflt = NULL; var_t *run; for (run = t -> parm; run; run = run -> next) if (! strcmp (run -> var, "default")) { dflt = run -> val; break; } return dflt; }/*}}}*/ void tag_parse (tag_t *t, blockmail_t *blockmail) /*{{{*/ { xmlBufferPtr temp; if (t -> name && (xmlBufferLength (t -> name) > 0) && (temp = xmlBufferCreateSize (xmlBufferLength (t -> name) + 1))) { xmlChar *ptr; xmlChar *name; int len; int tid; xmlBufferAdd (temp, xmlBufferContent (t -> name), xmlBufferLength (t -> name)); ptr = (xmlChar *) xmlBufferContent (temp); len = xmlBufferLength (temp); if ((xmlCharLength (*ptr) == 1) && (*ptr == '[')) { ++ptr; --len; if ((len > 0) && (xmlStrictCharLength (*(ptr + len - 1)) == 1) && (*(ptr + len - 1) == ']')) { --len; if ((len > 0) && (xmlStrictCharLength (*(ptr + len - 1)) == 1) && (*(ptr + len - 1) == '/')) --len; ptr[len] = '\0'; } } name = ptr; xmlSkip (& ptr, & len); if (t -> type) { for (tid = 0; tid < psize; ++tid) if (! strcmp (t -> type, parseable[tid].tname)) break; } else tid = psize; if (tid == psize) for (tid = 0; tid < psize; ++tid) if (! xmlstrcmp (name, parseable[tid].tname)) break; if (tid < psize) { var_t *cur, *prev; xmlChar *var, *val; int n; for (prev = t -> parm; prev && prev -> next; prev = prev -> next) ; while (len > 0) { var = ptr; while (len > 0) { n = xmlCharLength (*ptr); if ((n == 1) && (*ptr == '=')) { *ptr++ = '\0'; len -= 1; break; } else { ptr += n; len -= n; } } if (len > 0) { if ((xmlCharLength (*ptr) == 1) && (*ptr == '"')) { ++ptr; --len; val = ptr; while (len > 0) { n = xmlCharLength (*ptr); if ((n == 1) && (*ptr == '"')) { *ptr++ = '\0'; len -= 1; xmlSkip (& ptr, & len); break; } else { ptr += n; len -= n; } } } else { val = ptr; xmlSkip (& ptr, & len); } if (cur = var_alloc (xml2char (var), xml2char (val))) { if (prev) prev -> next = cur; else t -> parm = cur; prev = cur; } } } switch ((enum PType) tid) { case P_Sysinfo: for (cur = t -> parm; cur; cur = cur -> next) if (! strcmp (cur -> var, "name")) { if (! strcmp (cur -> val, "FQDN")) { const char *dflt; if (blockmail -> fqdn) { xmlBufferEmpty (t -> value); xmlBufferCCat (t -> value, blockmail -> fqdn); } else if (dflt = find_default (t)) { xmlBufferEmpty (t -> value); xmlBufferCCat (t -> value, dflt); } } else if (! strcmp (cur -> val, "RFCDATE")) { char dbuf[128]; if (mkRFCdate (dbuf, sizeof (dbuf))) { xmlBufferEmpty (t -> value); xmlBufferCCat (t -> value, dbuf); } } else if (! strcmp (cur -> val, "EPOCH")) { time_t now; char dbuf[64]; time (& now); sprintf (dbuf, "%ld", (long) now); xmlBufferEmpty (t -> value); xmlBufferCCat (t -> value, dbuf); } } break; } } xmlBufferFree (temp); } }/*}}}*/
static void xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, double *numbers, int numbers_max, xsltFormatPtr tokens, xmlBufferPtr buffer) { int i = 0; double number; xsltFormatTokenPtr token; /* * Handle initial non-alphanumeric token */ if (tokens->start != NULL) xmlBufferCat(buffer, tokens->start); for (i = 0; i < numbers_max; i++) { /* Insert number */ number = numbers[(numbers_max - 1) - i]; if (i < tokens->nTokens) { /* The "n"th format token will be used to format the "n"th * number in the list */ token = &(tokens->tokens[i]); } else if (tokens->nTokens > 0) { /* If there are more numbers than format tokens, then the * last format token will be used to format the remaining * numbers. */ token = &(tokens->tokens[tokens->nTokens - 1]); } else { /* If there are no format tokens, then a format token of * 1 is used to format all numbers. */ token = &default_token; } /* Print separator, except for the first number */ if (i > 0) { if (token->separator != NULL) xmlBufferCat(buffer, token->separator); else xmlBufferCCat(buffer, DEFAULT_SEPARATOR); } switch (xmlXPathIsInf(number)) { case -1: xmlBufferCCat(buffer, "-Infinity"); break; case 1: xmlBufferCCat(buffer, "Infinity"); break; default: if (xmlXPathIsNaN(number)) { xmlBufferCCat(buffer, "NaN"); } else { switch (token->token) { case 'A': xsltNumberFormatAlpha(buffer, number, TRUE); break; case 'a': xsltNumberFormatAlpha(buffer, number, FALSE); break; case 'I': xsltNumberFormatRoman(buffer, number, TRUE); break; case 'i': xsltNumberFormatRoman(buffer, number, FALSE); break; default: if (IS_DIGIT_ZERO(token->token)) { xsltNumberFormatDecimal(buffer, number, token->token, token->width, data->digitsPerGroup, data->groupingCharacter); } break; } } } } /* * Handle final non-alphanumeric token */ if (tokens->end != NULL) xmlBufferCat(buffer, tokens->end); }
static void xsltNumberFormatRoman(xmlBufferPtr buffer, double number, int is_upper) { /* * Based on an example by Jim Walsh */ while (number >= 1000.0) { xmlBufferCCat(buffer, (is_upper) ? "M" : "m"); number -= 1000.0; } if (number >= 900.0) { xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm"); number -= 900.0; } while (number >= 500.0) { xmlBufferCCat(buffer, (is_upper) ? "D" : "d"); number -= 500.0; } if (number >= 400.0) { xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd"); number -= 400.0; } while (number >= 100.0) { xmlBufferCCat(buffer, (is_upper) ? "C" : "c"); number -= 100.0; } if (number >= 90.0) { xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc"); number -= 90.0; } while (number >= 50.0) { xmlBufferCCat(buffer, (is_upper) ? "L" : "l"); number -= 50.0; } if (number >= 40.0) { xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl"); number -= 40.0; } while (number >= 10.0) { xmlBufferCCat(buffer, (is_upper) ? "X" : "x"); number -= 10.0; } if (number >= 9.0) { xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix"); number -= 9.0; } while (number >= 5.0) { xmlBufferCCat(buffer, (is_upper) ? "V" : "v"); number -= 5.0; } if (number >= 4.0) { xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv"); number -= 4.0; } while (number >= 1.0) { xmlBufferCCat(buffer, (is_upper) ? "I" : "i"); number--; } }
static void xsltNumberFormatInsertNumbers(xsltNumberDataPtr data, double *numbers, int numbers_max, xsltFormatPtr tokens, xmlBufferPtr buffer) { int i = 0; double number; xsltFormatTokenPtr token; /* * Handle initial non-alphanumeric token */ if (tokens->start != NULL) xmlBufferCat(buffer, tokens->start); for (i = 0; i < numbers_max; i++) { /* Insert number */ number = numbers[(numbers_max - 1) - i]; /* Round to nearest like XSLT 2.0 */ number = floor(number + 0.5); /* * XSLT 1.0 isn't clear on how to handle negative numbers, but XSLT * 2.0 says: * * It is a non-recoverable dynamic error if any undiscarded item * in the atomized sequence supplied as the value of the value * attribute of xsl:number cannot be converted to an integer, or * if the resulting integer is less than 0 (zero). */ if (number < 0.0) { xsltTransformError(NULL, NULL, NULL, "xsl-number : negative value\n"); /* Recover by treating negative values as zero. */ number = 0.0; } if (i < tokens->nTokens) { /* * The "n"th format token will be used to format the "n"th * number in the list */ token = &(tokens->tokens[i]); } else if (tokens->nTokens > 0) { /* * If there are more numbers than format tokens, then the * last format token will be used to format the remaining * numbers. */ token = &(tokens->tokens[tokens->nTokens - 1]); } else { /* * If there are no format tokens, then a format token of * 1 is used to format all numbers. */ token = &default_token; } /* Print separator, except for the first number */ if (i > 0) { if (token->separator != NULL) xmlBufferCat(buffer, token->separator); else xmlBufferCCat(buffer, DEFAULT_SEPARATOR); } switch (xmlXPathIsInf(number)) { case -1: xmlBufferCCat(buffer, "-Infinity"); break; case 1: xmlBufferCCat(buffer, "Infinity"); break; default: if (xmlXPathIsNaN(number)) { xmlBufferCCat(buffer, "NaN"); } else { switch (token->token) { case 'A': xsltNumberFormatAlpha(data, buffer, number, TRUE); break; case 'a': xsltNumberFormatAlpha(data, buffer, number, FALSE); break; case 'I': xsltNumberFormatRoman(data, buffer, number, TRUE); break; case 'i': xsltNumberFormatRoman(data, buffer, number, FALSE); break; default: if (IS_DIGIT_ZERO(token->token)) { xsltNumberFormatDecimal(buffer, number, token->token, token->width, data->digitsPerGroup, data->groupingCharacter, data->groupingCharacterLen); } break; } } } } /* * Handle final non-alphanumeric token */ if (tokens->end != NULL) xmlBufferCat(buffer, tokens->end); }
static void xsltNumberFormatRoman(xsltNumberDataPtr data, xmlBufferPtr buffer, double number, int is_upper) { /* * See discussion in xsltNumberFormatAlpha. Also use a reasonable upper * bound to avoid denial of service. */ if (number < 1.0 || number > 5000.0) { xsltNumberFormatDecimal(buffer, number, '0', 1, data->digitsPerGroup, data->groupingCharacter, data->groupingCharacterLen); return; } /* * Based on an example by Jim Walsh */ while (number >= 1000.0) { xmlBufferCCat(buffer, (is_upper) ? "M" : "m"); number -= 1000.0; } if (number >= 900.0) { xmlBufferCCat(buffer, (is_upper) ? "CM" : "cm"); number -= 900.0; } while (number >= 500.0) { xmlBufferCCat(buffer, (is_upper) ? "D" : "d"); number -= 500.0; } if (number >= 400.0) { xmlBufferCCat(buffer, (is_upper) ? "CD" : "cd"); number -= 400.0; } while (number >= 100.0) { xmlBufferCCat(buffer, (is_upper) ? "C" : "c"); number -= 100.0; } if (number >= 90.0) { xmlBufferCCat(buffer, (is_upper) ? "XC" : "xc"); number -= 90.0; } while (number >= 50.0) { xmlBufferCCat(buffer, (is_upper) ? "L" : "l"); number -= 50.0; } if (number >= 40.0) { xmlBufferCCat(buffer, (is_upper) ? "XL" : "xl"); number -= 40.0; } while (number >= 10.0) { xmlBufferCCat(buffer, (is_upper) ? "X" : "x"); number -= 10.0; } if (number >= 9.0) { xmlBufferCCat(buffer, (is_upper) ? "IX" : "ix"); number -= 9.0; } while (number >= 5.0) { xmlBufferCCat(buffer, (is_upper) ? "V" : "v"); number -= 5.0; } if (number >= 4.0) { xmlBufferCCat(buffer, (is_upper) ? "IV" : "iv"); number -= 4.0; } while (number >= 1.0) { xmlBufferCCat(buffer, (is_upper) ? "I" : "i"); number--; } }