static void cgi_puts(const char *s, /* I - String to output */ FILE *out) /* I - Output file */ { while (*s) { if (*s == '<') { /* * Pass <A HREF="url"> and </A>, otherwise quote it... */ if (!_cups_strncasecmp(s, "<A HREF=\"", 9)) { fputs("<A HREF=\"", out); s += 9; while (*s && *s != '\"') { if (*s == '&') fputs("&", out); else putc(*s, out); s ++; } if (*s) s ++; fputs("\">", out); } else if (!_cups_strncasecmp(s, "</A>", 4)) { fputs("</A>", out); s += 3; } else fputs("<", out); } else if (*s == '>') fputs(">", out); else if (*s == '\"') fputs(""", out); else if (*s == '\'') fputs("'", out); else if (*s == '&') fputs("&", out); else putc(*s, out); s ++; } }
static int /* O - 1 for YES or AUTOMATIC, 0 for NO */ get_hostconfig(const char *name) /* I - Name of service */ { cups_file_t *fp; /* Hostconfig file */ char line[1024], /* Line from file */ *ptr; /* Pointer to value */ int state = 1; /* State of service */ /* * Try opening the /etc/hostconfig file; if we can't open it, assume that * the service is enabled/auto. */ if ((fp = cupsFileOpen("/etc/hostconfig", "r")) != NULL) { /* * Read lines from the file until we find the service... */ while (cupsFileGets(fp, line, sizeof(line))) { if (line[0] == '#' || (ptr = strchr(line, '=')) == NULL) continue; *ptr++ = '\0'; if (!_cups_strcasecmp(line, name)) { /* * Found the service, see if it is set to "-NO-"... */ if (!_cups_strncasecmp(ptr, "-NO-", 4)) state = 0; break; } } cupsFileClose(fp); } return (state); }
ppd_choice_t * /* O - Choice pointer or @code NULL@ */ ppdFindChoice(ppd_option_t *o, /* I - Pointer to option */ const char *choice) /* I - Name of choice */ { int i; /* Looping var */ ppd_choice_t *c; /* Current choice */ if (!o || !choice) return (NULL); if (choice[0] == '{' || !_cups_strncasecmp(choice, "Custom.", 7)) choice = "Custom"; for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) if (!_cups_strcasecmp(c->choice, choice)) return (c); return (NULL); }
int /* O - 0 on success, -1 on error */ cupsDoAuthentication( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ const char *method, /* I - Request method ("GET", "POST", "PUT") */ const char *resource) /* I - Resource path */ { const char *password, /* Password string */ *www_auth; /* WWW-Authenticate header */ char prompt[1024], /* Prompt for user */ realm[HTTP_MAX_VALUE], /* realm="xyz" string */ nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */ int localauth; /* Local authentication result */ _cups_globals_t *cg; /* Global data */ DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")", http, method, resource)); if (!http) http = _cupsConnect(); if (!http || !method || !resource) return (-1); DEBUG_printf(("2cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"", http->digest_tries, http->userpass)); DEBUG_printf(("2cupsDoAuthentication: WWW-Authenticate=\"%s\"", httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE))); /* * Clear the current authentication string... */ httpSetAuthString(http, NULL, NULL); /* * See if we can do local authentication... */ if (http->digest_tries < 3) { if ((localauth = cups_local_auth(http)) == 0) { DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"", http->authstring)); if (http->status == HTTP_STATUS_UNAUTHORIZED) http->digest_tries ++; return (0); } else if (localauth == -1) { http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); /* Error or canceled */ } } /* * Nope, see if we should retry the current username:password... */ www_auth = http->fields[HTTP_FIELD_WWW_AUTHENTICATE]; if ((http->digest_tries > 1 || !http->userpass[0]) && (!_cups_strncasecmp(www_auth, "Basic", 5) || !_cups_strncasecmp(www_auth, "Digest", 6))) { /* * Nope - get a new password from the user... */ char default_username[HTTP_MAX_VALUE]; /* Default username */ cg = _cupsGlobals(); if (!cg->lang_default) cg->lang_default = cupsLangDefault(); if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username", default_username)) cupsSetUser(default_username); snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->hostname[0] == '/' ? "localhost" : http->hostname); http->digest_tries = _cups_strncasecmp(www_auth, "Digest", 6) != 0; http->userpass[0] = '\0'; if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) { http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(), password); } else if (http->status == HTTP_STATUS_UNAUTHORIZED) http->digest_tries ++; if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3) { DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)", http->digest_tries)); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } /* * Got a password; encode it for the server... */ #ifdef HAVE_GSSAPI if (!_cups_strncasecmp(www_auth, "Negotiate", 9)) { /* * Kerberos authentication... */ if (_cupsSetNegotiateAuthString(http, method, resource)) { http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } } else #endif /* HAVE_GSSAPI */ if (!_cups_strncasecmp(www_auth, "Basic", 5)) { /* * Basic authentication... */ char encode[256]; /* Base64 buffer */ httpEncode64_2(encode, sizeof(encode), http->userpass, (int)strlen(http->userpass)); httpSetAuthString(http, "Basic", encode); } else if (!_cups_strncasecmp(www_auth, "Digest", 6)) { /* * Digest authentication... */ char encode[33], /* MD5 buffer */ digest[1024]; /* Digest auth data */ httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode); httpMD5Final(nonce, method, resource, encode); snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", " "response=\"%s\"", cupsUser(), realm, nonce, resource, encode); httpSetAuthString(http, "Digest", digest); } else { DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", www_auth)); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring)); return (0); }
static int /* O - 0 if available */ /* 1 if not available */ /* -1 error */ cups_local_auth(http_t *http) /* I - HTTP connection to server */ { #if defined(WIN32) || defined(__EMX__) /* * Currently WIN32 and OS-2 do not support the CUPS server... */ return (1); #else int pid; /* Current process ID */ FILE *fp; /* Certificate file */ char trc[16], /* Try Root Certificate parameter */ filename[1024]; /* Certificate filename */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ # if defined(HAVE_AUTHORIZATION_H) OSStatus status; /* Status */ AuthorizationItem auth_right; /* Authorization right */ AuthorizationRights auth_rights; /* Authorization rights */ AuthorizationFlags auth_flags; /* Authorization flags */ AuthorizationExternalForm auth_extrn; /* Authorization ref external */ char auth_key[1024]; /* Buffer */ char buffer[1024]; /* Buffer */ # endif /* HAVE_AUTHORIZATION_H */ DEBUG_printf(("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"", http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname)); /* * See if we are accessing localhost... */ if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0) { DEBUG_puts("8cups_local_auth: Not a local connection!"); return (1); } # if defined(HAVE_AUTHORIZATION_H) /* * Delete any previous authorization reference... */ if (http->auth_ref) { AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults); http->auth_ref = NULL; } if (!getenv("GATEWAY_INTERFACE") && httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key))) { status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref); if (status != errAuthorizationSuccess) { DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)", (int)status, cssmErrorString(status))); return (-1); } auth_right.name = auth_key; auth_right.valueLength = 0; auth_right.value = NULL; auth_right.flags = 0; auth_rights.count = 1; auth_rights.items = &auth_right; auth_flags = kAuthorizationFlagDefaults | kAuthorizationFlagPreAuthorize | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; status = AuthorizationCopyRights(http->auth_ref, &auth_rights, kAuthorizationEmptyEnvironment, auth_flags, NULL); if (status == errAuthorizationSuccess) status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn); if (status == errAuthorizationSuccess) { /* * Set the authorization string and return... */ httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn, sizeof(auth_extrn)); httpSetAuthString(http, "AuthRef", buffer); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } else if (status == errAuthorizationCanceled) return (-1); DEBUG_printf(("9cups_local_auth: AuthorizationCopyRights() returned %d (%s)", (int)status, cssmErrorString(status))); /* * Fall through to try certificates... */ } # endif /* HAVE_AUTHORIZATION_H */ # if defined(SO_PEERCRED) && defined(AF_LOCAL) /* * See if we can authenticate using the peer credentials provided over a * domain socket; if so, specify "PeerCred username" as the authentication * information... */ if ( # ifdef HAVE_GSSAPI _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) && # endif /* HAVE_GSSAPI */ # ifdef HAVE_AUTHORIZATION_H !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key)) && # endif /* HAVE_AUTHORIZATION_H */ http->hostaddr->addr.sa_family == AF_LOCAL && !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */ { /* * Verify that the current cupsUser() matches the current UID... */ struct passwd *pwd; /* Password information */ const char *username; /* Current username */ username = cupsUser(); if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid()) { httpSetAuthString(http, "PeerCred", username); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } } # endif /* SO_PEERCRED && AF_LOCAL */ /* * Try opening a certificate file for this PID. If that fails, * try the root certificate... */ pid = getpid(); snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid); if ((fp = fopen(filename, "r")) == NULL && pid > 0) { /* * No certificate for this PID; see if we can get the root certificate... */ DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s", filename, strerror(errno))); # ifdef HAVE_GSSAPI if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) { /* * Kerberos required, don't try the root certificate... */ return (1); } # endif /* HAVE_GSSAPI */ # ifdef HAVE_AUTHORIZATION_H if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key))) { /* * Don't use the root certificate as a replacement for an authkey... */ return (1); } # endif /* HAVE_AUTHORIZATION_H */ if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc, sizeof(trc))) { /* * Scheduler doesn't want us to use the root certificate... */ return (1); } snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir); fp = fopen(filename, "r"); } if (fp) { /* * Read the certificate from the file... */ char certificate[33], /* Certificate string */ *certptr; /* Pointer to certificate string */ certptr = fgets(certificate, sizeof(certificate), fp); fclose(fp); if (certptr) { /* * Set the authorization string and return... */ httpSetAuthString(http, "Local", certificate); DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"", http->authstring)); return (0); } } return (1); #endif /* WIN32 || __EMX__ */ }
static cups_array_t * /* O - Array of active constraints */ ppd_test_constraints( ppd_file_t *ppd, /* I - PPD file */ const char *option, /* I - Current option */ const char *choice, /* I - Current choice */ int num_options, /* I - Number of additional options */ cups_option_t *options, /* I - Additional options */ int which) /* I - Which constraints to test */ { int i; /* Looping var */ _ppd_cups_uiconsts_t *consts; /* Current constraints */ _ppd_cups_uiconst_t *constptr; /* Current constraint */ ppd_choice_t key, /* Search key */ *marked; /* Marked choice */ cups_array_t *active = NULL; /* Active constraints */ const char *value, /* Current value */ *firstvalue; /* AP_FIRSTPAGE_Keyword value */ char firstpage[255]; /* AP_FIRSTPAGE_Keyword string */ DEBUG_printf(("7ppd_test_constraints(ppd=%p, option=\"%s\", choice=\"%s\", " "num_options=%d, options=%p, which=%d)", ppd, option, choice, num_options, options, which)); if (!ppd->cups_uiconstraints) ppd_load_constraints(ppd); DEBUG_printf(("9ppd_test_constraints: %d constraints!", cupsArrayCount(ppd->cups_uiconstraints))); cupsArraySave(ppd->marked); for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(ppd->cups_uiconstraints); consts; consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(ppd->cups_uiconstraints)) { DEBUG_printf(("9ppd_test_constraints: installable=%d, resolver=\"%s\", " "num_constraints=%d option1=\"%s\", choice1=\"%s\", " "option2=\"%s\", choice2=\"%s\", ...", consts->installable, consts->resolver, consts->num_constraints, consts->constraints[0].option->keyword, consts->constraints[0].choice ? consts->constraints[0].choice->choice : "", consts->constraints[1].option->keyword, consts->constraints[1].choice ? consts->constraints[1].choice->choice : "")); if (consts->installable && which < _PPD_INSTALLABLE_CONSTRAINTS) continue; /* Skip installable option constraint */ if (!consts->installable && which == _PPD_INSTALLABLE_CONSTRAINTS) continue; /* Skip non-installable option constraint */ if (which == _PPD_OPTION_CONSTRAINTS && option) { /* * Skip constraints that do not involve the current option... */ for (i = consts->num_constraints, constptr = consts->constraints; i > 0; i --, constptr ++) { if (!_cups_strcasecmp(constptr->option->keyword, option)) break; if (!_cups_strncasecmp(option, "AP_FIRSTPAGE_", 13) && !_cups_strcasecmp(constptr->option->keyword, option + 13)) break; } if (!i) continue; } DEBUG_puts("9ppd_test_constraints: Testing..."); for (i = consts->num_constraints, constptr = consts->constraints; i > 0; i --, constptr ++) { DEBUG_printf(("9ppd_test_constraints: %s=%s?", constptr->option->keyword, constptr->choice ? constptr->choice->choice : "")); if (constptr->choice && (!_cups_strcasecmp(constptr->option->keyword, "PageSize") || !_cups_strcasecmp(constptr->option->keyword, "PageRegion"))) { /* * PageSize and PageRegion are used depending on the selected input slot * and manual feed mode. Validate against the selected page size instead * of an individual option... */ if (option && choice && (!_cups_strcasecmp(option, "PageSize") || !_cups_strcasecmp(option, "PageRegion"))) { value = choice; } else if ((value = cupsGetOption("PageSize", num_options, options)) == NULL) if ((value = cupsGetOption("PageRegion", num_options, options)) == NULL) if ((value = cupsGetOption("media", num_options, options)) == NULL) { ppd_size_t *size = ppdPageSize(ppd, NULL); if (size) value = size->name; } if (value && !_cups_strncasecmp(value, "Custom.", 7)) value = "Custom"; if (option && choice && (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") || !_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion"))) { firstvalue = choice; } else if ((firstvalue = cupsGetOption("AP_FIRSTPAGE_PageSize", num_options, options)) == NULL) firstvalue = cupsGetOption("AP_FIRSTPAGE_PageRegion", num_options, options); if (firstvalue && !_cups_strncasecmp(firstvalue, "Custom.", 7)) firstvalue = "Custom"; if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) && (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice))) { DEBUG_puts("9ppd_test_constraints: NO"); break; } } else if (constptr->choice) { /* * Compare against the constrained choice... */ if (option && choice && !_cups_strcasecmp(option, constptr->option->keyword)) { if (!_cups_strncasecmp(choice, "Custom.", 7)) value = "Custom"; else value = choice; } else if ((value = cupsGetOption(constptr->option->keyword, num_options, options)) != NULL) { if (!_cups_strncasecmp(value, "Custom.", 7)) value = "Custom"; } else if (constptr->choice->marked) value = constptr->choice->choice; else value = NULL; /* * Now check AP_FIRSTPAGE_option... */ snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", constptr->option->keyword); if (option && choice && !_cups_strcasecmp(option, firstpage)) { if (!_cups_strncasecmp(choice, "Custom.", 7)) firstvalue = "Custom"; else firstvalue = choice; } else if ((firstvalue = cupsGetOption(firstpage, num_options, options)) != NULL) { if (!_cups_strncasecmp(firstvalue, "Custom.", 7)) firstvalue = "Custom"; } else firstvalue = NULL; DEBUG_printf(("9ppd_test_constraints: value=%s, firstvalue=%s", value, firstvalue)); if ((!value || _cups_strcasecmp(value, constptr->choice->choice)) && (!firstvalue || _cups_strcasecmp(firstvalue, constptr->choice->choice))) { DEBUG_puts("9ppd_test_constraints: NO"); break; } } else if (option && choice && !_cups_strcasecmp(option, constptr->option->keyword)) { if (!_cups_strcasecmp(choice, "None") || !_cups_strcasecmp(choice, "Off") || !_cups_strcasecmp(choice, "False")) { DEBUG_puts("9ppd_test_constraints: NO"); break; } } else if ((value = cupsGetOption(constptr->option->keyword, num_options, options)) != NULL) { if (!_cups_strcasecmp(value, "None") || !_cups_strcasecmp(value, "Off") || !_cups_strcasecmp(value, "False")) { DEBUG_puts("9ppd_test_constraints: NO"); break; } } else { key.option = constptr->option; if ((marked = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) == NULL || (!_cups_strcasecmp(marked->choice, "None") || !_cups_strcasecmp(marked->choice, "Off") || !_cups_strcasecmp(marked->choice, "False"))) { DEBUG_puts("9ppd_test_constraints: NO"); break; } } } if (i <= 0) { if (!active) active = cupsArrayNew(NULL, NULL); cupsArrayAdd(active, consts); DEBUG_puts("9ppd_test_constraints: Added..."); } } cupsArrayRestore(ppd->marked); DEBUG_printf(("8ppd_test_constraints: Found %d active constraints!", cupsArrayCount(active))); return (active); }
int /* O - Exit status */ print_device(const char *uri, /* I - Device URI */ const char *hostname, /* I - Hostname/manufacturer */ const char *resource, /* I - Resource/modelname */ char *options, /* I - Device options/serial number */ int print_fd, /* I - File descriptor to print */ int copies, /* I - Copies to print */ int argc, /* I - Number of command-line arguments (6 or 7) */ char *argv[]) /* I - Command-line arguments */ { int use_bc; /* Use backchannel path? */ int device_fd; /* USB device */ ssize_t tbytes; /* Total number of bytes written */ struct termios opts; /* Parallel port options */ (void)argc; (void)argv; /* * Open the USB port device... */ fputs("STATE: +connecting-to-device\n", stderr); do { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) /* * *BSD's ulpt driver currently does not support the * back-channel, incorrectly returns data ready on a select(), * and locks up on read()... */ use_bc = 0; #elif defined(__sun) /* * CUPS STR #3028: Solaris' usbprn driver apparently does not support * select() or poll(), so we can't support backchannel... */ use_bc = 0; #else /* * Disable backchannel data when printing to Brother, Canon, or * Minolta USB printers - apparently these printers will return * the IEEE-1284 device ID over and over and over when they get * a read request... */ use_bc = _cups_strcasecmp(hostname, "Brother") && _cups_strcasecmp(hostname, "Canon") && _cups_strncasecmp(hostname, "Konica", 6) && _cups_strncasecmp(hostname, "Minolta", 7); #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ || __DragonFly__ */ if ((device_fd = open_device(uri, &use_bc)) == -1) { if (getenv("CLASS") != NULL) { /* * If the CLASS environment variable is set, the job was submitted * to a class and not to a specific queue. In this case, we want * to abort immediately so that the job can be requeued on the next * available printer in the class. */ _cupsLangPrintFilter(stderr, "INFO", _("Unable to contact printer, queuing on next " "printer in class.")); /* * Sleep 5 seconds to keep the job from requeuing too rapidly... */ sleep(5); return (CUPS_BACKEND_FAILED); } if (errno == EBUSY) { _cupsLangPrintFilter(stderr, "INFO", _("The printer is in use.")); sleep(10); } else if (errno == ENXIO || errno == EIO || errno == ENOENT || errno == ENODEV) { sleep(30); } else { _cupsLangPrintError("ERROR", _("Unable to open device file")); return (CUPS_BACKEND_FAILED); } } } while (device_fd < 0); fputs("STATE: -connecting-to-device\n", stderr); /* * Set any options provided... */ tcgetattr(device_fd, &opts); opts.c_lflag &= ~(unsigned)(ICANON | ECHO | ISIG); /* Raw mode */ /**** No options supported yet ****/ tcsetattr(device_fd, TCSANOW, &opts); /* * Finally, send the print file... */ tbytes = 0; while (copies > 0 && tbytes >= 0) { copies --; if (print_fd != 0) { fputs("PAGE: 1 1\n", stderr); lseek(print_fd, 0, SEEK_SET); } #ifdef __sun /* * CUPS STR #3028: Solaris' usbprn driver apparently does not support * select() or poll(), so we can't support the sidechannel either... */ tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, NULL); #else tbytes = backendRunLoop(print_fd, device_fd, -1, NULL, use_bc, 1, side_cb); #endif /* __sun */ if (print_fd != 0 && tbytes >= 0) _cupsLangPrintFilter(stderr, "INFO", _("Print file sent.")); } /* * Close the USB port and return... */ close(device_fd); return (CUPS_BACKEND_OK); }
int /* O - 0 on success, -1 on failure */ backendGetMakeModel( const char *device_id, /* O - 1284 device ID */ char *make_model, /* O - Make/model */ size_t make_model_size) /* I - Size of buffer */ { int num_values; /* Number of keys and values */ cups_option_t *values; /* Keys and values */ const char *mfg, /* Manufacturer string */ *mdl, /* Model string */ *des; /* Description string */ DEBUG_printf(("backendGetMakeModel(device_id=\"%s\", make_model=%p, make_model_size=" CUPS_LLFMT ")\n", device_id, make_model, CUPS_LLCAST make_model_size)); /* * Range check input... */ if (!device_id || !*device_id || !make_model || make_model_size < 32) { DEBUG_puts("backendGetMakeModel: Bad args!"); return (-1); } *make_model = '\0'; /* * Look for the description field... */ num_values = _cupsGet1284Values(device_id, &values); if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL) mdl = cupsGetOption("MDL", num_values, values); if (mdl) { /* * Build a make-model string from the manufacturer and model attributes... */ if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL) mfg = cupsGetOption("MFG", num_values, values); if (!mfg || !_cups_strncasecmp(mdl, mfg, strlen(mfg))) { /* * Just copy the model string, since it has the manufacturer... */ _ppdNormalizeMakeAndModel(mdl, make_model, make_model_size); } else { /* * Concatenate the make and model... */ char temp[1024]; /* Temporary make and model */ snprintf(temp, sizeof(temp), "%s %s", mfg, mdl); _ppdNormalizeMakeAndModel(temp, make_model, make_model_size); } } else if ((des = cupsGetOption("DESCRIPTION", num_values, values)) != NULL || (des = cupsGetOption("DES", num_values, values)) != NULL) { /* * Make sure the description contains something useful, since some * printer manufacturers (HP) apparently don't follow the standards * they helped to define... * * Here we require the description to be 8 or more characters in length, * containing at least one space and one letter. */ if (strlen(des) >= 8) { const char *ptr; /* Pointer into description */ int letters, /* Number of letters seen */ spaces; /* Number of spaces seen */ for (ptr = des, letters = 0, spaces = 0; *ptr; ptr ++) { if (isspace(*ptr & 255)) spaces ++; else if (isalpha(*ptr & 255)) letters ++; if (spaces && letters) break; } if (spaces && letters) _ppdNormalizeMakeAndModel(des, make_model, make_model_size); } } if (!make_model[0]) { /* * Use "Unknown" as the printer make and model... */ strlcpy(make_model, "Unknown", make_model_size); } cupsFreeOptions(num_values, values); return (0); }
_pwg_media_t * /* O - Matching size or NULL */ _pwgMediaForPPD(const char *ppd) /* I - PPD size name */ { _pwg_media_t key, /* Search key */ *size; /* Matching size */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!ppd) return (NULL); /* * Build the lookup table for PWG names as needed... */ if (!cg->ppd_size_lut) { int i; /* Looping var */ cg->ppd_size_lut = cupsArrayNew((cups_array_func_t)pwg_compare_ppd, NULL); for (i = (int)(sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0])), size = (_pwg_media_t *)cups_pwg_media; i > 0; i --, size ++) if (size->ppd) cupsArrayAdd(cg->ppd_size_lut, size); } /* * Lookup the name... */ key.ppd = ppd; if ((size = (_pwg_media_t *)cupsArrayFind(cg->ppd_size_lut, &key)) == NULL) { /* * See if the name is of the form: * * [Custom.]WIDTHxLENGTH[.FullBleed] - Size in points/inches [borderless] * [Custom.]WIDTHxLENGTHcm[.FullBleed] - Size in centimeters [borderless] * [Custom.]WIDTHxLENGTHft[.FullBleed] - Size in feet [borderless] * [Custom.]WIDTHxLENGTHin[.FullBleed] - Size in inches [borderless] * [Custom.]WIDTHxLENGTHm[.FullBleed] - Size in meters [borderless] * [Custom.]WIDTHxLENGTHmm[.FullBleed] - Size in millimeters [borderless] * [Custom.]WIDTHxLENGTHpt[.FullBleed] - Size in points [borderless] */ double w, l, /* Width and length of page */ factor; /* Unit scaling factor */ char *ptr; /* Pointer into name */ struct lconv *loc; /* Locale data */ int custom; /* Custom page size? */ if (!_cups_strncasecmp(ppd, "Custom.", 7)) { custom = 1; factor = 2540.0 / 72.0; ptr = (char *)ppd + 7; } else { custom = 0; factor = 2540.0; ptr = (char *)ppd; } //loc = localeconv(); w = _cupsStrScand(ptr, &ptr, loc); if (ptr && ptr > ppd && *ptr == 'x') { l = _cupsStrScand(ptr + 1, &ptr, loc); if (ptr && (!*ptr || !_cups_strcasecmp(ptr, "FullBleed") || !_cups_strcasecmp(ptr, ".FullBleed") || !_cups_strcasecmp(ptr, "cm") || !_cups_strcasecmp(ptr, "cm.FullBleed") || !_cups_strcasecmp(ptr, "ft") || !_cups_strcasecmp(ptr, "ft.FullBleed") || !_cups_strcasecmp(ptr, "in") || !_cups_strcasecmp(ptr, "in.FullBleed") || !_cups_strcasecmp(ptr, "m") || !_cups_strcasecmp(ptr, "m.FullBleed") || !_cups_strcasecmp(ptr, "mm") || !_cups_strcasecmp(ptr, "mm.FullBleed") || !_cups_strcasecmp(ptr, "pt") || !_cups_strcasecmp(ptr, "pt.FullBleed"))) { size = &(cg->pwg_media); if (!_cups_strncasecmp(ptr, "cm", 2)) factor = 1000.0; else if (!_cups_strncasecmp(ptr, "ft", 2)) factor = 2540.0 * 12.0; else if (!_cups_strncasecmp(ptr, "in", 2)) factor = 2540.0; else if (!_cups_strncasecmp(ptr, "mm", 2)) factor = 100.0; else if (*ptr == 'm' || *ptr == 'M') factor = 100000.0; else if (!_cups_strncasecmp(ptr, "pt", 2)) factor = 2540.0 / 72.0; /* * Not a standard size; convert it to a PWG custom name of the form: * * [oe|om]_WIDTHxHEIGHTuu_WIDTHxHEIGHTuu */ size->width = (int)(w * factor); size->length = (int)(l * factor); size->pwg = cg->pwg_name; _pwgGenerateSize(cg->pwg_name, sizeof(cg->pwg_name), custom ? "custom" : NULL, custom ? ppd + 7 : NULL, size->width, size->length); } } } return (size); }
pwg_media_t * /* O - Matching size or NULL */ pwgMediaForPPD(const char *ppd) /* I - PPD size name */ { pwg_media_t key, /* Search key */ *size; /* Matching size */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!ppd) return (NULL); /* * Build the lookup table for PWG names as needed... */ if (!cg->ppd_size_lut) { int i; /* Looping var */ cg->ppd_size_lut = cupsArrayNew((cups_array_func_t)pwg_compare_ppd, NULL); for (i = (int)(sizeof(cups_pwg_media) / sizeof(cups_pwg_media[0])), size = (pwg_media_t *)cups_pwg_media; i > 0; i --, size ++) if (size->ppd) cupsArrayAdd(cg->ppd_size_lut, size); } /* * Lookup the name... */ key.ppd = ppd; if ((size = (pwg_media_t *)cupsArrayFind(cg->ppd_size_lut, &key)) == NULL) { /* * See if the name is of the form: * * [Custom.]WIDTHxLENGTH[.FullBleed] - Size in points/inches [borderless] * [Custom.]WIDTHxLENGTHcm[.FullBleed] - Size in centimeters [borderless] * [Custom.]WIDTHxLENGTHft[.FullBleed] - Size in feet [borderless] * [Custom.]WIDTHxLENGTHin[.FullBleed] - Size in inches [borderless] * [Custom.]WIDTHxLENGTHm[.FullBleed] - Size in meters [borderless] * [Custom.]WIDTHxLENGTHmm[.FullBleed] - Size in millimeters [borderless] * [Custom.]WIDTHxLENGTHpt[.FullBleed] - Size in points [borderless] */ int w, l, /* Width and length of page */ numer, /* Unit scaling factor */ denom; /* ... */ char *ptr; /* Pointer into name */ const char *units; /* Pointer to units */ int custom; /* Custom page size? */ if (!_cups_strncasecmp(ppd, "Custom.", 7)) { custom = 1; numer = 2540; denom = 72; ptr = (char *)ppd + 7; } else { custom = 0; numer = 2540; denom = 1; ptr = (char *)ppd; } /* * Find any units in the size... */ units = strchr(ptr, '.'); while (units && isdigit(units[1] & 255)) units = strchr(units + 1, '.'); if (units) units -= 2; else units = ptr + strlen(ptr) - 2; if (units > ptr) { if (isdigit(*units & 255) || *units == '.') units ++; if (!_cups_strncasecmp(units, "cm", 2)) { numer = 1000; denom = 1; } else if (!_cups_strncasecmp(units, "ft", 2)) { numer = 2540 * 12; denom = 1; } else if (!_cups_strncasecmp(units, "in", 2)) { numer = 2540; denom = 1; } else if (!_cups_strncasecmp(units, "mm", 2)) { numer = 100; denom = 1; } else if (*units == 'm' || *units == 'M') { numer = 100000; denom = 1; } else if (!_cups_strncasecmp(units, "pt", 2)) { numer = 2540; denom = 72; } } w = pwg_scan_measurement(ptr, &ptr, numer, denom); if (ptr && ptr > ppd && *ptr == 'x') { l = pwg_scan_measurement(ptr + 1, &ptr, numer, denom); if (ptr) { /* * Not a standard size; convert it to a PWG custom name of the form: * * [oe|om]_WIDTHxHEIGHTuu_WIDTHxHEIGHTuu */ char wstr[32], lstr[32]; /* Width and length as strings */ size = &(cg->pwg_media); size->width = w; size->length = l; size->pwg = cg->pwg_name; pwgFormatSizeName(cg->pwg_name, sizeof(cg->pwg_name), custom ? "custom" : NULL, custom ? ppd + 7 : NULL, size->width, size->length, NULL); if ((w % 635) == 0 && (l % 635) == 0) snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%s", pwg_format_inches(wstr, sizeof(wstr), w), pwg_format_inches(lstr, sizeof(lstr), l)); else snprintf(cg->ppd_name, sizeof(cg->ppd_name), "%sx%smm", pwg_format_millimeters(wstr, sizeof(wstr), w), pwg_format_millimeters(lstr, sizeof(lstr), l)); size->ppd = cg->ppd_name; } } } return (size); }
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 - 1 if form data was read */ cgi_initialize_multipart( const char *boundary) /* I - Boundary string */ { char line[10240], /* MIME header line */ name[1024], /* Form variable name */ filename[1024], /* Form filename */ mimetype[1024], /* MIME media type */ bstring[256], /* Boundary string to look for */ *ptr, /* Pointer into name/filename */ *end; /* End of buffer */ int ch, /* Character from file */ fd; /* Temporary file descriptor */ size_t blen; /* Length of boundary string */ DEBUG_printf(("cgi_initialize_multipart(boundary=\"%s\")\n", boundary)); /* * Read multipart form data until we run out... */ name[0] = '\0'; filename[0] = '\0'; mimetype[0] = '\0'; snprintf(bstring, sizeof(bstring), "\r\n--%s", boundary); blen = strlen(bstring); while (fgets(line, sizeof(line), stdin)) { if (!strcmp(line, "\r\n")) { /* * End of headers, grab value... */ if (filename[0]) { /* * Read an embedded file... */ if (form_file) { /* * Remove previous file... */ cgi_unlink_file(); } /* * Allocate memory for the new file... */ if ((form_file = calloc(1, sizeof(cgi_file_t))) == NULL) return (0); form_file->name = strdup(name); form_file->filename = strdup(filename); form_file->mimetype = strdup(mimetype); fd = cupsTempFd(form_file->tempfile, sizeof(form_file->tempfile)); if (fd < 0) return (0); atexit(cgi_unlink_file); /* * Copy file data to the temp file... */ ptr = line; while ((ch = getchar()) != EOF) { *ptr++ = (char)ch; if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; } if ((ptr - line - (int)blen) >= 8192) { /* * Write out the first 8k of the buffer... */ write(fd, line, 8192); memmove(line, line + 8192, (size_t)(ptr - line - 8192)); ptr -= 8192; } } /* * Write the rest of the data and close the temp file... */ if (ptr > line) write(fd, line, (size_t)(ptr - line)); close(fd); } else { /* * Just get a form variable; the current code only handles * form values up to 10k in size... */ ptr = line; end = line + sizeof(line) - 1; while ((ch = getchar()) != EOF) { if (ptr < end) *ptr++ = (char)ch; if ((size_t)(ptr - line) >= blen && !memcmp(ptr - blen, bstring, blen)) { ptr -= blen; break; } } *ptr = '\0'; /* * Set the form variable... */ if ((ptr = strrchr(name, '-')) != NULL && isdigit(ptr[1] & 255)) { /* * Set a specific index in the array... */ *ptr++ = '\0'; if (line[0]) cgiSetArray(name, atoi(ptr) - 1, line); } else if (cgiGetVariable(name)) { /* * Add another element in the array... */ cgiSetArray(name, cgiGetSize(name), line); } else { /* * Just set the line... */ cgiSetVariable(name, line); } } /* * Read the rest of the current line... */ fgets(line, sizeof(line), stdin); /* * Clear the state vars... */ name[0] = '\0'; filename[0] = '\0'; mimetype[0] = '\0'; } else if (!_cups_strncasecmp(line, "Content-Disposition:", 20)) { if ((ptr = strstr(line + 20, " name=\"")) != NULL) { strlcpy(name, ptr + 7, sizeof(name)); if ((ptr = strchr(name, '\"')) != NULL) *ptr = '\0'; } if ((ptr = strstr(line + 20, " filename=\"")) != NULL) { strlcpy(filename, ptr + 11, sizeof(filename)); if ((ptr = strchr(filename, '\"')) != NULL) *ptr = '\0'; } } else if (!_cups_strncasecmp(line, "Content-Type:", 13)) { for (ptr = line + 13; isspace(*ptr & 255); ptr ++); strlcpy(mimetype, ptr, sizeof(mimetype)); for (ptr = mimetype + strlen(mimetype) - 1; ptr > mimetype && isspace(*ptr & 255); *ptr-- = '\0'); } } /* * Return 1 for "form data found"... */ return (1); }
void * /* O - Search context */ cgiCompileSearch(const char *query) /* I - Query string */ { regex_t *re; /* Regular expression */ char *s, /* Regular expression string */ *sptr, /* Pointer into RE string */ *sword; /* Pointer to start of word */ int slen; /* Allocated size of RE string */ const char *qptr, /* Pointer into query string */ *qend; /* End of current word */ const char *prefix; /* Prefix to add to next word */ int quoted; /* Word is quoted */ int wlen; /* Word length */ char *lword; /* Last word in query */ DEBUG_printf(("cgiCompileSearch(query=\"%s\")\n", query)); /* * Range check input... */ if (!query) return (NULL); /* * Allocate a regular expression storage structure... */ if ((re = (regex_t *)calloc(1, sizeof(regex_t))) == NULL) return (NULL); /* * Allocate a buffer to hold the regular expression string, starting * at 1024 bytes or 3 times the length of the query string, whichever * is greater. We'll expand the string as needed... */ slen = strlen(query) * 3; if (slen < 1024) slen = 1024; if ((s = (char *)malloc(slen)) == NULL) { free(re); return (NULL); } /* * Copy the query string to the regular expression, handling basic * AND and OR logic... */ prefix = ".*"; qptr = query; sptr = s; lword = NULL; while (*qptr) { /* * Skip leading whitespace... */ while (isspace(*qptr & 255)) qptr ++; if (!*qptr) break; /* * Find the end of the current word... */ if (*qptr == '\"' || *qptr == '\'') { /* * Scan quoted string... */ quoted = *qptr ++; for (qend = qptr; *qend && *qend != quoted; qend ++); if (!*qend) { /* * No closing quote, error out! */ free(s); free(re); if (lword) free(lword); return (NULL); } } else { /* * Scan whitespace-delimited string... */ quoted = 0; for (qend = qptr + 1; *qend && !isspace(*qend); qend ++); } wlen = qend - qptr; /* * Look for logic words: AND, OR */ if (wlen == 3 && !_cups_strncasecmp(qptr, "AND", 3)) { /* * Logical AND with the following text... */ if (sptr > s) prefix = ".*"; qptr = qend; } else if (wlen == 2 && !_cups_strncasecmp(qptr, "OR", 2)) { /* * Logical OR with the following text... */ if (sptr > s) prefix = ".*|.*"; qptr = qend; } else { /* * Add a search word, making sure we have enough room for the * string + RE overhead... */ wlen = (sptr - s) + 2 * 4 * wlen + 2 * strlen(prefix) + 11; if (lword) wlen += strlen(lword); if (wlen > slen) { /* * Expand the RE string buffer... */ char *temp; /* Temporary string pointer */ slen = wlen + 128; temp = (char *)realloc(s, slen); if (!temp) { free(s); free(re); if (lword) free(lword); return (NULL); } sptr = temp + (sptr - s); s = temp; } /* * Add the prefix string... */ memcpy(sptr, prefix, strlen(prefix) + 1); sptr += strlen(sptr); /* * Then quote the remaining word characters as needed for the * RE... */ sword = sptr; while (qptr < qend) { /* * Quote: ^ . [ $ ( ) | * + ? { \ */ if (strchr("^.[$()|*+?{\\", *qptr)) *sptr++ = '\\'; *sptr++ = *qptr++; } *sptr = '\0'; /* * For "word1 AND word2", add reciprocal "word2 AND word1"... */ if (!strcmp(prefix, ".*") && lword) { char *lword2; /* New "last word" */ if ((lword2 = strdup(sword)) == NULL) { free(lword); free(s); free(re); return (NULL); } memcpy(sptr, ".*|.*", 6); sptr += 5; memcpy(sptr, lword2, strlen(lword2) + 1); sptr += strlen(sptr); memcpy(sptr, ".*", 3); sptr += 2; memcpy(sptr, lword, strlen(lword) + 1); sptr += strlen(sptr); free(lword); lword = lword2; } else { if (lword) free(lword); lword = strdup(sword); } prefix = ".*|.*"; } /* * Advance to the next string... */ if (quoted) qptr ++; } if (lword) free(lword); if (sptr > s) memcpy(sptr, ".*", 3); else { /* * No query data, return NULL... */ free(s); free(re); return (NULL); } /* * Compile the regular expression... */ DEBUG_printf((" s=\"%s\"\n", s)); if (regcomp(re, s, REG_EXTENDED | REG_ICASE)) { free(re); free(s); return (NULL); } /* * Free the RE string and return the new regular expression we compiled... */ free(s); return ((void *)re); }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { help_index_t *hi, /* Help index */ *si; /* Search index */ help_node_t *n; /* Current help node */ int i; /* Looping var */ const char *query; /* Search query */ const char *cache_dir; /* CUPS_CACHEDIR environment variable */ const char *docroot; /* CUPS_DOCROOT environment variable */ const char *helpfile, /* Current help file */ *helptitle = NULL; /* Current help title */ const char *topic; /* Current topic */ char topic_data[1024]; /* Topic form data */ const char *section; /* Current section */ char filename[1024], /* Filename */ directory[1024]; /* Directory */ cups_file_t *fp; /* Help file */ char line[1024]; /* Line from file */ int printable; /* Show printable version? */ /* * Get any form variables... */ cgiInitialize(); printable = cgiGetVariable("PRINTABLE") != NULL; /* * Set the web interface section... */ cgiSetVariable("SECTION", "help"); cgiSetVariable("REFRESH_PAGE", ""); /* * Load the help index... */ if ((cache_dir = getenv("CUPS_CACHEDIR")) == NULL) cache_dir = CUPS_CACHEDIR; snprintf(filename, sizeof(filename), "%s/help.index", cache_dir); if ((docroot = getenv("CUPS_DOCROOT")) == NULL) docroot = CUPS_DOCROOT; snprintf(directory, sizeof(directory), "%s/help", docroot); fprintf(stderr, "DEBUG: helpLoadIndex(filename=\"%s\", directory=\"%s\")\n", filename, directory); hi = helpLoadIndex(filename, directory); if (!hi) { perror(filename); cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Unable to load help index."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } fprintf(stderr, "DEBUG: %d nodes in help index...\n", cupsArrayCount(hi->nodes)); /* * See if we are viewing a file... */ for (i = 0; i < argc; i ++) fprintf(stderr, "DEBUG: argv[%d]=\"%s\"\n", i, argv[i]); if ((helpfile = getenv("PATH_INFO")) != NULL) { helpfile ++; if (!*helpfile) helpfile = NULL; } if (helpfile) { /* * Verify that the help file exists and is part of the index... */ snprintf(filename, sizeof(filename), "%s/help/%s", docroot, helpfile); fprintf(stderr, "DEBUG: helpfile=\"%s\", filename=\"%s\"\n", helpfile, filename); if (access(filename, R_OK)) { perror(filename); cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Unable to access help file."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } if ((n = helpFindNode(hi, helpfile, NULL)) == NULL) { cgiStartHTML(cgiText(_("Online Help"))); cgiSetVariable("ERROR", cgiText(_("Help file not in index."))); cgiCopyTemplateLang("error.tmpl"); cgiEndHTML(); return (1); } /* * Save the page title and help file... */ helptitle = n->text; topic = n->section; /* * Send a standard page header... */ if (printable) puts("Content-Type: text/html;charset=utf-8\n"); else cgiStartHTML(n->text); } else { /* * Send a standard page header... */ cgiStartHTML(cgiText(_("Online Help"))); topic = cgiGetVariable("TOPIC"); } /* * Do a search as needed... */ if (cgiGetVariable("CLEAR")) cgiSetVariable("QUERY", ""); query = cgiGetVariable("QUERY"); si = helpSearchIndex(hi, query, topic, helpfile); cgiClearVariables(); if (query) cgiSetVariable("QUERY", query); if (topic) cgiSetVariable("TOPIC", topic); if (helpfile) cgiSetVariable("HELPFILE", helpfile); if (helptitle) cgiSetVariable("HELPTITLE", helptitle); fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n", query ? query : "(null)", topic ? topic : "(null)"); if (si) { help_node_t *nn; /* Parent node */ fprintf(stderr, "DEBUG: si=%p, si->sorted=%p, cupsArrayCount(si->sorted)=%d\n", si, si->sorted, cupsArrayCount(si->sorted)); for (i = 0, n = (help_node_t *)cupsArrayFirst(si->sorted); n; i ++, n = (help_node_t *)cupsArrayNext(si->sorted)) { if (helpfile && n->anchor) snprintf(line, sizeof(line), "#%s", n->anchor); else if (n->anchor) snprintf(line, sizeof(line), "/help/%s?QUERY=%s#%s", n->filename, query ? query : "", n->anchor); else snprintf(line, sizeof(line), "/help/%s?QUERY=%s", n->filename, query ? query : ""); cgiSetArray("QTEXT", i, n->text); cgiSetArray("QLINK", i, line); if (!helpfile && n->anchor) { nn = helpFindNode(hi, n->filename, NULL); snprintf(line, sizeof(line), "/help/%s?QUERY=%s", nn->filename, query ? query : ""); cgiSetArray("QPTEXT", i, nn->text); cgiSetArray("QPLINK", i, line); } else { cgiSetArray("QPTEXT", i, ""); cgiSetArray("QPLINK", i, ""); } fprintf(stderr, "DEBUG: [%d] = \"%s\" @ \"%s\"\n", i, n->text, line); } helpDeleteIndex(si); } /* * OK, now list the bookmarks within the index... */ for (i = 0, section = NULL, n = (help_node_t *)cupsArrayFirst(hi->sorted); n; n = (help_node_t *)cupsArrayNext(hi->sorted)) { if (n->anchor) continue; /* * Add a section link as needed... */ if (n->section && (!section || strcmp(n->section, section))) { /* * Add a link for this node... */ snprintf(line, sizeof(line), "/help/?TOPIC=%s&QUERY=%s", cgiFormEncode(topic_data, n->section, sizeof(topic_data)), query ? query : ""); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, n->section); cgiSetArray("BMINDENT", i, "0"); i ++; section = n->section; } if (!topic || strcmp(n->section, topic)) continue; /* * Add a link for this node... */ snprintf(line, sizeof(line), "/help/%s?TOPIC=%s&QUERY=%s", n->filename, cgiFormEncode(topic_data, n->section, sizeof(topic_data)), query ? query : ""); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, n->text); cgiSetArray("BMINDENT", i, "1"); i ++; if (helpfile && !strcmp(helpfile, n->filename)) { help_node_t *nn; /* Pointer to sub-node */ cupsArraySave(hi->sorted); for (nn = (help_node_t *)cupsArrayFirst(hi->sorted); nn; nn = (help_node_t *)cupsArrayNext(hi->sorted)) if (nn->anchor && !strcmp(helpfile, nn->filename)) { /* * Add a link for this node... */ snprintf(line, sizeof(line), "#%s", nn->anchor); cgiSetArray("BMLINK", i, line); cgiSetArray("BMTEXT", i, nn->text); cgiSetArray("BMINDENT", i, "2"); i ++; } cupsArrayRestore(hi->sorted); } } /* * Show the search and bookmark content... */ if (!helpfile || !printable) cgiCopyTemplateLang("help-header.tmpl"); else cgiCopyTemplateLang("help-printable.tmpl"); /* * If we are viewing a file, copy it in now... */ if (helpfile) { if ((fp = cupsFileOpen(filename, "r")) != NULL) { int inbody; /* Are we inside the body? */ inbody = 0; while (cupsFileGets(fp, line, sizeof(line))) { if (inbody) { if (!_cups_strncasecmp(line, "</BODY>", 7)) break; printf("%s\n", line); } else if (!_cups_strncasecmp(line, "<BODY", 5)) inbody = 1; } cupsFileClose(fp); } else { perror(filename); cgiSetVariable("ERROR", cgiText(_("Unable to open help file."))); cgiCopyTemplateLang("error.tmpl"); } } /* * Send a standard trailer... */ if (!printable) { cgiCopyTemplateLang("help-trailer.tmpl"); cgiEndHTML(); } else puts("</BODY>\n</HTML>"); /* * Delete the index... */ helpDeleteIndex(hi); /* * Return with no errors... */ return (0); }
int main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ http_t *http; /* Connection to server */ char *printer, /* Destination printer */ *pclass, /* Printer class name */ *val; /* Pointer to allow/deny value */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ char *file; /* New PPD file/interface script */ _cupsSetLocale(argv); http = NULL; printer = NULL; num_options = 0; options = NULL; file = NULL; for (i = 1; i < argc; i ++) if (argv[i][0] == '-') switch (argv[i][1]) { case 'c' : /* Add printer to class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to add a printer to the class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class name after \"-c\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (add_printer_to_class(http, printer, pclass)) return (1); break; case 'd' : /* Set as default destination */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer name after \"-d\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (default_printer(http, printer)) return (1); i = argc; break; case 'h' : /* Connect to host */ if (http) { httpClose(http); http = NULL; } if (argv[i][2] != '\0') cupsSetServer(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected hostname after \"-h\" " "option.")); return (1); } cupsSetServer(argv[i]); } break; case 'i' : /* Use the specified interface script */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected interface after \"-i\" " "option.")); return (1); } file = argv[i]; } break; case 'E' : /* Enable the printer */ if (printer == NULL) { #ifdef HAVE_SSL cupsSetEncryption(HTTP_ENCRYPT_REQUIRED); if (http) httpEncryption(http, HTTP_ENCRYPT_REQUIRED); #else _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), argv[0]); #endif /* HAVE_SSL */ break; } if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (enable_printer(http, printer)) return (1); break; case 'm' : /* Use the specified standard script/PPD file */ if (argv[i][2]) num_options = cupsAddOption("ppd-name", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected model after \"-m\" " "option.")); return (1); } num_options = cupsAddOption("ppd-name", argv[i], num_options, &options); } break; case 'o' : /* Set option */ if (argv[i][2]) num_options = cupsParseOptions(argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name=value after \"-o\" " "option.")); return (1); } num_options = cupsParseOptions(argv[i], num_options, &options); } break; case 'p' : /* Add/modify a printer */ if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer after \"-p\" " "option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } break; case 'r' : /* Remove printer from class */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to remove a printer from the " "class:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) pclass = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected class after \"-r\" " "option.")); return (1); } pclass = argv[i]; } if (!validate_name(pclass)) { _cupsLangPuts(stderr, _("lpadmin: Class name can only contain printable " "characters.")); return (1); } if (delete_printer_from_class(http, printer, pclass)) return (1); break; case 'R' : /* Remove option */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to delete option:\n" " You must specify a printer name " "first.")); return (1); } if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected name after \"-R\" " "option.")); return (1); } val = argv[i]; } if (delete_printer_option(http, printer, val)) return (1); break; case 'U' : /* Username */ if (argv[i][2] != '\0') cupsSetUser(argv[i] + 2); else { i ++; if (i >= argc) { _cupsLangPrintf(stderr, _("%s: Error - expected username after " "\"-U\" option."), argv[0]); return (1); } cupsSetUser(argv[i]); } break; case 'u' : /* Allow/deny users */ if (argv[i][2]) val = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected allow/deny:userlist after " "\"-u\" option.")); return (1); } val = argv[i]; } if (!_cups_strncasecmp(val, "allow:", 6)) num_options = cupsAddOption("requesting-user-name-allowed", val + 6, num_options, &options); else if (!_cups_strncasecmp(val, "deny:", 5)) num_options = cupsAddOption("requesting-user-name-denied", val + 5, num_options, &options); else { _cupsLangPrintf(stderr, _("lpadmin: Unknown allow/deny option \"%s\"."), val); return (1); } break; case 'v' : /* Set the device-uri attribute */ if (argv[i][2]) num_options = cupsAddOption("device-uri", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected device URI after \"-v\" " "option.")); return (1); } num_options = cupsAddOption("device-uri", argv[i], num_options, &options); } break; case 'x' : /* Delete a printer */ if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (argv[i][2]) printer = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected printer or class after " "\"-x\" option.")); return (1); } printer = argv[i]; } if (!validate_name(printer)) { _cupsLangPuts(stderr, _("lpadmin: Printer name can only contain " "printable characters.")); return (1); } if (delete_printer(http, printer)) return (1); i = argc; break; case 'D' : /* Set the printer-info attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-info", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected description after " "\"-D\" option.")); return (1); } num_options = cupsAddOption("printer-info", argv[i], num_options, &options); } break; case 'I' : /* Set the supported file types (ignored) */ i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected file type(s) after \"-I\" " "option.")); return (1); } _cupsLangPuts(stderr, _("lpadmin: Warning - content type list ignored.")); break; case 'L' : /* Set the printer-location attribute */ if (argv[i][2]) num_options = cupsAddOption("printer-location", argv[i] + 2, num_options, &options); else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected location after \"-L\" " "option.")); return (1); } num_options = cupsAddOption("printer-location", argv[i], num_options, &options); } break; case 'P' : /* Use the specified PPD file */ if (argv[i][2]) file = argv[i] + 2; else { i ++; if (i >= argc) { _cupsLangPuts(stderr, _("lpadmin: Expected PPD after \"-P\" option.")); return (1); } file = argv[i]; } break; default : _cupsLangPrintf(stderr, _("lpadmin: Unknown option \"%c\"."), argv[i][1]); return (1); } else { _cupsLangPrintf(stderr, _("lpadmin: Unknown argument \"%s\"."), argv[i]); return (1); } /* * Set options as needed... */ if (num_options || file) { if (!http) { http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption()); if (http == NULL) { _cupsLangPrintf(stderr, _("lpadmin: Unable to connect to server: %s"), strerror(errno)); return (1); } } if (printer == NULL) { _cupsLangPuts(stderr, _("lpadmin: Unable to set the printer options:\n" " You must specify a printer name first.")); return (1); } if (set_printer_options(http, printer, num_options, options, file)) return (1); } if (printer == NULL) { _cupsLangPuts(stdout, _("Usage:\n" "\n" " lpadmin [-h server] -d destination\n" " lpadmin [-h server] -x destination\n" " lpadmin [-h server] -p printer [-c add-class] " "[-i interface] [-m model]\n" " [-r remove-class] [-v device] " "[-D description]\n" " [-P ppd-file] [-o name=value]\n" " [-u allow:user,user] " "[-u deny:user,user]")); } if (http) httpClose(http); return (0); }
int /* O - 1 on success, 0 on failure */ cupsAdminGetServerSettings( http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */ int *num_settings, /* O - Number of settings */ cups_option_t **settings) /* O - Settings */ { int i; /* Looping var */ cups_file_t *cupsd; /* cupsd.conf file */ char cupsdconf[1024]; /* cupsd.conf filename */ int remote; /* Remote cupsd.conf file? */ http_status_t status; /* Status of getting cupsd.conf */ char line[1024], /* Line from cupsd.conf file */ *value; /* Value on line */ cups_option_t *setting; /* Current setting */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ /* * Range check input... */ if (!http) { /* * See if we are connected to the same server... */ if (cg->http) { /* * Compare the connection hostname, port, and encryption settings to * the cached defaults; these were initialized the first time we * connected... */ if (strcmp(cg->http->hostname, cg->server) || cg->ipp_port != httpAddrPort(cg->http->hostaddr) || (cg->http->encryption != cg->encryption && cg->http->encryption == HTTP_ENCRYPTION_NEVER)) { /* * Need to close the current connection because something has changed... */ httpClose(cg->http); cg->http = NULL; } } /* * (Re)connect as needed... */ if (!cg->http) { if ((cg->http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, cupsEncryption(), 1, 0, NULL)) == NULL) { if (errno) _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, NULL, 0); else _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, _("Unable to connect to host."), 1); if (num_settings) *num_settings = 0; if (settings) *settings = NULL; return (0); } } http = cg->http; } if (!http || !num_settings || !settings) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0); if (num_settings) *num_settings = 0; if (settings) *settings = NULL; return (0); } *num_settings = 0; *settings = NULL; /* * Get the cupsd.conf file... */ if ((status = get_cupsd_conf(http, cg, cg->cupsd_update, cupsdconf, sizeof(cupsdconf), &remote)) == HTTP_STATUS_OK) { if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL) { char message[1024]; /* Message string */ snprintf(message, sizeof(message), _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")), cupsdconf, strerror(errno)); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0); } } else cupsd = NULL; if (cupsd) { /* * Read the file, keeping track of what settings are enabled... */ int remote_access = 0, /* Remote access allowed? */ remote_admin = 0, /* Remote administration allowed? */ remote_any = 0, /* Remote access from anywhere allowed? */ browsing = 1, /* Browsing enabled? */ cancel_policy = 1, /* Cancel-job policy set? */ debug_logging = 0; /* LogLevel debug set? */ int linenum = 0, /* Line number in file */ in_location = 0, /* In a location section? */ in_policy = 0, /* In a policy section? */ in_cancel_job = 0, /* In a cancel-job section? */ in_admin_location = 0; /* In the /admin location? */ invalidate_cupsd_cache(cg); cg->cupsd_update = time(NULL); httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname)); while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum)) { if (!value && strncmp(line, "</", 2)) value = line + strlen(line); if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && value) { char *port; /* Pointer to port number, if any */ if ((port = strrchr(value, ':')) != NULL) *port = '\0'; else if (isdigit(*value & 255)) { /* * Listen on a port number implies remote access... */ remote_access = 1; continue; } if (_cups_strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1") #ifdef AF_LOCAL && *value != '/' #endif /* AF_LOCAL */ #ifdef AF_INET6 && strcmp(value, "[::1]") #endif /* AF_INET6 */ ) remote_access = 1; } else if (!_cups_strcasecmp(line, "Browsing")) { browsing = !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(line, "LogLevel")) { debug_logging = !_cups_strncasecmp(value, "debug", 5); } else if (!_cups_strcasecmp(line, "<Policy") && !_cups_strcasecmp(value, "default")) { in_policy = 1; } else if (!_cups_strcasecmp(line, "</Policy>")) { in_policy = 0; } else if (!_cups_strcasecmp(line, "<Limit") && in_policy && value) { /* * See if the policy limit is for the Cancel-Job operation... */ char *valptr; /* Pointer into value */ while (*value) { for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++); if (*valptr) *valptr++ = '\0'; if (!_cups_strcasecmp(value, "cancel-job") || !_cups_strcasecmp(value, "all")) { in_cancel_job = 1; break; } for (value = valptr; _cups_isspace(*value); value ++); } } else if (!_cups_strcasecmp(line, "</Limit>")) { in_cancel_job = 0; } else if (!_cups_strcasecmp(line, "Require") && in_cancel_job) { cancel_policy = 0; } else if (!_cups_strcasecmp(line, "<Location") && value) { in_admin_location = !_cups_strcasecmp(value, "/admin"); in_location = 1; } else if (!_cups_strcasecmp(line, "</Location>")) { in_admin_location = 0; in_location = 0; } else if (!_cups_strcasecmp(line, "Allow") && value && _cups_strcasecmp(value, "localhost") && _cups_strcasecmp(value, "127.0.0.1") #ifdef AF_LOCAL && *value != '/' #endif /* AF_LOCAL */ #ifdef AF_INET6 && strcmp(value, "::1") #endif /* AF_INET6 */ ) { if (in_admin_location) remote_admin = 1; else if (!_cups_strcasecmp(value, "all")) remote_any = 1; } else if (line[0] != '<' && !in_location && !in_policy && _cups_strcasecmp(line, "Allow") && _cups_strcasecmp(line, "AuthType") && _cups_strcasecmp(line, "Deny") && _cups_strcasecmp(line, "Order") && _cups_strcasecmp(line, "Require") && _cups_strcasecmp(line, "Satisfy")) cg->cupsd_num_settings = cupsAddOption(line, value, cg->cupsd_num_settings, &(cg->cupsd_settings)); } cupsFileClose(cupsd); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING, debug_logging ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN, (remote_access && remote_admin) ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY, remote_any ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS, (remote_access && browsing) ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY, cancel_policy ? "1" : "0", cg->cupsd_num_settings, &(cg->cupsd_settings)); } else if (status != HTTP_STATUS_NOT_MODIFIED) invalidate_cupsd_cache(cg); /* * Remove any temporary files and copy the settings array... */ if (remote) unlink(cupsdconf); for (i = cg->cupsd_num_settings, setting = cg->cupsd_settings; i > 0; i --, setting ++) *num_settings = cupsAddOption(setting->name, setting->value, *num_settings, settings); return (cg->cupsd_num_settings > 0); }
int /* O - Number of options found */ cupsParseOptions( const char *arg, /* I - Argument to parse */ int num_options, /* I - Number of options */ cups_option_t **options) /* O - Options found */ { char *copyarg, /* Copy of input string */ *ptr, /* Pointer into string */ *name, /* Pointer to name */ *value, /* Pointer to value */ sep, /* Separator character */ quote; /* Quote character */ DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options)); /* * Range check input... */ if (!arg) { DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (!options || num_options < 0) { DEBUG_puts("1cupsParseOptions: Returning 0"); return (0); } /* * Make a copy of the argument string and then divide it up... */ if ((copyarg = strdup(arg)) == NULL) { DEBUG_puts("1cupsParseOptions: Unable to copy arg string"); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); } if (*copyarg == '{') { /* * Remove surrounding {} so we can parse "{name=value ... name=value}"... */ if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}') { *ptr = '\0'; ptr = copyarg + 1; } else ptr = copyarg; } else ptr = copyarg; /* * Skip leading spaces... */ while (_cups_isspace(*ptr)) ptr ++; /* * Loop through the string... */ while (*ptr != '\0') { /* * Get the name up to a SPACE, =, or end-of-string... */ name = ptr; while (!strchr("\f\n\r\t\v =", *ptr) && *ptr) ptr ++; /* * Avoid an empty name... */ if (ptr == name) break; /* * Skip trailing spaces... */ while (_cups_isspace(*ptr)) *ptr++ = '\0'; if ((sep = *ptr) == '=') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name)); if (sep != '=') { /* * Boolean option... */ if (!_cups_strncasecmp(name, "no", 2)) num_options = cupsAddOption(name + 2, "false", num_options, options); else num_options = cupsAddOption(name, "true", num_options, options); continue; } /* * Remove = and parse the value... */ value = ptr; while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == ',') ptr ++; else if (*ptr == '\'' || *ptr == '\"') { /* * Quoted string constant... */ quote = *ptr; _cups_strcpy(ptr, ptr + 1); while (*ptr != quote && *ptr) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } if (*ptr) _cups_strcpy(ptr, ptr + 1); } else if (*ptr == '{') { /* * Collection value... */ int depth; for (depth = 0; *ptr; ptr ++) { if (*ptr == '{') depth ++; else if (*ptr == '}') { depth --; if (!depth) { ptr ++; break; } } else if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); } } else { /* * Normal space-delimited string... */ while (*ptr && !_cups_isspace(*ptr)) { if (*ptr == '\\' && ptr[1]) _cups_strcpy(ptr, ptr + 1); ptr ++; } } } if (*ptr != '\0') *ptr++ = '\0'; DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value)); /* * Skip trailing whitespace... */ while (_cups_isspace(*ptr)) ptr ++; /* * Add the string value... */ num_options = cupsAddOption(name, value, num_options, options); } /* * Free the copy of the argument we made and return the number of options * found. */ free(copyarg); DEBUG_printf(("1cupsParseOptions: Returning %d", num_options)); return (num_options); }
int /* O - 1 if conflicts exist, 0 otherwise */ cupsMarkOptions( ppd_file_t *ppd, /* I - PPD file */ int num_options, /* I - Number of options */ cups_option_t *options) /* I - Options */ { int i, j; /* Looping vars */ char *ptr, /* Pointer into string */ s[255]; /* Temporary string */ const char *val, /* Pointer into value */ *media, /* media option */ *output_bin, /* output-bin option */ *page_size, /* PageSize option */ *ppd_keyword, /* PPD keyword */ *print_color_mode, /* print-color-mode option */ *print_quality, /* print-quality option */ *sides; /* sides option */ cups_option_t *optptr; /* Current option */ ppd_attr_t *attr; /* PPD attribute */ _ppd_cache_t *cache; /* PPD cache and mapping data */ /* * Check arguments... */ if (!ppd || num_options <= 0 || !options) return (0); ppd_debug_marked(ppd, "Before..."); /* * Do special handling for finishings, media, output-bin, output-mode, * print-color-mode, print-quality, and PageSize... */ media = cupsGetOption("media", num_options, options); output_bin = cupsGetOption("output-bin", num_options, options); page_size = cupsGetOption("PageSize", num_options, options); print_quality = cupsGetOption("print-quality", num_options, options); sides = cupsGetOption("sides", num_options, options); if ((print_color_mode = cupsGetOption("print-color-mode", num_options, options)) == NULL) print_color_mode = cupsGetOption("output-mode", num_options, options); if ((media || output_bin || print_color_mode || print_quality || sides) && !ppd->cache) { /* * Load PPD cache and mapping data as needed... */ ppd->cache = _ppdCacheCreateWithPPD(ppd); } cache = ppd->cache; if (media) { /* * Loop through the option string, separating it at commas and marking each * individual option as long as the corresponding PPD option (PageSize, * InputSlot, etc.) is not also set. * * For PageSize, we also check for an empty option value since some versions * of MacOS X use it to specify auto-selection of the media based solely on * the size. */ for (val = media; *val;) { /* * Extract the sub-option from the string... */ for (ptr = s; *val && *val != ',' && (ptr - s) < (sizeof(s) - 1);) *ptr++ = *val++; *ptr++ = '\0'; if (*val == ',') val ++; /* * Mark it... */ if (!page_size || !page_size[0]) { if (!_cups_strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s)) ppd_mark_option(ppd, "PageSize", s); else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL) ppd_mark_option(ppd, "PageSize", ppd_keyword); } if (cache && cache->source_option && !cupsGetOption(cache->source_option, num_options, options) && (ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL) ppd_mark_option(ppd, cache->source_option, ppd_keyword); if (!cupsGetOption("MediaType", num_options, options) && (ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL) ppd_mark_option(ppd, "MediaType", ppd_keyword); } } if (cache) { if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat", num_options, options) && !cupsGetOption("APPrinterPreset", num_options, options) && (print_color_mode || print_quality)) { /* * Map output-mode and print-quality to a preset... */ _pwg_print_color_mode_t pwg_pcm;/* print-color-mode index */ _pwg_print_quality_t pwg_pq; /* print-quality index */ cups_option_t *preset;/* Current preset option */ if (print_color_mode && !strcmp(print_color_mode, "monochrome")) pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME; else pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; if (print_quality) { pwg_pq = atoi(print_quality) - IPP_QUALITY_DRAFT; if (pwg_pq < _PWG_PRINT_QUALITY_DRAFT) pwg_pq = _PWG_PRINT_QUALITY_DRAFT; else if (pwg_pq > _PWG_PRINT_QUALITY_HIGH) pwg_pq = _PWG_PRINT_QUALITY_HIGH; } else pwg_pq = _PWG_PRINT_QUALITY_NORMAL; if (cache->num_presets[pwg_pcm][pwg_pq] == 0) { /* * Try to find a preset that works so that we maximize the chances of us * getting a good print using IPP attributes. */ if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0) pwg_pq = _PWG_PRINT_QUALITY_NORMAL; else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0) pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; else { pwg_pq = _PWG_PRINT_QUALITY_NORMAL; pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; } } if (cache->num_presets[pwg_pcm][pwg_pq] > 0) { /* * Copy the preset options as long as the corresponding names are not * already defined in the IPP request... */ for (i = cache->num_presets[pwg_pcm][pwg_pq], preset = cache->presets[pwg_pcm][pwg_pq]; i > 0; i --, preset ++) { if (!cupsGetOption(preset->name, num_options, options)) ppd_mark_option(ppd, preset->name, preset->value); } } } if (output_bin && !cupsGetOption("OutputBin", num_options, options) && (ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL) { /* * Map output-bin to OutputBin... */ ppd_mark_option(ppd, "OutputBin", ppd_keyword); } if (sides && cache->sides_option && !cupsGetOption(cache->sides_option, num_options, options)) { /* * Map sides to duplex option... */ if (!strcmp(sides, "one-sided") && cache->sides_1sided) ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided); else if (!strcmp(sides, "two-sided-long-edge") && cache->sides_2sided_long) ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long); else if (!strcmp(sides, "two-sided-short-edge") && cache->sides_2sided_short) ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short); } } /* * Mark other options... */ for (i = num_options, optptr = options; i > 0; i --, optptr ++) if (!_cups_strcasecmp(optptr->name, "media") || !_cups_strcasecmp(optptr->name, "output-bin") || !_cups_strcasecmp(optptr->name, "output-mode") || !_cups_strcasecmp(optptr->name, "print-quality") || !_cups_strcasecmp(optptr->name, "sides")) continue; else if (!_cups_strcasecmp(optptr->name, "resolution") || !_cups_strcasecmp(optptr->name, "printer-resolution")) { ppd_mark_option(ppd, "Resolution", optptr->value); ppd_mark_option(ppd, "SetResolution", optptr->value); /* Calcomp, Linotype, QMS, Summagraphics, Tektronix, Varityper */ ppd_mark_option(ppd, "JCLResolution", optptr->value); /* HP */ ppd_mark_option(ppd, "CNRes_PGP", optptr->value); /* Canon */ } else if (!_cups_strcasecmp(optptr->name, "multiple-document-handling")) { if (!cupsGetOption("Collate", num_options, options) && ppdFindOption(ppd, "Collate")) { if (_cups_strcasecmp(optptr->value, "separate-documents-uncollated-copies")) ppd_mark_option(ppd, "Collate", "True"); else ppd_mark_option(ppd, "Collate", "False"); } } else if (!_cups_strcasecmp(optptr->name, "finishings")) { /* * Lookup cupsIPPFinishings attributes for each value... */ for (ptr = optptr->value; *ptr;) { /* * Get the next finishings number... */ if (!isdigit(*ptr & 255)) break; if ((j = strtol(ptr, &ptr, 10)) < 3) break; /* * Skip separator as needed... */ if (*ptr == ',') ptr ++; /* * Look it up in the PPD file... */ sprintf(s, "%d", j); if ((attr = ppdFindAttr(ppd, "cupsIPPFinishings", s)) == NULL) continue; /* * Apply "*Option Choice" settings from the attribute value... */ ppd_mark_choices(ppd, attr->value); } } else if (!_cups_strcasecmp(optptr->name, "APPrinterPreset")) { /* * Lookup APPrinterPreset value... */ if ((attr = ppdFindAttr(ppd, "APPrinterPreset", optptr->value)) != NULL) { /* * Apply "*Option Choice" settings from the attribute value... */ ppd_mark_choices(ppd, attr->value); } } else if (!_cups_strcasecmp(optptr->name, "mirror")) ppd_mark_option(ppd, "MirrorPrint", optptr->value); else ppd_mark_option(ppd, optptr->name, optptr->value); ppd_debug_marked(ppd, "After..."); return (ppdConflicts(ppd) > 0); }
static void fix_make_model( char *make_model, /* I - New make-and-model string */ const char *old_make_model, /* I - Old make-and-model string */ int make_model_size) /* I - Size of new string buffer */ { char *mmptr; /* Pointer into make-and-model string */ /* * Fix some common problems with the make-and-model string so * that printer driver detection works better... */ if (!_cups_strncasecmp(old_make_model, "Hewlett-Packard", 15)) { /* * Strip leading Hewlett-Packard and hp prefixes and replace * with a single HP manufacturer prefix... */ mmptr = (char *)old_make_model + 15; while (isspace(*mmptr & 255)) mmptr ++; if (!_cups_strncasecmp(mmptr, "hp", 2)) { mmptr += 2; while (isspace(*mmptr & 255)) mmptr ++; } make_model[0] = 'H'; make_model[1] = 'P'; make_model[2] = ' '; strlcpy(make_model + 3, mmptr, (size_t)make_model_size - 3); } else if (!_cups_strncasecmp(old_make_model, "deskjet", 7)) snprintf(make_model, (size_t)make_model_size, "HP DeskJet%s", old_make_model + 7); else if (!_cups_strncasecmp(old_make_model, "officejet", 9)) snprintf(make_model, (size_t)make_model_size, "HP OfficeJet%s", old_make_model + 9); else if (!_cups_strncasecmp(old_make_model, "stylus_pro_", 11)) snprintf(make_model, (size_t)make_model_size, "EPSON Stylus Pro %s", old_make_model + 11); else strlcpy(make_model, old_make_model, (size_t)make_model_size); if ((mmptr = strstr(make_model, ", Inc.,")) != NULL) { /* * Strip inc. from name, e.g. "Tektronix, Inc., Phaser 560" * becomes "Tektronix Phaser 560"... */ _cups_strcpy(mmptr, mmptr + 7); } if ((mmptr = strstr(make_model, " Network")) != NULL) { /* * Drop unnecessary informational text, e.g. "Xerox DocuPrint N2025 * Network LaserJet - 2.12" becomes "Xerox DocuPrint N2025"... */ *mmptr = '\0'; } if ((mmptr = strchr(make_model, ',')) != NULL) { /* * Drop anything after a trailing comma... */ *mmptr = '\0'; } }
static int /* O - 0 = success, -1 = error */ help_load_file( help_index_t *hi, /* I - Index */ const char *filename, /* I - Filename */ const char *relative, /* I - Relative path */ time_t mtime) /* I - Modification time */ { cups_file_t *fp; /* HTML file */ help_node_t *node; /* Current node */ char line[1024], /* Line from file */ temp[1024], /* Temporary word */ section[1024], /* Section */ *ptr, /* Pointer into line */ *anchor, /* Anchor name */ *text; /* Text for anchor */ off_t offset; /* File offset */ char quote; /* Quote character */ help_word_t *word; /* Current word */ int wordlen; /* Length of word */ DEBUG_printf(("2help_load_file(hi=%p, filename=\"%s\", relative=\"%s\", " "mtime=%ld)", hi, filename, relative, mtime)); if ((fp = cupsFileOpen(filename, "r")) == NULL) return (-1); node = NULL; offset = 0; strlcpy(section, "Other", sizeof(section)); while (cupsFileGets(fp, line, sizeof(line))) { /* * Look for "<TITLE>", "<A NAME", or "<!-- SECTION:" prefix... */ if (!_cups_strncasecmp(line, "<!-- SECTION:", 13)) { /* * Got section line, copy it! */ for (ptr = line + 13; isspace(*ptr & 255); ptr ++); strlcpy(section, ptr, sizeof(section)); if ((ptr = strstr(section, "-->")) != NULL) { /* * Strip comment stuff from end of line... */ for (*ptr-- = '\0'; ptr > line && isspace(*ptr & 255); *ptr-- = '\0'); if (isspace(*ptr & 255)) *ptr = '\0'; } continue; } for (ptr = line; (ptr = strchr(ptr, '<')) != NULL;) { ptr ++; if (!_cups_strncasecmp(ptr, "TITLE>", 6)) { /* * Found the title... */ anchor = NULL; ptr += 6; } else if (!_cups_strncasecmp(ptr, "A NAME=", 7)) { /* * Found an anchor... */ ptr += 7; if (*ptr == '\"' || *ptr == '\'') { /* * Get quoted anchor... */ quote = *ptr; anchor = ptr + 1; if ((ptr = strchr(anchor, quote)) != NULL) *ptr++ = '\0'; else break; } else { /* * Get unquoted anchor... */ anchor = ptr + 1; for (ptr = anchor; *ptr && *ptr != '>' && !isspace(*ptr & 255); ptr ++); if (*ptr) *ptr++ = '\0'; else break; } /* * Got the anchor, now lets find the end... */ while (*ptr && *ptr != '>') ptr ++; if (*ptr != '>') break; ptr ++; } else continue; /* * Now collect text for the link... */ text = ptr; while ((ptr = strchr(text, '<')) == NULL) { ptr = text + strlen(text); if (ptr >= (line + sizeof(line) - 2)) break; *ptr++ = ' '; if (!cupsFileGets(fp, ptr, sizeof(line) - (ptr - line) - 1)) break; } *ptr = '\0'; if (node) node->length = offset - node->offset; if (!*text) { node = NULL; break; } if ((node = helpFindNode(hi, relative, anchor)) != NULL) { /* * Node already in the index, so replace the text and other * data... */ cupsArrayRemove(hi->nodes, node); if (node->section) free(node->section); if (node->text) free(node->text); if (node->words) { for (word = (help_word_t *)cupsArrayFirst(node->words); word; word = (help_word_t *)cupsArrayNext(node->words)) help_delete_word(word); cupsArrayDelete(node->words); node->words = NULL; } node->section = section[0] ? strdup(section) : NULL; node->text = strdup(text); node->mtime = mtime; node->offset = offset; node->score = 0; } else { /* * New node... */ node = help_new_node(relative, anchor, section, text, mtime, offset, 0); } /* * Go through the text value and replace tabs and newlines with * whitespace and eliminate extra whitespace... */ for (ptr = node->text, text = node->text; *ptr;) if (isspace(*ptr & 255)) { while (isspace(*ptr & 255)) ptr ++; *text++ = ' '; } else if (text != ptr) *text++ = *ptr++; else { text ++; ptr ++; } *text = '\0'; /* * (Re)add the node to the array... */ cupsArrayAdd(hi->nodes, node); if (!anchor) node = NULL; break; } if (node) { /* * Scan this line for words... */ for (ptr = line; *ptr; ptr ++) { /* * Skip HTML stuff... */ if (*ptr == '<') { if (!strncmp(ptr, "<!--", 4)) { /* * Skip HTML comment... */ if ((text = strstr(ptr + 4, "-->")) == NULL) ptr += strlen(ptr) - 1; else ptr = text + 2; } else { /* * Skip HTML element... */ for (ptr ++; *ptr && *ptr != '>'; ptr ++) { if (*ptr == '\"' || *ptr == '\'') { for (quote = *ptr++; *ptr && *ptr != quote; ptr ++); if (!*ptr) ptr --; } } if (!*ptr) ptr --; } continue; } else if (*ptr == '&') { /* * Skip HTML entity... */ for (ptr ++; *ptr && *ptr != ';'; ptr ++); if (!*ptr) ptr --; continue; } else if (!isalnum(*ptr & 255)) continue; /* * Found the start of a word, search until we find the end... */ for (text = ptr, ptr ++; *ptr && isalnum(*ptr & 255); ptr ++); wordlen = ptr - text; memcpy(temp, text, wordlen); temp[wordlen] = '\0'; ptr --; if (wordlen > 1 && !bsearch(temp, help_common_words, (sizeof(help_common_words) / sizeof(help_common_words[0])), sizeof(help_common_words[0]), (int (*)(const void *, const void *)) _cups_strcasecmp)) help_add_word(node, temp); } } /* * Get the offset of the next line... */ offset = cupsFileTell(fp); } cupsFileClose(fp); if (node) node->length = offset - node->offset; return (0); }
char * /* O - Normalized make-and-model string or NULL on error */ _ppdNormalizeMakeAndModel( const char *make_and_model, /* I - Original make-and-model string */ char *buffer, /* I - String buffer */ size_t bufsize) /* I - Size of string buffer */ { char *bufptr; /* Pointer into buffer */ if (!make_and_model || !buffer || bufsize < 1) { if (buffer) *buffer = '\0'; return (NULL); } /* * Skip leading whitespace... */ while (_cups_isspace(*make_and_model)) make_and_model ++; /* * Remove parenthesis and add manufacturers as needed... */ if (make_and_model[0] == '(') { strlcpy(buffer, make_and_model + 1, bufsize); if ((bufptr = strrchr(buffer, ')')) != NULL) *bufptr = '\0'; } else if (!_cups_strncasecmp(make_and_model, "XPrint", 6)) { /* * Xerox XPrint... */ snprintf(buffer, bufsize, "Xerox %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "Eastman", 7)) { /* * Kodak... */ snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7); } else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11)) { /* * Apple LaserWriter... */ snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11); } else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10)) { /* * Seiko... */ snprintf(buffer, bufsize, "Seiko %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "fiery", 5)) { /* * EFI... */ snprintf(buffer, bufsize, "EFI %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "ps ", 3) || !_cups_strncasecmp(make_and_model, "colorpass", 9)) { /* * Canon... */ snprintf(buffer, bufsize, "Canon %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "primera", 7)) { /* * Fargo... */ snprintf(buffer, bufsize, "Fargo %s", make_and_model); } else if (!_cups_strncasecmp(make_and_model, "designjet", 9) || !_cups_strncasecmp(make_and_model, "deskjet", 7)) { /* * HP... */ snprintf(buffer, bufsize, "HP %s", make_and_model); } else strlcpy(buffer, make_and_model, bufsize); /* * Clean up the make... */ if (!_cups_strncasecmp(buffer, "agfa", 4)) { /* * Replace with AGFA (all uppercase)... */ buffer[0] = 'A'; buffer[1] = 'G'; buffer[2] = 'F'; buffer[3] = 'A'; } else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19)) { /* * Just put "HP" on the front... */ buffer[0] = 'H'; buffer[1] = 'P'; _cups_strcpy(buffer + 2, buffer + 18); } else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16)) { /* * Just put "HP" on the front... */ buffer[0] = 'H'; buffer[1] = 'P'; _cups_strcpy(buffer + 2, buffer + 15); } else if (!_cups_strncasecmp(buffer, "Lexmark International", 21)) { /* * Strip "International"... */ _cups_strcpy(buffer + 8, buffer + 21); } else if (!_cups_strncasecmp(buffer, "herk", 4)) { /* * Replace with LHAG... */ buffer[0] = 'L'; buffer[1] = 'H'; buffer[2] = 'A'; buffer[3] = 'G'; } else if (!_cups_strncasecmp(buffer, "linotype", 8)) { /* * Replace with LHAG... */ buffer[0] = 'L'; buffer[1] = 'H'; buffer[2] = 'A'; buffer[3] = 'G'; _cups_strcpy(buffer + 4, buffer + 8); } /* * Remove trailing whitespace and return... */ for (bufptr = buffer + strlen(buffer) - 1; bufptr >= buffer && _cups_isspace(*bufptr); bufptr --); bufptr[1] = '\0'; return (buffer[0] ? buffer : NULL); }
int /* O - 0 on success, -1 on failure */ backendGetDeviceID( int fd, /* I - File descriptor */ char *device_id, /* O - 1284 device ID */ int device_id_size, /* I - Size of buffer */ char *make_model, /* O - Make/model */ int make_model_size, /* I - Size of buffer */ const char *scheme, /* I - URI scheme */ char *uri, /* O - Device URI */ int uri_size) /* I - Size of buffer */ { #ifdef __APPLE__ /* This function is a no-op */ (void)fd; (void)device_id; (void)device_id_size; (void)make_model; (void)make_model_size; (void)scheme; (void)uri; (void)uri_size; return (-1); #else /* Get the device ID from the specified file descriptor... */ # ifdef __linux int length; /* Length of device ID info */ int got_id = 0; # endif /* __linux */ # if defined(__sun) && defined(ECPPIOC_GETDEVID) struct ecpp_device_id did; /* Device ID buffer */ # endif /* __sun && ECPPIOC_GETDEVID */ char *ptr; /* Pointer into device ID */ DEBUG_printf(("backendGetDeviceID(fd=%d, device_id=%p, device_id_size=%d, " "make_model=%p, make_model_size=%d, scheme=\"%s\", " "uri=%p, uri_size=%d)\n", fd, device_id, device_id_size, make_model, make_model_size, scheme ? scheme : "(null)", uri, uri_size)); /* * Range check input... */ if (!device_id || device_id_size < 32) { DEBUG_puts("backendGetDeviceID: Bad args!"); return (-1); } if (make_model) *make_model = '\0'; if (fd >= 0) { /* * Get the device ID string... */ *device_id = '\0'; # ifdef __linux if (ioctl(fd, LPIOC_GET_DEVICE_ID(device_id_size), device_id)) { /* * Linux has to implement things differently for every device it seems. * Since the standard parallel port driver does not provide a simple * ioctl() to get the 1284 device ID, we have to open the "raw" parallel * device corresponding to this port and do some negotiation trickery * to get the current device ID. */ if (uri && !strncmp(uri, "parallel:/dev/", 14)) { char devparport[16]; /* /dev/parportN */ int devparportfd, /* File descriptor for raw device */ mode; /* Port mode */ /* * Since the Linux parallel backend only supports 4 parallel port * devices, just grab the trailing digit and use it to construct a * /dev/parportN filename... */ snprintf(devparport, sizeof(devparport), "/dev/parport%s", uri + strlen(uri) - 1); if ((devparportfd = open(devparport, O_RDWR | O_NOCTTY)) != -1) { /* * Claim the device... */ if (!ioctl(devparportfd, PPCLAIM)) { fcntl(devparportfd, F_SETFL, fcntl(devparportfd, F_GETFL) | O_NONBLOCK); mode = IEEE1284_MODE_COMPAT; if (!ioctl(devparportfd, PPNEGOT, &mode)) { /* * Put the device into Device ID mode... */ mode = IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID; if (!ioctl(devparportfd, PPNEGOT, &mode)) { /* * Read the 1284 device ID... */ if ((length = read(devparportfd, device_id, (size_t)device_id_size - 1)) >= 2) { device_id[length] = '\0'; got_id = 1; } } } /* * Release the device... */ ioctl(devparportfd, PPRELEASE); } close(devparportfd); } } } else got_id = 1; if (got_id) { /* * Extract the length of the device ID string from the first two * bytes. The 1284 spec says the length is stored MSB first... */ length = (int)((((unsigned)device_id[0] & 255) << 8) + ((unsigned)device_id[1] & 255)); /* * Check to see if the length is larger than our buffer; first * assume that the vendor incorrectly implemented the 1284 spec, * and then limit the length to the size of our buffer... */ if (length > device_id_size || length < 14) length = (int)((((unsigned)device_id[1] & 255) << 8) + ((unsigned)device_id[0] & 255)); if (length > device_id_size) length = device_id_size; /* * The length field counts the number of bytes in the string * including the length field itself (2 bytes). The minimum * length for a valid/usable device ID is 14 bytes: * * <LENGTH> MFG: <MFG> ;MDL: <MDL> ; * 2 + 4 + 1 + 5 + 1 + 1 */ if (length < 14) { /* * Can't use this device ID, so don't try to copy it... */ device_id[0] = '\0'; got_id = 0; } else { /* * Copy the device ID text to the beginning of the buffer and * nul-terminate. */ length -= 2; memmove(device_id, device_id + 2, (size_t)length); device_id[length] = '\0'; } } else { DEBUG_printf(("backendGetDeviceID: ioctl failed - %s\n", strerror(errno))); *device_id = '\0'; } # endif /* __linux */ # if defined(__sun) && defined(ECPPIOC_GETDEVID) did.mode = ECPP_CENTRONICS; did.len = device_id_size - 1; did.rlen = 0; did.addr = device_id; if (!ioctl(fd, ECPPIOC_GETDEVID, &did)) { /* * Nul-terminate the device ID text. */ if (did.rlen < (device_id_size - 1)) device_id[did.rlen] = '\0'; else device_id[device_id_size - 1] = '\0'; } # ifdef DEBUG else DEBUG_printf(("backendGetDeviceID: ioctl failed - %s\n", strerror(errno))); # endif /* DEBUG */ # endif /* __sun && ECPPIOC_GETDEVID */ } /* * Check whether device ID is valid. Turn line breaks and tabs to spaces and * reject device IDs with non-printable characters. */ for (ptr = device_id; *ptr; ptr ++) if (_cups_isspace(*ptr)) *ptr = ' '; else if ((*ptr & 255) < ' ' || *ptr == 127) { DEBUG_printf(("backendGetDeviceID: Bad device_id character %d.", *ptr & 255)); *device_id = '\0'; break; } DEBUG_printf(("backendGetDeviceID: device_id=\"%s\"\n", device_id)); if (scheme && uri) *uri = '\0'; if (!*device_id) return (-1); /* * Get the make and model... */ if (make_model) backendGetMakeModel(device_id, make_model, (size_t)make_model_size); /* * Then generate a device URI... */ if (scheme && uri && uri_size > 32) { int num_values; /* Number of keys and values */ cups_option_t *values; /* Keys and values in device ID */ const char *mfg, /* Manufacturer */ *mdl, /* Model */ *sern; /* Serial number */ char temp[256], /* Temporary manufacturer string */ *tempptr; /* Pointer into temp string */ /* * Get the make, model, and serial numbers... */ num_values = _cupsGet1284Values(device_id, &values); if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL) if ((sern = cupsGetOption("SERN", num_values, values)) == NULL) sern = cupsGetOption("SN", num_values, values); if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL) mfg = cupsGetOption("MFG", num_values, values); if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL) mdl = cupsGetOption("MDL", num_values, values); if (mfg) { if (!_cups_strcasecmp(mfg, "Hewlett-Packard")) mfg = "HP"; else if (!_cups_strcasecmp(mfg, "Lexmark International")) mfg = "Lexmark"; } else { strlcpy(temp, make_model, sizeof(temp)); if ((tempptr = strchr(temp, ' ')) != NULL) *tempptr = '\0'; mfg = temp; } if (!mdl) mdl = ""; if (!_cups_strncasecmp(mdl, mfg, strlen(mfg))) { mdl += strlen(mfg); while (isspace(*mdl & 255)) mdl ++; } /* * Generate the device URI from the manufacturer, make_model, and * serial number strings. */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, uri_size, scheme, NULL, mfg, 0, "/%s%s%s", mdl, sern ? "?serial=" : "", sern ? sern : ""); cupsFreeOptions(num_values, values); } return (0); #endif /* __APPLE__ */ }
static void ppd_mark_option(ppd_file_t *ppd, /* I - PPD file */ const char *option, /* I - Option name */ const char *choice) /* I - Choice name */ { int i, j; /* Looping vars */ ppd_option_t *o; /* Option pointer */ ppd_choice_t *c, /* Choice pointer */ *oldc, /* Old choice pointer */ key; /* Search key for choice */ struct lconv *loc; /* Locale data */ DEBUG_printf(("7ppd_mark_option(ppd=%p, option=\"%s\", choice=\"%s\")", ppd, option, choice)); /* * AP_D_InputSlot is the "default input slot" on MacOS X, and setting * it clears the regular InputSlot choices... */ if (!_cups_strcasecmp(option, "AP_D_InputSlot")) { cupsArraySave(ppd->options); if ((o = ppdFindOption(ppd, "InputSlot")) != NULL) { key.option = o; if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } } cupsArrayRestore(ppd->options); } /* * Check for custom options... */ cupsArraySave(ppd->options); o = ppdFindOption(ppd, option); cupsArrayRestore(ppd->options); if (!o) return; loc = localeconv(); if (!_cups_strncasecmp(choice, "Custom.", 7)) { /* * Handle a custom option... */ if ((c = ppdFindChoice(o, "Custom")) == NULL) return; if (!_cups_strcasecmp(option, "PageSize")) { /* * Handle custom page sizes... */ ppdPageSize(ppd, choice); } else { /* * Handle other custom options... */ ppd_coption_t *coption; /* Custom option */ ppd_cparam_t *cparam; /* Custom parameter */ char *units; /* Custom points units */ if ((coption = ppdFindCustomOption(ppd, option)) != NULL) { if ((cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params)) == NULL) return; switch (cparam->type) { case PPD_CUSTOM_CURVE : case PPD_CUSTOM_INVCURVE : case PPD_CUSTOM_REAL : cparam->current.custom_real = (float)_cupsStrScand(choice + 7, NULL, loc); break; case PPD_CUSTOM_POINTS : cparam->current.custom_points = (float)_cupsStrScand(choice + 7, &units, loc); if (units) { if (!_cups_strcasecmp(units, "cm")) cparam->current.custom_points *= 72.0f / 2.54f; else if (!_cups_strcasecmp(units, "mm")) cparam->current.custom_points *= 72.0f / 25.4f; else if (!_cups_strcasecmp(units, "m")) cparam->current.custom_points *= 72.0f / 0.0254f; else if (!_cups_strcasecmp(units, "in")) cparam->current.custom_points *= 72.0f; else if (!_cups_strcasecmp(units, "ft")) cparam->current.custom_points *= 12.0f * 72.0f; } break; case PPD_CUSTOM_INT : cparam->current.custom_int = atoi(choice + 7); break; case PPD_CUSTOM_PASSCODE : case PPD_CUSTOM_PASSWORD : case PPD_CUSTOM_STRING : if (cparam->current.custom_string) _cupsStrFree(cparam->current.custom_string); cparam->current.custom_string = _cupsStrAlloc(choice + 7); break; } } } /* * Make sure that we keep the option marked below... */ choice = "Custom"; } else if (choice[0] == '{') { /* * Handle multi-value custom options... */ ppd_coption_t *coption; /* Custom option */ ppd_cparam_t *cparam; /* Custom parameter */ char *units; /* Custom points units */ int num_vals; /* Number of values */ cups_option_t *vals, /* Values */ *val; /* Value */ if ((c = ppdFindChoice(o, "Custom")) == NULL) return; if ((coption = ppdFindCustomOption(ppd, option)) != NULL) { num_vals = cupsParseOptions(choice, 0, &vals); for (i = 0, val = vals; i < num_vals; i ++, val ++) { if ((cparam = ppdFindCustomParam(coption, val->name)) == NULL) continue; switch (cparam->type) { case PPD_CUSTOM_CURVE : case PPD_CUSTOM_INVCURVE : case PPD_CUSTOM_REAL : cparam->current.custom_real = (float)_cupsStrScand(val->value, NULL, loc); break; case PPD_CUSTOM_POINTS : cparam->current.custom_points = (float)_cupsStrScand(val->value, &units, loc); if (units) { if (!_cups_strcasecmp(units, "cm")) cparam->current.custom_points *= 72.0f / 2.54f; else if (!_cups_strcasecmp(units, "mm")) cparam->current.custom_points *= 72.0f / 25.4f; else if (!_cups_strcasecmp(units, "m")) cparam->current.custom_points *= 72.0f / 0.0254f; else if (!_cups_strcasecmp(units, "in")) cparam->current.custom_points *= 72.0f; else if (!_cups_strcasecmp(units, "ft")) cparam->current.custom_points *= 12.0f * 72.0f; } break; case PPD_CUSTOM_INT : cparam->current.custom_int = atoi(val->value); break; case PPD_CUSTOM_PASSCODE : case PPD_CUSTOM_PASSWORD : case PPD_CUSTOM_STRING : if (cparam->current.custom_string) _cupsStrFree(cparam->current.custom_string); cparam->current.custom_string = _cupsStrRetain(val->value); break; } } cupsFreeOptions(num_vals, vals); } } else { for (i = o->num_choices, c = o->choices; i > 0; i --, c ++) if (!_cups_strcasecmp(c->choice, choice)) break; if (!i) return; } /* * Option found; mark it and then handle unmarking any other options. */ if (o->ui != PPD_UI_PICKMANY) { /* * Unmark all other choices... */ if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, c)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } if (!_cups_strcasecmp(option, "PageSize") || !_cups_strcasecmp(option, "PageRegion")) { /* * Mark current page size... */ for (j = 0; j < ppd->num_sizes; j ++) ppd->sizes[j].marked = !_cups_strcasecmp(ppd->sizes[j].name, choice); /* * Unmark the current PageSize or PageRegion setting, as * appropriate... */ cupsArraySave(ppd->options); if (!_cups_strcasecmp(option, "PageSize")) { if ((o = ppdFindOption(ppd, "PageRegion")) != NULL) { key.option = o; if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } } } else { if ((o = ppdFindOption(ppd, "PageSize")) != NULL) { key.option = o; if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } } } cupsArrayRestore(ppd->options); } else if (!_cups_strcasecmp(option, "InputSlot")) { /* * Unmark ManualFeed option... */ cupsArraySave(ppd->options); if ((o = ppdFindOption(ppd, "ManualFeed")) != NULL) { key.option = o; if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } } cupsArrayRestore(ppd->options); } else if (!_cups_strcasecmp(option, "ManualFeed") && !_cups_strcasecmp(choice, "True")) { /* * Unmark InputSlot option... */ cupsArraySave(ppd->options); if ((o = ppdFindOption(ppd, "InputSlot")) != NULL) { key.option = o; if ((oldc = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key)) != NULL) { oldc->marked = 0; cupsArrayRemove(ppd->marked, oldc); } } cupsArrayRestore(ppd->options); } } c->marked = 1; cupsArrayAdd(ppd->marked, c); }
int /* O - 1 on success, 0 on failure */ cupsResolveConflicts( ppd_file_t *ppd, /* I - PPD file */ const char *option, /* I - Newly selected option or @code NULL@ for none */ const char *choice, /* I - Newly selected choice or @code NULL@ for none */ int *num_options, /* IO - Number of additional selected options */ cups_option_t **options) /* IO - Additional selected options */ { int i, /* Looping var */ tries, /* Number of tries */ num_newopts; /* Number of new options */ cups_option_t *newopts; /* New options */ cups_array_t *active = NULL, /* Active constraints */ *pass, /* Resolvers for this pass */ *resolvers, /* Resolvers we have used */ *test; /* Test array for conflicts */ _ppd_cups_uiconsts_t *consts; /* Current constraints */ _ppd_cups_uiconst_t *constptr; /* Current constraint */ ppd_attr_t *resolver; /* Current resolver */ const char *resval; /* Pointer into resolver value */ char resoption[PPD_MAX_NAME], /* Current resolver option */ reschoice[PPD_MAX_NAME], /* Current resolver choice */ *resptr, /* Pointer into option/choice */ firstpage[255]; /* AP_FIRSTPAGE_Keyword string */ const char *value; /* Selected option value */ int changed; /* Did we change anything? */ ppd_choice_t *marked; /* Marked choice */ /* * Range check input... */ if (!ppd || !num_options || !options || (option == NULL) != (choice == NULL)) return (0); /* * Build a shadow option array... */ num_newopts = 0; newopts = NULL; for (i = 0; i < *num_options; i ++) num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value, num_newopts, &newopts); if (option && _cups_strcasecmp(option, "Collate")) num_newopts = cupsAddOption(option, choice, num_newopts, &newopts); /* * Loop until we have no conflicts... */ cupsArraySave(ppd->sorted_attrs); resolvers = NULL; pass = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL); tries = 0; while (tries < 100 && (active = ppd_test_constraints(ppd, NULL, NULL, num_newopts, newopts, _PPD_ALL_CONSTRAINTS)) != NULL) { tries ++; if (!resolvers) resolvers = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL); for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active), changed = 0; consts; consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(active)) { if (consts->resolver[0]) { /* * Look up the resolver... */ if (cupsArrayFind(pass, consts->resolver)) continue; /* Already applied this resolver... */ if (cupsArrayFind(resolvers, consts->resolver)) { /* * Resolver loop! */ DEBUG_printf(("1cupsResolveConflicts: Resolver loop with %s!", consts->resolver)); goto error; } if ((resolver = ppdFindAttr(ppd, "cupsUIResolver", consts->resolver)) == NULL) { DEBUG_printf(("1cupsResolveConflicts: Resolver %s not found!", consts->resolver)); goto error; } if (!resolver->value) { DEBUG_printf(("1cupsResolveConflicts: Resolver %s has no value!", consts->resolver)); goto error; } /* * Add the options from the resolver... */ cupsArrayAdd(pass, consts->resolver); cupsArrayAdd(resolvers, consts->resolver); for (resval = resolver->value; *resval && !changed;) { while (_cups_isspace(*resval)) resval ++; if (*resval != '*') break; for (resval ++, resptr = resoption; *resval && !_cups_isspace(*resval); resval ++) if (resptr < (resoption + sizeof(resoption) - 1)) *resptr++ = *resval; *resptr = '\0'; while (_cups_isspace(*resval)) resval ++; for (resptr = reschoice; *resval && !_cups_isspace(*resval); resval ++) if (resptr < (reschoice + sizeof(reschoice) - 1)) *resptr++ = *resval; *resptr = '\0'; if (!resoption[0] || !reschoice[0]) break; /* * Is this the option we are changing? */ snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", resoption); if (option && (!_cups_strcasecmp(resoption, option) || !_cups_strcasecmp(firstpage, option) || (!_cups_strcasecmp(option, "PageSize") && !_cups_strcasecmp(resoption, "PageRegion")) || (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") && !_cups_strcasecmp(resoption, "PageSize")) || (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") && !_cups_strcasecmp(resoption, "PageRegion")) || (!_cups_strcasecmp(option, "PageRegion") && !_cups_strcasecmp(resoption, "PageSize")) || (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") && !_cups_strcasecmp(resoption, "PageSize")) || (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") && !_cups_strcasecmp(resoption, "PageRegion")))) continue; /* * Try this choice... */ if ((test = ppd_test_constraints(ppd, resoption, reschoice, num_newopts, newopts, _PPD_ALL_CONSTRAINTS)) == NULL) { /* * That worked... */ changed = 1; } else cupsArrayDelete(test); /* * Add the option/choice from the resolver regardless of whether it * worked; this makes sure that we can cascade several changes to * make things resolve... */ num_newopts = cupsAddOption(resoption, reschoice, num_newopts, &newopts); } } else { /* * Try resolving by choosing the default values for non-installable * options, then by iterating through the possible choices... */ int j; /* Looping var */ ppd_choice_t *cptr; /* Current choice */ ppd_size_t *size; /* Current page size */ for (i = consts->num_constraints, constptr = consts->constraints; i > 0 && !changed; i --, constptr ++) { /* * Can't resolve by changing an installable option... */ if (constptr->installable) continue; /* * Is this the option we are changing? */ if (option && (!_cups_strcasecmp(constptr->option->keyword, option) || (!_cups_strcasecmp(option, "PageSize") && !_cups_strcasecmp(constptr->option->keyword, "PageRegion")) || (!_cups_strcasecmp(option, "PageRegion") && !_cups_strcasecmp(constptr->option->keyword, "PageSize")))) continue; /* * Get the current option choice... */ if ((value = cupsGetOption(constptr->option->keyword, num_newopts, newopts)) == NULL) { if (!_cups_strcasecmp(constptr->option->keyword, "PageSize") || !_cups_strcasecmp(constptr->option->keyword, "PageRegion")) { if ((value = cupsGetOption("PageSize", num_newopts, newopts)) == NULL) value = cupsGetOption("PageRegion", num_newopts, newopts); if (!value) { if ((size = ppdPageSize(ppd, NULL)) != NULL) value = size->name; else value = ""; } } else { marked = ppdFindMarkedChoice(ppd, constptr->option->keyword); value = marked ? marked->choice : ""; } } if (!_cups_strncasecmp(value, "Custom.", 7)) value = "Custom"; /* * Try the default choice... */ test = NULL; if (_cups_strcasecmp(value, constptr->option->defchoice) && (test = ppd_test_constraints(ppd, constptr->option->keyword, constptr->option->defchoice, num_newopts, newopts, _PPD_OPTION_CONSTRAINTS)) == NULL) { /* * That worked... */ num_newopts = cupsAddOption(constptr->option->keyword, constptr->option->defchoice, num_newopts, &newopts); changed = 1; } else { /* * Try each choice instead... */ for (j = constptr->option->num_choices, cptr = constptr->option->choices; j > 0; j --, cptr ++) { cupsArrayDelete(test); test = NULL; if (_cups_strcasecmp(value, cptr->choice) && _cups_strcasecmp(constptr->option->defchoice, cptr->choice) && _cups_strcasecmp("Custom", cptr->choice) && (test = ppd_test_constraints(ppd, constptr->option->keyword, cptr->choice, num_newopts, newopts, _PPD_OPTION_CONSTRAINTS)) == NULL) { /* * This choice works... */ num_newopts = cupsAddOption(constptr->option->keyword, cptr->choice, num_newopts, &newopts); changed = 1; break; } } cupsArrayDelete(test); } } } } if (!changed) { DEBUG_puts("1cupsResolveConflicts: Unable to automatically resolve " "constraint!"); goto error; } cupsArrayClear(pass); cupsArrayDelete(active); active = NULL; } if (tries >= 100) goto error; /* * Free the caller's option array... */ cupsFreeOptions(*num_options, *options); /* * If Collate is the option we are testing, add it here. Otherwise, remove * any Collate option from the resolve list since the filters automatically * handle manual collation... */ if (option && !_cups_strcasecmp(option, "Collate")) num_newopts = cupsAddOption(option, choice, num_newopts, &newopts); else num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts); /* * Return the new list of options to the caller... */ *num_options = num_newopts; *options = newopts; cupsArrayDelete(pass); cupsArrayDelete(resolvers); cupsArrayRestore(ppd->sorted_attrs); DEBUG_printf(("1cupsResolveConflicts: Returning %d options:", num_newopts)); #ifdef DEBUG for (i = 0; i < num_newopts; i ++) DEBUG_printf(("1cupsResolveConflicts: options[%d]: %s=%s", i, newopts[i].name, newopts[i].value)); #endif /* DEBUG */ return (1); /* * If we get here, we failed to resolve... */ error: cupsFreeOptions(num_newopts, newopts); cupsArrayDelete(active); cupsArrayDelete(pass); cupsArrayDelete(resolvers); cupsArrayRestore(ppd->sorted_attrs); DEBUG_puts("1cupsResolveConflicts: Unable to resolve conflicts!"); return (0); }
static void query_callback( DNSServiceRef sdRef, /* I - Service reference */ DNSServiceFlags flags, /* I - Data flags */ uint32_t interfaceIndex, /* I - Interface */ DNSServiceErrorType errorCode, /* I - Error, if any */ const char *fullName, /* I - Full service name */ uint16_t rrtype, /* I - Record type */ uint16_t rrclass, /* I - Record class */ uint16_t rdlen, /* I - Length of record data */ const void *rdata, /* I - Record data */ uint32_t ttl, /* I - Time-to-live */ void *context) /* I - Device */ { # else /* * 'query_callback()' - Process query data. */ static void query_callback( AvahiRecordBrowser *browser, /* I - Record browser */ AvahiIfIndex interfaceIndex, /* I - Interface index (unused) */ AvahiProtocol protocol, /* I - Network protocol (unused) */ AvahiBrowserEvent event, /* I - What happened? */ const char *fullName, /* I - Service name */ uint16_t rrclass, /* I - Record class */ uint16_t rrtype, /* I - Record type */ const void *rdata, /* I - TXT record */ size_t rdlen, /* I - Length of TXT record */ AvahiLookupResultFlags flags, /* I - Flags */ void *context) /* I - Device */ { AvahiClient *client = avahi_record_browser_get_client(browser); /* Client information */ # endif /* HAVE_DNSSD */ char *ptr; /* Pointer into string */ cups_device_t *device = (cups_device_t *)context; /* Device */ const uint8_t *data, /* Pointer into data */ *datanext, /* Next key/value pair */ *dataend; /* End of entire TXT record */ uint8_t datalen; /* Length of current key/value pair */ char key[256], /* Key string */ value[256], /* Value string */ make_and_model[512], /* Manufacturer and model */ model[256], /* Model */ pdl[256], /* PDL */ device_id[2048]; /* 1284 device ID */ # ifdef HAVE_DNSSD fprintf(stderr, "DEBUG2: query_callback(sdRef=%p, flags=%x, " "interfaceIndex=%d, errorCode=%d, fullName=\"%s\", " "rrtype=%u, rrclass=%u, rdlen=%u, rdata=%p, ttl=%u, " "context=%p)\n", sdRef, flags, interfaceIndex, errorCode, fullName, rrtype, rrclass, rdlen, rdata, ttl, context); /* * Only process "add" data... */ if (errorCode != kDNSServiceErr_NoError || !(flags & kDNSServiceFlagsAdd)) return; # else fprintf(stderr, "DEBUG2: query_callback(browser=%p, interfaceIndex=%d, " "protocol=%d, event=%d, fullName=\"%s\", rrclass=%u, " "rrtype=%u, rdata=%p, rdlen=%u, flags=%x, context=%p)\n", browser, interfaceIndex, protocol, event, fullName, rrclass, rrtype, rdata, (unsigned)rdlen, flags, context); /* * Only process "add" data... */ if (event != AVAHI_BROWSER_NEW) { if (event == AVAHI_BROWSER_FAILURE) fprintf(stderr, "ERROR: %s\n", avahi_strerror(avahi_client_errno(client))); return; } # endif /* HAVE_DNSSD */ /* * Pull out the priority and make and model from the TXT * record and save it... */ device_id[0] = '\0'; make_and_model[0] = '\0'; pdl[0] = '\0'; strlcpy(model, "Unknown", sizeof(model)); for (data = rdata, dataend = data + rdlen; data < dataend; data = datanext) { /* * Read a key/value pair starting with an 8-bit length. Since the * length is 8 bits and the size of the key/value buffers is 256, we * don't need to check for overflow... */ datalen = *data++; if (!datalen || (data + datalen) > dataend) break; datanext = data + datalen; for (ptr = key; data < datanext && *data != '='; data ++) *ptr++ = (char)*data; *ptr = '\0'; if (data < datanext && *data == '=') { data ++; if (data < datanext) memcpy(value, data, (size_t)(datanext - data)); value[datanext - data] = '\0'; fprintf(stderr, "DEBUG2: query_callback: \"%s=%s\".\n", key, value); } else { fprintf(stderr, "DEBUG2: query_callback: \"%s\" with no value.\n", key); continue; } if (!_cups_strncasecmp(key, "usb_", 4)) { /* * Add USB device ID information... */ ptr = device_id + strlen(device_id); snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "%s:%s;", key + 4, value); } if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") || !_cups_strcasecmp(key, "usb_MANUFACTURER")) strlcpy(make_and_model, value, sizeof(make_and_model)); else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL")) strlcpy(model, value, sizeof(model)); else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript")) { if (value[0] == '(') { /* * Strip parenthesis... */ if ((ptr = value + strlen(value) - 1) > value && *ptr == ')') *ptr = '\0'; strlcpy(model, value + 1, sizeof(model)); } else strlcpy(model, value, sizeof(model)); } else if (!_cups_strcasecmp(key, "ty")) { strlcpy(model, value, sizeof(model)); if ((ptr = strchr(model, ',')) != NULL) *ptr = '\0'; } else if (!_cups_strcasecmp(key, "pdl")) strlcpy(pdl, value, sizeof(pdl)); else if (!_cups_strcasecmp(key, "priority")) device->priority = atoi(value); else if ((device->type == CUPS_DEVICE_IPP || device->type == CUPS_DEVICE_IPPS || device->type == CUPS_DEVICE_PRINTER) && !_cups_strcasecmp(key, "printer-type")) { /* * This is a CUPS printer! */ device->cups_shared = 1; if (device->type == CUPS_DEVICE_PRINTER) device->sent = 1; } else if (!_cups_strcasecmp(key, "UUID")) device->uuid = strdup(value); } if (device->device_id) free(device->device_id); if (!device_id[0] && strcmp(model, "Unknown")) { if (make_and_model[0]) snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", make_and_model, model); else if (!_cups_strncasecmp(model, "designjet ", 10)) snprintf(device_id, sizeof(device_id), "MFG:HP;MDL:%s;", model + 10); else if (!_cups_strncasecmp(model, "stylus ", 7)) snprintf(device_id, sizeof(device_id), "MFG:EPSON;MDL:%s;", model + 7); else if ((ptr = strchr(model, ' ')) != NULL) { /* * Assume the first word is the make... */ memcpy(make_and_model, model, (size_t)(ptr - model)); make_and_model[ptr - model] = '\0'; snprintf(device_id, sizeof(device_id), "MFG:%s;MDL:%s;", make_and_model, ptr + 1); } } if (device_id[0] && !strstr(device_id, "CMD:") && !strstr(device_id, "COMMAND SET:") && (strstr(pdl, "application/pdf") || strstr(pdl, "application/postscript") || strstr(pdl, "application/vnd.hp-PCL") || strstr(pdl, "image/"))) { value[0] = '\0'; if (strstr(pdl, "application/pdf")) strlcat(value, ",PDF", sizeof(value)); if (strstr(pdl, "application/postscript")) strlcat(value, ",PS", sizeof(value)); if (strstr(pdl, "application/vnd.hp-PCL")) strlcat(value, ",PCL", sizeof(value)); for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/")) { char *valptr = value + strlen(value); /* Pointer into value */ if (valptr < (value + sizeof(value) - 1)) *valptr++ = ','; ptr += 6; while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.') { if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1)) *valptr++ = (char)toupper(*ptr++ & 255); else break; } *valptr = '\0'; } ptr = device_id + strlen(device_id); snprintf(ptr, sizeof(device_id) - (size_t)(ptr - device_id), "CMD:%s;", value + 1); } if (device_id[0]) device->device_id = strdup(device_id); else device->device_id = NULL; if (device->make_and_model) free(device->make_and_model); if (make_and_model[0]) { strlcat(make_and_model, " ", sizeof(make_and_model)); strlcat(make_and_model, model, sizeof(make_and_model)); if (!_cups_strncasecmp(make_and_model, "EPSON EPSON ", 12)) _cups_strcpy(make_and_model, make_and_model + 6); else if (!_cups_strncasecmp(make_and_model, "HP HP ", 6)) _cups_strcpy(make_and_model, make_and_model + 3); else if (!_cups_strncasecmp(make_and_model, "Lexmark International Lexmark ", 30)) _cups_strcpy(make_and_model, make_and_model + 22); device->make_and_model = strdup(make_and_model); } else device->make_and_model = strdup(model); }
static void ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ { int i; /* Looping var */ ppd_const_t *oldconst; /* Current UIConstraints data */ ppd_attr_t *constattr; /* Current cupsUIConstraints attribute */ _ppd_cups_uiconsts_t *consts; /* Current cupsUIConstraints data */ _ppd_cups_uiconst_t *constptr; /* Current constraint */ ppd_group_t *installable; /* Installable options group */ const char *vptr; /* Pointer into constraint value */ char option[PPD_MAX_NAME], /* Option name/MainKeyword */ choice[PPD_MAX_NAME], /* Choice/OptionKeyword */ *ptr; /* Pointer into option or choice */ DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd)); /* * Create an array to hold the constraint data... */ ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL); /* * Find the installable options group if it exists... */ for (i = ppd->num_groups, installable = ppd->groups; i > 0; i --, installable ++) if (!_cups_strcasecmp(installable->name, "InstallableOptions")) break; if (i <= 0) installable = NULL; /* * Load old-style [Non]UIConstraints data... */ for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++) { /* * Weed out nearby duplicates, since the PPD spec requires that you * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"... */ if (i > 1 && !_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) && !_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) && !_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) && !_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1)) continue; /* * Allocate memory... */ if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL) { DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "UIConstraints!"); return; } if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL) { free(consts); DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "UIConstraints!"); return; } /* * Fill in the information... */ consts->num_constraints = 2; consts->constraints = constptr; if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) && !_cups_strcasecmp(oldconst->choice1, "True")) { constptr[0].option = ppdFindOption(ppd, oldconst->option1 + 6); constptr[0].choice = ppdFindChoice(constptr[0].option, "Custom"); constptr[0].installable = 0; } else { constptr[0].option = ppdFindOption(ppd, oldconst->option1); constptr[0].choice = ppdFindChoice(constptr[0].option, oldconst->choice1); constptr[0].installable = ppd_is_installable(installable, oldconst->option1); } if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", oldconst->option1, oldconst->choice1)); free(consts->constraints); free(consts); continue; } if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) && !_cups_strcasecmp(oldconst->choice2, "True")) { constptr[1].option = ppdFindOption(ppd, oldconst->option2 + 6); constptr[1].choice = ppdFindChoice(constptr[1].option, "Custom"); constptr[1].installable = 0; } else { constptr[1].option = ppdFindOption(ppd, oldconst->option2); constptr[1].choice = ppdFindChoice(constptr[1].option, oldconst->choice2); constptr[1].installable = ppd_is_installable(installable, oldconst->option2); } if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", oldconst->option2, oldconst->choice2)); free(consts->constraints); free(consts); continue; } consts->installable = constptr[0].installable || constptr[1].installable; /* * Add it to the constraints array... */ cupsArrayAdd(ppd->cups_uiconstraints, consts); } /* * Then load new-style constraints... */ for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL); constattr; constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL)) { if (!constattr->value) { DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!"); continue; } for (i = 0, vptr = strchr(constattr->value, '*'); vptr; i ++, vptr = strchr(vptr + 1, '*')); if (i == 0) { DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!"); continue; } if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL) { DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "cupsUIConstraints!"); return; } if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL) { free(consts); DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for " "cupsUIConstraints!"); return; } consts->num_constraints = i; consts->constraints = constptr; strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver)); for (i = 0, vptr = strchr(constattr->value, '*'); vptr; i ++, vptr = strchr(vptr, '*'), constptr ++) { /* * Extract "*Option Choice" or just "*Option"... */ for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++) if (ptr < (option + sizeof(option) - 1)) *ptr++ = *vptr; *ptr = '\0'; while (_cups_isspace(*vptr)) vptr ++; if (*vptr == '*') choice[0] = '\0'; else { for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++) if (ptr < (choice + sizeof(choice) - 1)) *ptr++ = *vptr; *ptr = '\0'; } if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True")) { _cups_strcpy(option, option + 6); strlcpy(choice, "Custom", sizeof(choice)); } constptr->option = ppdFindOption(ppd, option); constptr->choice = ppdFindChoice(constptr->option, choice); constptr->installable = ppd_is_installable(installable, option); consts->installable |= constptr->installable; if (!constptr->option || (!constptr->choice && choice[0])) { DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!", option, choice)); break; } } if (!vptr) cupsArrayAdd(ppd->cups_uiconstraints, consts); else { free(consts->constraints); free(consts); } } }