static ipp_t * /* O - Collection value */ get_collection(cups_file_t *fp, /* I - File to read from */ const char *filename, /* I - Attributes filename */ int *linenum) /* IO - Line number */ { char token[1024], /* Token from file */ attr[128]; /* Attribute name */ ipp_tag_t value; /* Current value type */ ipp_t *col = ippNew(); /* Collection value */ ipp_attribute_t *lastcol = NULL; /* Last collection attribute */ while (get_token(fp, token, sizeof(token), linenum) != NULL) { if (!strcmp(token, "}")) break; else if (!strcmp(token, "{") && lastcol) { /* * Another collection value */ ipp_t *subcol = get_collection(fp, filename, linenum); /* Collection value */ if (subcol) ippSetCollection(col, &lastcol, ippGetCount(lastcol), subcol); else goto col_error; } else if (!_cups_strcasecmp(token, "MEMBER")) { /* * Attribute... */ lastcol = NULL; if (!get_token(fp, token, sizeof(token), linenum)) { fprintf(stderr, "ippserver: Missing MEMBER value tag on line %d of \"%s\".\n", *linenum, filename); goto col_error; } if ((value = ippTagValue(token)) == IPP_TAG_ZERO) { fprintf(stderr, "ippserver: Bad MEMBER value tag \"%s\" on line %d of \"%s\".\n", token, *linenum, filename); goto col_error; } if (!get_token(fp, attr, sizeof(attr), linenum)) { fprintf(stderr, "ippserver: Missing MEMBER name on line %d of \"%s\".\n", *linenum, filename); goto col_error; } if (!get_token(fp, token, sizeof(token), linenum)) { fprintf(stderr, "ippserver: Missing MEMBER value on line %d of \"%s\".\n", *linenum, filename); goto col_error; } switch (value) { case IPP_TAG_BOOLEAN : if (!_cups_strcasecmp(token, "true")) ippAddBoolean(col, IPP_TAG_ZERO, attr, 1); else ippAddBoolean(col, IPP_TAG_ZERO, attr, (char)atoi(token)); break; case IPP_TAG_INTEGER : case IPP_TAG_ENUM : ippAddInteger(col, IPP_TAG_ZERO, value, attr, atoi(token)); break; case IPP_TAG_RESOLUTION : { int xres, /* X resolution */ yres; /* Y resolution */ char units[6]; /* Units */ if (sscanf(token, "%dx%d%5s", &xres, &yres, units) != 3 || (_cups_strcasecmp(units, "dpi") && _cups_strcasecmp(units, "dpc") && _cups_strcasecmp(units, "dpcm") && _cups_strcasecmp(units, "other"))) { fprintf(stderr, "ippserver: Bad resolution value \"%s\" on line %d of \"%s\".\n", token, *linenum, filename); goto col_error; } if (!_cups_strcasecmp(units, "dpi")) ippAddResolution(col, IPP_TAG_ZERO, attr, IPP_RES_PER_INCH, xres, yres); else if (!_cups_strcasecmp(units, "dpc") || !_cups_strcasecmp(units, "dpcm")) ippAddResolution(col, IPP_TAG_ZERO, attr, IPP_RES_PER_CM, xres, yres); else ippAddResolution(col, IPP_TAG_ZERO, attr, (ipp_res_t)0, 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) { fprintf(stderr, "ippserver: Bad rangeOfInteger value \"%s\" on line %d of \"%s\".\n", token, *linenum, filename); goto col_error; } ippAddRanges(col, IPP_TAG_ZERO, attr, num_vals / 2, lowers, uppers); } break; case IPP_TAG_BEGIN_COLLECTION : if (!strcmp(token, "{")) { ipp_t *subcol = get_collection(fp, filename, linenum); /* Collection value */ if (subcol) { lastcol = ippAddCollection(col, IPP_TAG_ZERO, attr, subcol); ippDelete(subcol); } else goto col_error; } else { fprintf(stderr, "ippserver: Bad collection value on line %d of \"%s\".\n", *linenum, filename); goto col_error; } break; case IPP_TAG_STRING : ippAddOctetString(col, IPP_TAG_ZERO, attr, token, (int)strlen(token)); break; default : if (!strchr(token, ',')) ippAddString(col, IPP_TAG_ZERO, 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, ',')) { *ptr++ = '\0'; values[num_values] = ptr; num_values ++; if (num_values >= (int)(sizeof(values) / sizeof(values[0]))) break; } ippAddStrings(col, IPP_TAG_ZERO, value, attr, num_values, NULL, (const char **)values); } break; } } } return (col); /* * If we get here there was a parse error; free memory and return. */ col_error: ippDelete(col); return (NULL); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { _ippdata_t data; /* IPP buffer */ ipp_uchar_t buffer[8192]; /* Write buffer data */ ipp_t *cols[2], /* Collections */ *size; /* media-size collection */ ipp_t *request; /* Request */ ipp_attribute_t *media_col, /* media-col attribute */ *media_size, /* media-size attribute */ *attr; /* Other attribute */ ipp_state_t state; /* State */ size_t length; /* Length of data */ cups_file_t *fp; /* File pointer */ size_t i; /* Looping var */ int status; /* Status of tests (0 = success, 1 = fail) */ #ifdef DEBUG const char *name; /* Option name */ #endif /* DEBUG */ status = 0; if (argc == 1) { /* * Test request generation code... */ printf("Create Sample Request: "); request = ippNew(); request->request.op.version[0] = 0x01; request->request.op.version[1] = 0x01; request->request.op.operation_id = IPP_OP_PRINT_JOB; request->request.op.request_id = 1; ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, "en"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/foo"); cols[0] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21590); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 27940); ippAddCollection(cols[0], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "blue"); ippAddString(cols[0], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "plain"); cols[1] = ippNew(); size = ippNew(); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "x-dimension", 21000); ippAddInteger(size, IPP_TAG_ZERO, IPP_TAG_INTEGER, "y-dimension", 29700); ippAddCollection(cols[1], IPP_TAG_JOB, "media-size", size); ippDelete(size); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-color", NULL, "plaid"); ippAddString(cols[1], IPP_TAG_JOB, IPP_TAG_KEYWORD, "media-type", NULL, "glossy"); ippAddCollections(request, IPP_TAG_JOB, "media-col", 2, (const ipp_t **)cols); ippDelete(cols[0]); ippDelete(cols[1]); length = ippLength(request); if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); status = 1; } else puts("PASS"); /* * Write test #1... */ printf("Write Sample to Memory: "); data.wused = 0; data.wsize = sizeof(buffer); data.wbuffer = buffer; while ((state = ippWriteIO(&data, (ipp_iocb_t)write_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes written.\n", (int)data.wused); status = 1; } else if (data.wused != sizeof(collection)) { printf("FAIL - wrote %d bytes, expected %d bytes!\n", (int)data.wused, (int)sizeof(collection)); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else if (memcmp(data.wbuffer, collection, data.wused)) { for (i = 0; i < data.wused; i ++) if (data.wbuffer[i] != collection[i]) break; printf("FAIL - output does not match baseline at 0x%04x!\n", (unsigned)i); hex_dump("Bytes Written", data.wbuffer, data.wused); hex_dump("Baseline", collection, sizeof(collection)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the data back in and confirm... */ printf("Read Sample from Memory: "); request = ippNew(); data.rpos = 0; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != data.wused) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)data.wused); print_attributes(request, 8); status = 1; } else if (length != sizeof(collection)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(collection)); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(media-col): ", stdout); if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_col = ippFindAttribute(request, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_col->value_tag)); status = 1; } else if (media_col->num_values != 2) { printf("FAIL (wrong count - %d)\n", media_col->num_values); status = 1; } else puts("PASS"); if (media_col) { fputs("ippFindAttribute(media-size 1): ", stdout); if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[0].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 27940) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } fputs("ippFindAttribute(media-size 2): ", stdout); if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-size", IPP_TAG_BEGIN_COLLECTION)) == NULL) { if ((media_size = ippFindAttribute(media_col->values[1].collection, "media-col", IPP_TAG_ZERO)) == NULL) puts("FAIL (not found)"); else printf("FAIL (wrong type - %s)\n", ippTagString(media_size->value_tag)); status = 1; } else { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "x-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing x-dimension)"); else printf("FAIL (wrong type for x-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", attr->values[0].integer); status = 1; } else if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_INTEGER)) == NULL) { if ((attr = ippFindAttribute(media_size->values[0].collection, "y-dimension", IPP_TAG_ZERO)) == NULL) puts("FAIL (missing y-dimension)"); else printf("FAIL (wrong type for y-dimension - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->values[0].integer != 29700) { printf("FAIL (wrong value for y-dimension - %d)\n", attr->values[0].integer); status = 1; } else puts("PASS"); } } /* * Test hierarchical find... */ fputs("ippFindAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21590) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension): ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { if (ippGetInteger(attr, 0) != 21000) { printf("FAIL (wrong value for x-dimension - %d)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); } else { puts("FAIL (not found)"); status = 1; } fputs("ippFindNextAttribute(media-col/media-size/x-dimension) again: ", stdout); if ((attr = ippFindNextAttribute(request, "media-col/media-size/x-dimension", IPP_TAG_INTEGER)) != NULL) { printf("FAIL (got %d, expected nothing)\n", ippGetInteger(attr, 0)); status = 1; } else puts("PASS"); ippDelete(request); /* * Read the mixed data and confirm we converted everything to rangeOfInteger * values... */ printf("Read Mixed integer/rangeOfInteger from Memory: "); request = ippNew(); data.rpos = 0; data.wused = sizeof(mixed); data.wsize = sizeof(mixed); data.wbuffer = mixed; while ((state = ippReadIO(&data, (ipp_iocb_t)read_cb, 1, NULL, request)) != IPP_STATE_DATA) if (state == IPP_STATE_ERROR) break; length = ippLength(request); if (state != IPP_STATE_DATA) { printf("FAIL - %d bytes read.\n", (int)data.rpos); status = 1; } else if (data.rpos != sizeof(mixed)) { printf("FAIL - read %d bytes, expected %d bytes!\n", (int)data.rpos, (int)sizeof(mixed)); print_attributes(request, 8); status = 1; } else if (length != (sizeof(mixed) + 4)) { printf("FAIL - wrong ippLength(), %d instead of %d bytes!\n", (int)length, (int)sizeof(mixed) + 4); print_attributes(request, 8); status = 1; } else puts("PASS"); fputs("ippFindAttribute(notify-lease-duration-supported): ", stdout); if ((attr = ippFindAttribute(request, "notify-lease-duration-supported", IPP_TAG_ZERO)) == NULL) { puts("FAIL (not found)"); status = 1; } else if (attr->value_tag != IPP_TAG_RANGE) { printf("FAIL (wrong type - %s)\n", ippTagString(attr->value_tag)); status = 1; } else if (attr->num_values != 2) { printf("FAIL (wrong count - %d)\n", attr->num_values); status = 1; } else if (attr->values[0].range.lower != 1 || attr->values[0].range.upper != 1 || attr->values[1].range.lower != 16 || attr->values[1].range.upper != 32) { printf("FAIL (wrong values - %d,%d and %d,%d)\n", attr->values[0].range.lower, attr->values[0].range.upper, attr->values[1].range.lower, attr->values[1].range.upper); status = 1; } else puts("PASS"); ippDelete(request); #ifdef DEBUG /* * Test that private option array is sorted... */ fputs("_ippCheckOptions: ", stdout); if ((name = _ippCheckOptions()) == NULL) puts("PASS"); else { printf("FAIL (\"%s\" out of order)\n", name); status = 1; } #endif /* DEBUG */ /* * Test _ippFindOption() private API... */ fputs("_ippFindOption(\"printer-type\"): ", stdout); if (_ippFindOption("printer-type")) puts("PASS"); else { puts("FAIL"); status = 1; } /* * Summarize... */ putchar('\n'); if (status) puts("Core IPP tests failed."); else puts("Core IPP tests passed."); } else { /* * Read IPP files... */ for (i = 1; i < (size_t)argc; i ++) { if ((fp = cupsFileOpen(argv[i], "r")) == NULL) { printf("Unable to open \"%s\" - %s\n", argv[i], strerror(errno)); status = 1; continue; } request = ippNew(); while ((state = ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, request)) == IPP_STATE_ATTRIBUTE); if (state != IPP_STATE_DATA) { printf("Error reading IPP message from \"%s\"!\n", argv[i]); status = 1; } else { printf("\n%s:\n", argv[i]); print_attributes(request, 4); } ippDelete(request); cupsFileClose(fp); } } 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); }