static int /* O - 1 if match, 0 if no match */ mime_check_rules( const char *filename, /* I - Filename */ _mime_filebuf_t *fb, /* I - File to check */ mime_magic_t *rules) /* I - Rules to check */ { int n; /* Looping var */ int region; /* Region to look at */ int logic, /* Logic to apply */ result, /* Result of test */ intv; /* Integer value */ short shortv; /* Short value */ unsigned char *bufptr; /* Pointer into buffer */ DEBUG_printf(("4mime_check_rules(filename=\"%s\", fb=%p, rules=%p)", filename, fb, rules)); if (rules == NULL) return (0); if (rules->parent == NULL) logic = MIME_MAGIC_OR; else logic = rules->parent->op; result = 0; while (rules != NULL) { /* * Compute the result of this rule... */ switch (rules->op) { case MIME_MAGIC_MATCH : result = mime_patmatch(filename, rules->value.matchv); break; case MIME_MAGIC_ASCII : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + rules->length) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Test for ASCII printable characters plus standard control chars. */ if ((rules->offset + rules->length) > (fb->offset + fb->length)) n = fb->offset + fb->length - rules->offset; else n = rules->length; bufptr = fb->buffer + rules->offset - fb->offset; while (n > 0) if ((*bufptr >= 32 && *bufptr <= 126) || (*bufptr >= 8 && *bufptr <= 13) || *bufptr == 26 || *bufptr == 27) { n --; bufptr ++; } else break; result = (n == 0); break; case MIME_MAGIC_PRINTABLE : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + rules->length) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Test for 8-bit printable characters plus standard control chars. */ if ((rules->offset + rules->length) > (fb->offset + fb->length)) n = fb->offset + fb->length - rules->offset; else n = rules->length; bufptr = fb->buffer + rules->offset - fb->offset; while (n > 0) if (*bufptr >= 128 || (*bufptr >= 32 && *bufptr <= 126) || (*bufptr >= 8 && *bufptr <= 13) || *bufptr == 26 || *bufptr == 27) { n --; bufptr ++; } else break; result = (n == 0); break; case MIME_MAGIC_STRING : DEBUG_printf(("5mime_check_rules: string(%d, \"%s\")", rules->offset, rules->value.stringv)); /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + rules->length) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; DEBUG_printf(("5mime_check_rules: loaded %d byte fb->buffer at %d, starts " "with \"%c%c%c%c\".", fb->length, fb->offset, fb->buffer[0], fb->buffer[1], fb->buffer[2], fb->buffer[3])); } /* * Compare the buffer against the string. If the file is too * short then don't compare - it can't match... */ if ((rules->offset + rules->length) > (fb->offset + fb->length)) result = 0; else result = (memcmp(fb->buffer + rules->offset - fb->offset, rules->value.stringv, rules->length) == 0); DEBUG_printf(("5mime_check_rules: result=%d", result)); break; case MIME_MAGIC_ISTRING : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + rules->length) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Compare the buffer against the string. If the file is too * short then don't compare - it can't match... */ if ((rules->offset + rules->length) > (fb->offset + fb->length)) result = 0; else result = (_cups_strncasecmp((char *)fb->buffer + rules->offset - fb->offset, rules->value.stringv, rules->length) == 0); break; case MIME_MAGIC_CHAR : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Compare the character values; if the file is too short, it * can't match... */ if (fb->length < 1) result = 0; else result = (fb->buffer[rules->offset - fb->offset] == rules->value.charv); break; case MIME_MAGIC_SHORT : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + 2) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Compare the short values; if the file is too short, it * can't match... */ if (fb->length < 2) result = 0; else { bufptr = fb->buffer + rules->offset - fb->offset; shortv = (bufptr[0] << 8) | bufptr[1]; result = (shortv == rules->value.shortv); } break; case MIME_MAGIC_INT : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + 4) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Compare the int values; if the file is too short, it * can't match... */ if (fb->length < 4) result = 0; else { bufptr = fb->buffer + rules->offset - fb->offset; intv = (((((bufptr[0] << 8) | bufptr[1]) << 8) | bufptr[2]) << 8) | bufptr[3]; result = (intv == rules->value.intv); } break; case MIME_MAGIC_LOCALE : #if defined(WIN32) || defined(__EMX__) || defined(__APPLE__) result = (strcmp(rules->value.localev, setlocale(LC_ALL, "")) == 0); #else result = (strcmp(rules->value.localev, setlocale(LC_MESSAGES, "")) == 0); #endif /* __APPLE__ */ break; case MIME_MAGIC_CONTAINS : /* * Load the buffer if necessary... */ if (fb->offset < 0 || rules->offset < fb->offset || (rules->offset + rules->region) > (fb->offset + fb->length)) { /* * Reload file buffer... */ cupsFileSeek(fb->fp, rules->offset); fb->length = cupsFileRead(fb->fp, (char *)fb->buffer, sizeof(fb->buffer)); fb->offset = rules->offset; } /* * Compare the buffer against the string. If the file is too * short then don't compare - it can't match... */ if ((rules->offset + rules->length) > (fb->offset + fb->length)) result = 0; else { if (fb->length > rules->region) region = rules->region - rules->length; else region = fb->length - rules->length; for (n = 0; n < region; n ++) if ((result = (memcmp(fb->buffer + rules->offset - fb->offset + n, rules->value.stringv, rules->length) == 0)) != 0) break; } break; default : if (rules->child != NULL) result = mime_check_rules(filename, fb, rules->child); else result = 0; break; } /* * If the logic is inverted, invert the result... */ if (rules->invert) result = !result; /* * OK, now if the current logic is OR and this result is true, the this * rule set is true. If the current logic is AND and this result is false, * the the rule set is false... */ DEBUG_printf(("5mime_check_rules: result of test %p (MIME_MAGIC_%s) is %d", rules, debug_ops[rules->op], result)); if ((result && logic == MIME_MAGIC_OR) || (!result && logic == MIME_MAGIC_AND)) return (result); /* * Otherwise the jury is still out on this one, so move to the next rule. */ rules = rules->next; } return (result); }
static int /* O - Status */ random_tests(void) { int status, /* Status of tests */ pass, /* Current pass */ count, /* Number of records read */ record, /* Current record */ num_records; /* Number of records */ ssize_t pos, /* Position in file */ expected; /* Expected position in file */ cups_file_t *fp; /* File */ char buffer[512]; /* Data buffer */ /* * Run 4 passes, each time appending to a data file and then reopening the * file for reading to validate random records in the file. */ for (status = 0, pass = 0; pass < 4; pass ++) { /* * cupsFileOpen(append) */ printf("\ncupsFileOpen(append %d): ", pass); if ((fp = cupsFileOpen("testfile.dat", "a")) == NULL) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileTell() */ expected = 256 * sizeof(buffer) * pass; fputs("cupsFileTell(): ", stdout); if ((pos = cupsFileTell(fp)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else puts("PASS"); /* * cupsFileWrite() */ fputs("cupsFileWrite(256 512-byte records): ", stdout); for (record = 0; record < 256; record ++) { memset(buffer, record, sizeof(buffer)); if (cupsFileWrite(fp, buffer, sizeof(buffer)) < sizeof(buffer)) break; } if (record < 256) { printf("FAIL (%d: %s)\n", record, strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileTell() */ expected += 256 * sizeof(buffer); fputs("cupsFileTell(): ", stdout); if ((pos = cupsFileTell(fp)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else puts("PASS"); cupsFileClose(fp); /* * cupsFileOpen(read) */ printf("\ncupsFileOpen(read %d): ", pass); if ((fp = cupsFileOpen("testfile.dat", "r")) == NULL) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else puts("PASS"); /* * cupsFileSeek, cupsFileRead */ fputs("cupsFileSeek(), cupsFileRead(): ", stdout); for (num_records = (pass + 1) * 256, count = (pass + 1) * 256, record = CUPS_RAND() % num_records; count > 0; count --, record = (record + (CUPS_RAND() & 31) - 16 + num_records) % num_records) { /* * The last record is always the first... */ if (count == 1) record = 0; /* * Try reading the data for the specified record, and validate the * contents... */ expected = sizeof(buffer) * record; if ((pos = cupsFileSeek(fp, expected)) != expected) { printf("FAIL (" CUPS_LLFMT " instead of " CUPS_LLFMT ")\n", CUPS_LLCAST pos, CUPS_LLCAST expected); status ++; break; } else { if (cupsFileRead(fp, buffer, sizeof(buffer)) != sizeof(buffer)) { printf("FAIL (%s)\n", strerror(errno)); status ++; break; } else if ((buffer[0] & 255) != (record & 255) || memcmp(buffer, buffer + 1, sizeof(buffer) - 1)) { printf("FAIL (Bad Data - %d instead of %d)\n", buffer[0] & 255, record & 255); status ++; break; } } } if (count == 0) puts("PASS"); cupsFileClose(fp); } /* * Remove the test file... */ unlink("testfile.dat"); /* * Return the test status... */ return (status); }
ipp_t * /* O - Attributes */ serverLoadAttributes( const char *filename, /* I - File to load */ char **authtype, /* O - Authentication type, if any */ char **command, /* O - Command to run, if any */ char **device_uri, /* O - Device URI, if any */ char **make, /* O - Manufacturer */ char **model, /* O - Model */ char **proxy_user) /* O - Proxy user, if any */ { ipp_t *attrs; /* Attributes to return */ cups_file_t *fp; /* File */ int linenum = 0; /* Current line number */ char attr[128], /* Attribute name */ token[1024], /* Token from file */ *tokenptr; /* Pointer into token */ ipp_tag_t value; /* Current value type */ ipp_attribute_t *attrptr; /* Attribute pointer */ if ((fp = cupsFileOpen(filename, "r")) == NULL) { serverLog(SERVER_LOGLEVEL_ERROR, "Unable to open \"%s\": %s", filename, strerror(errno)); return (NULL); } attrs = ippNew(); while (get_token(fp, token, sizeof(token), &linenum) != NULL) { if (!_cups_strcasecmp(token, "ATTR")) { /* * Attribute... */ if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value tag on line %d of \"%s\".", linenum, filename); goto load_error; } if ((value = ippTagValue(token)) == IPP_TAG_ZERO) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR value tag \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if (!get_token(fp, attr, sizeof(attr), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR name on line %d of \"%s\".", linenum, filename); goto load_error; } if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value on line %d of \"%s\".", linenum, filename); goto load_error; } attrptr = NULL; switch (value) { case IPP_TAG_BOOLEAN : if (!_cups_strcasecmp(token, "true")) attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, 1); else attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, (char)atoi(token)); break; case IPP_TAG_INTEGER : case IPP_TAG_ENUM : if (!strchr(token, ',')) attrptr = ippAddInteger(attrs, IPP_TAG_PRINTER, value, attr, (int)strtol(token, &tokenptr, 0)); else { int values[100], /* Values */ num_values = 1; /* Number of values */ values[0] = (int)strtol(token, &tokenptr, 10); while (tokenptr && *tokenptr && num_values < (int)(sizeof(values) / sizeof(values[0]))) { if (*tokenptr == ',') tokenptr ++; else if (!isdigit(*tokenptr & 255) && *tokenptr != '-') break; values[num_values] = (int)strtol(tokenptr, &tokenptr, 0); num_values ++; } attrptr = ippAddIntegers(attrs, IPP_TAG_PRINTER, value, attr, num_values, values); } if (!tokenptr || *tokenptr) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad %s value \"%s\" on line %d of \"%s\".", ippTagString(value), token, linenum, filename); goto load_error; } break; case IPP_TAG_RESOLUTION : { int xres, /* X resolution */ yres; /* Y resolution */ ipp_res_t units; /* Units */ char *start, /* Start of value */ *ptr, /* Pointer into value */ *next = NULL; /* Next value */ for (start = token; start; start = next) { xres = yres = (int)strtol(start, (char **)&ptr, 10); if (ptr > start && xres > 0) { if (*ptr == 'x') yres = (int)strtol(ptr + 1, (char **)&ptr, 10); } if (ptr && (next = strchr(ptr, ',')) != NULL) *next++ = '\0'; if (ptr <= start || xres <= 0 || yres <= 0 || !ptr || (_cups_strcasecmp(ptr, "dpi") && _cups_strcasecmp(ptr, "dpc") && _cups_strcasecmp(ptr, "dpcm") && _cups_strcasecmp(ptr, "other"))) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad resolution value \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if (!_cups_strcasecmp(ptr, "dpc") || !_cups_strcasecmp(ptr, "dpcm")) units = IPP_RES_PER_CM; else units = IPP_RES_PER_INCH; if (attrptr) ippSetResolution(attrs, &attrptr, ippGetCount(attrptr), units, xres, yres); else attrptr = ippAddResolution(attrs, IPP_TAG_PRINTER, attr, units, xres, yres); } } break; case IPP_TAG_RANGE : { int lowers[4], /* Lower value */ uppers[4], /* Upper values */ num_vals; /* Number of values */ num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d", lowers + 0, uppers + 0, lowers + 1, uppers + 1, lowers + 2, uppers + 2, lowers + 3, uppers + 3); if ((num_vals & 1) || num_vals == 0) { serverLog(SERVER_LOGLEVEL_ERROR, "Bad rangeOfInteger value \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } attrptr = ippAddRanges(attrs, IPP_TAG_PRINTER, attr, num_vals / 2, lowers, uppers); } break; case IPP_TAG_BEGIN_COLLECTION : if (!strcmp(token, "{")) { ipp_t *col = get_collection(fp, filename, &linenum); /* Collection value */ if (col) { attrptr = ippAddCollection(attrs, IPP_TAG_PRINTER, attr, col); ippDelete(col); } else exit(1); } else { serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR collection value on line %d of \"%s\".", linenum, filename); goto load_error; } do { ipp_t *col; /* Collection value */ long pos = cupsFileTell(fp); /* Save position of file */ if (!get_token(fp, token, sizeof(token), &linenum)) break; if (strcmp(token, ",")) { cupsFileSeek(fp, pos); break; } if (!get_token(fp, token, sizeof(token), &linenum) || strcmp(token, "{")) { serverLog(SERVER_LOGLEVEL_ERROR, "Unexpected \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } if ((col = get_collection(fp, filename, &linenum)) == NULL) break; ippSetCollection(attrs, &attrptr, ippGetCount(attrptr), col); } while (!strcmp(token, "{")); break; case IPP_TAG_STRING : attrptr = ippAddOctetString(attrs, IPP_TAG_PRINTER, attr, token, (int)strlen(token)); break; default : serverLog(SERVER_LOGLEVEL_ERROR, "Unsupported ATTR value tag %s on line %d of \"%s\".", ippTagString(value), linenum, filename); goto load_error; case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : case IPP_TAG_TEXT : case IPP_TAG_NAME : case IPP_TAG_KEYWORD : case IPP_TAG_URI : case IPP_TAG_URISCHEME : case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : if (!strchr(token, ',')) attrptr = ippAddString(attrs, IPP_TAG_PRINTER, value, attr, NULL, token); else { /* * Multiple string values... */ int num_values; /* Number of values */ char *values[100], /* Values */ *ptr; /* Pointer to next value */ values[0] = token; num_values = 1; for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ',')) { if (ptr > token && ptr[-1] == '\\') _cups_strcpy(ptr - 1, ptr); else { *ptr++ = '\0'; values[num_values] = ptr; num_values ++; if (num_values >= (int)(sizeof(values) / sizeof(values[0]))) break; } } attrptr = ippAddStrings(attrs, IPP_TAG_PRINTER, value, attr, num_values, NULL, (const char **)values); } break; } if (!attrptr) { serverLog(SERVER_LOGLEVEL_ERROR, "Unable to add attribute on line %d of \"%s\": %s", linenum, filename, cupsLastErrorString()); goto load_error; } } else if (!_cups_strcasecmp(token, "AUTHTYPE") && authtype) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing AUTHTYPE value on line %d of \"%s\".", linenum, filename); goto load_error; } *authtype = strdup(token); } else if (!_cups_strcasecmp(token, "COMMAND") && command) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing COMMAND value on line %d of \"%s\".", linenum, filename); goto load_error; } *command = strdup(token); } else if (!_cups_strcasecmp(token, "DEVICEURI") && device_uri) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing DEVICE-URI value on line %d of \"%s\".", linenum, filename); goto load_error; } *device_uri = strdup(token); } else if (!_cups_strcasecmp(token, "MAKE") && make) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing MAKE value on line %d of \"%s\".", linenum, filename); goto load_error; } *make = strdup(token); } else if (!_cups_strcasecmp(token, "MODEL") && model) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing MODEL value on line %d of \"%s\".", linenum, filename); goto load_error; } *model = strdup(token); } else if (!_cups_strcasecmp(token, "PROXYUSER") && proxy_user) { if (!get_token(fp, token, sizeof(token), &linenum)) { serverLog(SERVER_LOGLEVEL_ERROR, "Missing PROXY-USER value on line %d of \"%s\".", linenum, filename); goto load_error; } *proxy_user = strdup(token); } else { serverLog(SERVER_LOGLEVEL_ERROR, "Unknown directive \"%s\" on line %d of \"%s\".", token, linenum, filename); goto load_error; } } cupsFileClose(fp); return (attrs); /* * If we get here something bad happened... */ load_error: cupsFileClose(fp); ippDelete(attrs); return (NULL); }