int /* O - 0 on success, -1 on error */ ppdLocalize(ppd_file_t *ppd) /* I - PPD file */ { int i, j, k; /* Looping vars */ ppd_group_t *group; /* Current group */ ppd_option_t *option; /* Current option */ ppd_choice_t *choice; /* Current choice */ ppd_coption_t *coption; /* Current custom option */ ppd_cparam_t *cparam; /* Current custom parameter */ ppd_attr_t *attr, /* Current attribute */ *locattr; /* Localized attribute */ char ckeyword[PPD_MAX_NAME], /* Custom keyword */ ll_CC[6]; /* Language + country locale */ /* * Range check input... */ DEBUG_printf(("ppdLocalize(ppd=%p)", ppd)); if (!ppd) return (-1); /* * Get the default language... */ ppd_ll_CC(ll_CC, sizeof(ll_CC)); /* * Now lookup all of the groups, options, choices, etc. */ for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) { if ((locattr = _ppdLocalizedAttr(ppd, "Translation", group->name, ll_CC)) != NULL) strlcpy(group->text, locattr->text, sizeof(group->text)); for (j = group->num_options, option = group->options; j > 0; j --, option ++) { if ((locattr = _ppdLocalizedAttr(ppd, "Translation", option->keyword, ll_CC)) != NULL) strlcpy(option->text, locattr->text, sizeof(option->text)); for (k = option->num_choices, choice = option->choices; k > 0; k --, choice ++) { if (strcmp(choice->choice, "Custom") || !ppdFindCustomOption(ppd, option->keyword)) locattr = _ppdLocalizedAttr(ppd, option->keyword, choice->choice, ll_CC); else { snprintf(ckeyword, sizeof(ckeyword), "Custom%s", option->keyword); locattr = _ppdLocalizedAttr(ppd, ckeyword, "True", ll_CC); } if (locattr) strlcpy(choice->text, locattr->text, sizeof(choice->text)); } } } /* * Translate any custom parameters... */ for (coption = (ppd_coption_t *)cupsArrayFirst(ppd->coptions); coption; coption = (ppd_coption_t *)cupsArrayNext(ppd->coptions)) { for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); cparam; cparam = (ppd_cparam_t *)cupsArrayNext(coption->params)) { snprintf(ckeyword, sizeof(ckeyword), "ParamCustom%s", coption->keyword); if ((locattr = _ppdLocalizedAttr(ppd, ckeyword, cparam->name, ll_CC)) != NULL) strlcpy(cparam->text, locattr->text, sizeof(cparam->text)); } } /* * Translate ICC profile names... */ if ((attr = ppdFindAttr(ppd, "APCustomColorMatchingName", NULL)) != NULL) { if ((locattr = _ppdLocalizedAttr(ppd, "APCustomColorMatchingName", attr->spec, ll_CC)) != NULL) strlcpy(attr->text, locattr->text, sizeof(attr->text)); } for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); attr; attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL)) { cupsArraySave(ppd->sorted_attrs); if ((locattr = _ppdLocalizedAttr(ppd, "cupsICCProfile", attr->spec, ll_CC)) != NULL) strlcpy(attr->text, locattr->text, sizeof(attr->text)); cupsArrayRestore(ppd->sorted_attrs); } /* * Translate printer presets... */ for (attr = ppdFindAttr(ppd, "APPrinterPreset", NULL); attr; attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) { cupsArraySave(ppd->sorted_attrs); if ((locattr = _ppdLocalizedAttr(ppd, "APPrinterPreset", attr->spec, ll_CC)) != NULL) strlcpy(attr->text, locattr->text, sizeof(attr->text)); cupsArrayRestore(ppd->sorted_attrs); } return (0); }
static void apple_register_profiles( cupsd_printer_t *p) /* I - Printer */ { int i; /* Looping var */ char ppdfile[1024], /* PPD filename */ iccfile[1024], /* ICC filename */ selector[PPD_MAX_NAME]; /* Profile selection string */ ppd_file_t *ppd; /* PPD file */ ppd_attr_t *attr, /* Profile attributes */ *profileid_attr,/* cupsProfileID attribute */ *q1_attr, /* ColorModel (or other) qualifier */ *q2_attr, /* MediaType (or other) qualifier */ *q3_attr; /* Resolution (or other) qualifier */ char q_keyword[PPD_MAX_NAME]; /* Qualifier keyword */ const char *q1_choice, /* ColorModel (or other) choice */ *q2_choice, /* MediaType (or other) choice */ *q3_choice; /* Resolution (or other) choice */ ppd_option_t *cm_option; /* Color model option */ ppd_choice_t *cm_choice; /* Color model choice */ int num_profiles; /* Number of profiles */ OSStatus error = 0; /* Last error */ unsigned device_id, /* Printer device ID */ profile_id = 0, /* Profile ID */ default_profile_id = 0; /* Default profile ID */ CFMutableDictionaryRef device_name; /* Printer device name dictionary */ CFStringRef printer_name; /* Printer name string */ cups_array_t *languages; /* Languages array */ CFMutableDictionaryRef profiles, /* Dictionary of profiles */ profile; /* Current profile info dictionary */ CFStringRef dict_key; /* Key in factory profile dictionary */ /* * Make sure ColorSync is available... */ if (&ColorSyncRegisterDevice == NULL) return; /* * Try opening the PPD file for this printer... */ snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name); if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL) return; /* * See if we have any profiles... */ for (num_profiles = 0, attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); attr; attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL)) if (attr->spec[0] && attr->value && attr->value[0]) { if (attr->value[0] != '/') snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, attr->value); else strlcpy(iccfile, attr->value, sizeof(iccfile)); if (access(iccfile, 0)) { cupsdLogMessage(CUPSD_LOG_ERROR, "%s: ICC Profile \"%s\" does not exist.", p->name, iccfile); cupsdSetPrinterReasons(p, "+cups-missing-filter-warning"); continue; } num_profiles ++; } /* * Create a dictionary for the factory profiles... */ profiles = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!profiles) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for factory profiles."); ppdClose(ppd); return; } /* * If we have profiles, add them... */ if (num_profiles > 0) { /* * For CUPS PPDs, figure out the default profile selector values... */ if ((attr = ppdFindAttr(ppd, "cupsICCQualifier1", NULL)) != NULL && attr->value && attr->value[0]) { snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); q1_attr = ppdFindAttr(ppd, q_keyword, NULL); } else if ((q1_attr = ppdFindAttr(ppd, "DefaultColorModel", NULL)) == NULL) q1_attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); if (q1_attr && q1_attr->value && q1_attr->value[0]) q1_choice = q1_attr->value; else q1_choice = ""; if ((attr = ppdFindAttr(ppd, "cupsICCQualifier2", NULL)) != NULL && attr->value && attr->value[0]) { snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); q2_attr = ppdFindAttr(ppd, q_keyword, NULL); } else q2_attr = ppdFindAttr(ppd, "DefaultMediaType", NULL); if (q2_attr && q2_attr->value && q2_attr->value[0]) q2_choice = q2_attr->value; else q2_choice = NULL; if ((attr = ppdFindAttr(ppd, "cupsICCQualifier3", NULL)) != NULL && attr->value && attr->value[0]) { snprintf(q_keyword, sizeof(q_keyword), "Default%s", attr->value); q3_attr = ppdFindAttr(ppd, q_keyword, NULL); } else q3_attr = ppdFindAttr(ppd, "DefaultResolution", NULL); if (q3_attr && q3_attr->value && q3_attr->value[0]) q3_choice = q3_attr->value; else q3_choice = NULL; /* * Loop through the profiles listed in the PPD... */ languages = _ppdGetLanguages(ppd); for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); attr; attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL)) if (attr->spec[0] && attr->value && attr->value[0]) { /* * Add this profile... */ if (attr->value[0] != '/') snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, attr->value); else strlcpy(iccfile, attr->value, sizeof(iccfile)); if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser, cupsdLogFCMessage, p)) iccfile[0] = '\0'; cupsArraySave(ppd->sorted_attrs); if ((profileid_attr = ppdFindAttr(ppd, "cupsProfileID", attr->spec)) != NULL && profileid_attr->value && isdigit(profileid_attr->value[0] & 255)) profile_id = (unsigned)strtoul(profileid_attr->value, NULL, 10); else profile_id = _ppdHashName(attr->spec); cupsArrayRestore(ppd->sorted_attrs); profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!profile) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for color profile."); CFRelease(profiles); ppdClose(ppd); return; } apple_init_profile(ppd, languages, profile, profile_id, attr->spec, attr->text[0] ? attr->text : attr->spec, iccfile); dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), profile_id); if (dict_key) { CFDictionarySetValue(profiles, dict_key, profile); CFRelease(dict_key); } CFRelease(profile); /* * See if this is the default profile... */ if (!default_profile_id && q1_choice && q2_choice && q3_choice) { snprintf(selector, sizeof(selector), "%s.%s.%s", q1_choice, q2_choice, q3_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q1_choice && q2_choice) { snprintf(selector, sizeof(selector), "%s.%s.", q1_choice, q2_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q1_choice && q3_choice) { snprintf(selector, sizeof(selector), "%s..%s", q1_choice, q3_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q1_choice) { snprintf(selector, sizeof(selector), "%s..", q1_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q2_choice && q3_choice) { snprintf(selector, sizeof(selector), ".%s.%s", q2_choice, q3_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q2_choice) { snprintf(selector, sizeof(selector), ".%s.", q2_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } if (!default_profile_id && q3_choice) { snprintf(selector, sizeof(selector), "..%s", q3_choice); if (!strcmp(selector, attr->spec)) default_profile_id = profile_id; } } _ppdFreeLanguages(languages); } else if ((cm_option = ppdFindOption(ppd, "ColorModel")) != NULL) { /* * Extract profiles from ColorModel option... */ const char *profile_name; /* Name of generic profile */ num_profiles = cm_option->num_choices; for (i = cm_option->num_choices, cm_choice = cm_option->choices; i > 0; i --, cm_choice ++) { if (!strcmp(cm_choice->choice, "Gray") || !strcmp(cm_choice->choice, "Black")) profile_name = "Gray"; else if (!strcmp(cm_choice->choice, "RGB") || !strcmp(cm_choice->choice, "CMY")) profile_name = "RGB"; else if (!strcmp(cm_choice->choice, "CMYK") || !strcmp(cm_choice->choice, "KCMY")) profile_name = "CMYK"; else profile_name = "DeviceN"; snprintf(selector, sizeof(selector), "%s..", profile_name); profile_id = _ppdHashName(selector); profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!profile) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for color profile."); CFRelease(profiles); ppdClose(ppd); return; } apple_init_profile(ppd, NULL, profile, profile_id, cm_choice->choice, cm_choice->text, NULL); dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), profile_id); if (dict_key) { CFDictionarySetValue(profiles, dict_key, profile); CFRelease(dict_key); } CFRelease(profile); if (cm_choice->marked) default_profile_id = profile_id; } } else { /* * Use the default colorspace... */ attr = ppdFindAttr(ppd, "DefaultColorSpace", NULL); num_profiles = (attr && ppd->colorspace == PPD_CS_GRAY) ? 1 : 2; /* * Add the grayscale profile first. We always have a grayscale profile. */ profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!profile) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for color profile."); CFRelease(profiles); ppdClose(ppd); return; } profile_id = _ppdHashName("Gray.."); apple_init_profile(ppd, NULL, profile, profile_id, "Gray", "Gray", NULL); dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), profile_id); if (dict_key) { CFDictionarySetValue(profiles, dict_key, profile); CFRelease(dict_key); } CFRelease(profile); /* * Then add the RGB/CMYK/DeviceN color profile... */ profile = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!profile) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to allocate memory for color profile."); CFRelease(profiles); ppdClose(ppd); return; } switch (ppd->colorspace) { default : case PPD_CS_RGB : case PPD_CS_CMY : profile_id = _ppdHashName("RGB.."); apple_init_profile(ppd, NULL, profile, profile_id, "RGB", "RGB", NULL); break; case PPD_CS_RGBK : case PPD_CS_CMYK : profile_id = _ppdHashName("CMYK.."); apple_init_profile(ppd, NULL, profile, profile_id, "CMYK", "CMYK", NULL); break; case PPD_CS_GRAY : if (attr) break; case PPD_CS_N : profile_id = _ppdHashName("DeviceN.."); apple_init_profile(ppd, NULL, profile, profile_id, "DeviceN", "DeviceN", NULL); break; } if (CFDictionaryGetCount(profile) > 0) { dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), profile_id); if (dict_key) { CFDictionarySetValue(profiles, dict_key, profile); CFRelease(dict_key); } } CFRelease(profile); } if (num_profiles > 0) { /* * Make sure we have a default profile ID... */ if (!default_profile_id) default_profile_id = profile_id; /* Last profile */ dict_key = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%u"), default_profile_id); if (dict_key) { CFDictionarySetValue(profiles, kColorSyncDeviceDefaultProfileID, dict_key); CFRelease(dict_key); } /* * Get the device ID hash and pathelogical name dictionary. */ cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\"", p->name); device_id = _ppdHashName(p->name); device_name = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); printer_name = CFStringCreateWithCString(kCFAllocatorDefault, p->name, kCFStringEncodingUTF8); if (device_name && printer_name) { /* * Register the device with ColorSync... */ CFTypeRef deviceDictKeys[] = { /* Device keys */ kColorSyncDeviceDescriptions, kColorSyncFactoryProfiles, kColorSyncDeviceUserScope, kColorSyncDeviceHostScope }; CFTypeRef deviceDictVals[] = { /* Device values */ device_name, profiles, kCFPreferencesAnyUser, kCFPreferencesCurrentHost }; CFDictionaryRef deviceDict; /* Device dictionary */ CFUUIDRef deviceUUID; /* Device UUID */ CFDictionarySetValue(device_name, CFSTR("en_US"), printer_name); deviceDict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)deviceDictKeys, (const void **)deviceDictVals, sizeof(deviceDictKeys) / sizeof(deviceDictKeys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); deviceUUID = ColorSyncCreateUUIDFromUInt32(device_id); if (!deviceDict || !deviceUUID || !ColorSyncRegisterDevice(kColorSyncPrinterDeviceClass, deviceUUID, deviceDict)) error = 1001; if (deviceUUID) CFRelease(deviceUUID); if (deviceDict) CFRelease(deviceDict); } else error = 1000; /* * Clean up... */ if (error != noErr) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to register ICC color profiles for \"%s\": %d", p->name, (int)error); if (printer_name) CFRelease(printer_name); if (device_name) CFRelease(device_name); } /* * Free any memory we used... */ CFRelease(profiles); ppdClose(ppd); }
static void colord_register_printer( cupsd_printer_t *p) /* I - printer */ { char ppdfile[1024], /* PPD filename */ iccfile[1024]; /* ICC filename */ ppd_file_t *ppd; /* PPD file */ cups_array_t *profiles; /* Profile paths array */ ppd_attr_t *attr; /* Profile attributes */ const char *device_colorspace; /* Device colorspace */ char *format[3]; /* Qualifier format tuple */ /* * Ensure we have a D-Bus connection... */ if (!colord_con) return; /* * Try opening the PPD file for this printer... */ snprintf(ppdfile, sizeof(ppdfile), "%s/ppd/%s.ppd", ServerRoot, p->name); if ((ppd = _ppdOpenFile(ppdfile, _PPD_LOCALIZATION_ICC_PROFILES)) == NULL) return; /* * Find out the qualifier format */ colord_get_qualifier_format(ppd, format); /* * See if we have any embedded profiles... */ profiles = cupsArrayNew3(NULL, NULL, NULL, 0, (cups_acopy_func_t)strdup, (cups_afree_func_t)free); for (attr = ppdFindAttr(ppd, "cupsICCProfile", NULL); attr; attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL)) if (attr->spec[0] && attr->value && attr->value[0]) { if (attr->value[0] != '/') snprintf(iccfile, sizeof(iccfile), "%s/profiles/%s", DataDir, attr->value); else strlcpy(iccfile, attr->value, sizeof(iccfile)); if (_cupsFileCheck(iccfile, _CUPS_FILE_CHECK_FILE, !RunUser, cupsdLogFCMessage, p)) continue; colord_create_profile(profiles, p->name, attr->spec, COLORD_SPACE_UNKNOWN, format, iccfile, COLORD_SCOPE_TEMP); } /* * Add the grayscale profile first. We always have a grayscale profile. */ colord_create_profile(profiles, p->name, "Gray..", COLORD_SPACE_GRAY, format, NULL, COLORD_SCOPE_TEMP); /* * Then add the RGB/CMYK/DeviceN color profile... */ device_colorspace = "unknown"; switch (ppd->colorspace) { case PPD_CS_RGB : case PPD_CS_CMY : device_colorspace = COLORD_SPACE_RGB; colord_create_profile(profiles, p->name, "RGB..", COLORD_SPACE_RGB, format, NULL, COLORD_SCOPE_TEMP); break; case PPD_CS_RGBK : case PPD_CS_CMYK : device_colorspace = COLORD_SPACE_CMYK; colord_create_profile(profiles, p->name, "CMYK..", COLORD_SPACE_CMYK, format, NULL, COLORD_SCOPE_TEMP); break; case PPD_CS_GRAY : device_colorspace = COLORD_SPACE_GRAY; break; case PPD_CS_N : colord_create_profile(profiles, p->name, "DeviceN..", COLORD_SPACE_UNKNOWN, format, NULL, COLORD_SCOPE_TEMP); break; } /* * Register the device with colord. */ cupsdLogMessage(CUPSD_LOG_INFO, "Registering ICC color profiles for \"%s\".", p->name); colord_create_device(p, ppd, profiles, device_colorspace, format, COLORD_RELATION_SOFT, COLORD_SCOPE_TEMP); /* * Free any memory we used... */ cupsArrayDelete(profiles); free(format[0]); free(format[1]); free(format[2]); ppdClose(ppd); }
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); } } }
int /* O - Number of options marked */ ppdCollect2(ppd_file_t *ppd, /* I - PPD file data */ ppd_section_t section, /* I - Section to collect */ float min_order, /* I - Minimum OrderDependency value */ ppd_choice_t ***choices) /* O - Pointers to choices */ { ppd_choice_t *c; /* Current choice */ ppd_section_t csection; /* Current section */ float corder; /* Current OrderDependency value */ int count; /* Number of choices collected */ ppd_choice_t **collect; /* Collected choices */ float *orders; /* Collected order values */ DEBUG_printf(("ppdCollect2(ppd=%p, section=%d, min_order=%f, choices=%p)", ppd, section, min_order, choices)); if (!ppd || !choices) { if (choices) *choices = NULL; return (0); } /* * Allocate memory for up to N selected choices... */ count = 0; if ((collect = calloc(sizeof(ppd_choice_t *), cupsArrayCount(ppd->marked))) == NULL) { *choices = NULL; return (0); } if ((orders = calloc(sizeof(float), cupsArrayCount(ppd->marked))) == NULL) { *choices = NULL; free(collect); return (0); } /* * Loop through all options and add choices as needed... */ for (c = (ppd_choice_t *)cupsArrayFirst(ppd->marked); c; c = (ppd_choice_t *)cupsArrayNext(ppd->marked)) { csection = c->option->section; corder = c->option->order; if (!strcmp(c->choice, "Custom")) { ppd_attr_t *attr; /* NonUIOrderDependency value */ float aorder; /* Order value */ char asection[17], /* Section name */ amain[PPD_MAX_NAME + 1], aoption[PPD_MAX_NAME]; /* *CustomFoo and True */ for (attr = ppdFindAttr(ppd, "NonUIOrderDependency", NULL); attr; attr = ppdFindNextAttr(ppd, "NonUIOrderDependency", NULL)) if (attr->value && sscanf(attr->value, "%f%16s%41s%40s", &aorder, asection, amain, aoption) == 4 && !strncmp(amain, "*Custom", 7) && !strcmp(amain + 7, c->option->keyword) && !strcmp(aoption, "True")) { /* * Use this NonUIOrderDependency... */ corder = aorder; if (!strcmp(asection, "DocumentSetup")) csection = PPD_ORDER_DOCUMENT; else if (!strcmp(asection, "ExitServer")) csection = PPD_ORDER_EXIT; else if (!strcmp(asection, "JCLSetup")) csection = PPD_ORDER_JCL; else if (!strcmp(asection, "PageSetup")) csection = PPD_ORDER_PAGE; else if (!strcmp(asection, "Prolog")) csection = PPD_ORDER_PROLOG; else csection = PPD_ORDER_ANY; break; } } if (csection == section && corder >= min_order) { collect[count] = c; orders[count] = corder; count ++; } } /* * If we have more than 1 marked choice, sort them... */ if (count > 1) { int i, j; /* Looping vars */ for (i = 0; i < (count - 1); i ++) for (j = i + 1; j < count; j ++) if (orders[i] > orders[j]) { c = collect[i]; corder = orders[i]; collect[i] = collect[j]; orders[i] = orders[j]; collect[j] = c; orders[j] = corder; } } free(orders); DEBUG_printf(("2ppdCollect2: %d marked choices...", count)); /* * Return the array and number of choices; if 0, free the array since * it isn't needed. */ if (count > 0) { *choices = collect; return (count); } else { *choices = NULL; free(collect); return (0); } }
int /* O - Exit status */ main(int argc, /* I - Number of command-line arguments */ char *argv[]) /* I - Command-line arguments */ { int i; /* Looping var */ ppd_file_t *ppd; /* PPD file loaded from disk */ int status; /* Status of tests (0 = success, 1 = fail) */ int conflicts; /* Number of conflicts */ char *s; /* String */ char buffer[8192]; /* String buffer */ const char *text, /* Localized text */ *val; /* Option value */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ ppd_size_t minsize, /* Minimum size */ maxsize, /* Maximum size */ *size; /* Current size */ ppd_attr_t *attr; /* Current attribute */ _ppd_cache_t *pc; /* PPD cache */ status = 0; if (argc == 1) { /* * Setup directories for locale stuff... */ if (access("locale", 0)) { mkdir("locale", 0777); mkdir("locale/fr", 0777); symlink("../../../locale/cups_fr.po", "locale/fr/cups_fr.po"); mkdir("locale/zh_TW", 0777); symlink("../../../locale/cups_zh_TW.po", "locale/zh_TW/cups_zh_TW.po"); } putenv("LOCALEDIR=locale"); putenv("SOFTWARE=CUPS"); /* * Do tests with test.ppd... */ fputs("ppdOpenFile(test.ppd): ", stdout); if ((ppd = _ppdOpenFile("test.ppd", _PPD_LOCALIZATION_ALL)) != NULL) puts("PASS"); else { ppd_status_t err; /* Last error in file */ int line; /* Line number in file */ status ++; err = ppdLastError(&line); printf("FAIL (%s on line %d)\n", ppdErrorString(err), line); } fputs("ppdFindAttr(wildcard): ", stdout); if ((attr = ppdFindAttr(ppd, "cupsTest", NULL)) == NULL) { status ++; puts("FAIL (not found)"); } else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo")) { status ++; printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); } else puts("PASS"); fputs("ppdFindNextAttr(wildcard): ", stdout); if ((attr = ppdFindNextAttr(ppd, "cupsTest", NULL)) == NULL) { status ++; puts("FAIL (not found)"); } else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Bar")) { status ++; printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); } else puts("PASS"); fputs("ppdFindAttr(Foo): ", stdout); if ((attr = ppdFindAttr(ppd, "cupsTest", "Foo")) == NULL) { status ++; puts("FAIL (not found)"); } else if (strcmp(attr->name, "cupsTest") || strcmp(attr->spec, "Foo")) { status ++; printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); } else puts("PASS"); fputs("ppdFindNextAttr(Foo): ", stdout); if ((attr = ppdFindNextAttr(ppd, "cupsTest", "Foo")) != NULL) { status ++; printf("FAIL (got \"%s %s\")\n", attr->name, attr->spec); } else puts("PASS"); fputs("ppdMarkDefaults: ", stdout); ppdMarkDefaults(ppd); if ((conflicts = ppdConflicts(ppd)) == 0) puts("PASS"); else { status ++; printf("FAIL (%d conflicts)\n", conflicts); } fputs("ppdEmitString (defaults): ", stdout); if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && !strcmp(s, default_code)) puts("PASS"); else { status ++; printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, (int)strlen(default_code)); if (s) puts(s); } if (s) free(s); fputs("ppdEmitString (custom size and string): ", stdout); ppdMarkOption(ppd, "PageSize", "Custom.400x500"); ppdMarkOption(ppd, "StringOption", "{String1=\"value 1\" String2=value(2)}"); if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && !strcmp(s, custom_code)) puts("PASS"); else { status ++; printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, (int)strlen(custom_code)); if (s) puts(s); } if (s) free(s); /* * Test constraints... */ fputs("cupsGetConflicts(InputSlot=Envelope): ", stdout); ppdMarkOption(ppd, "PageSize", "Letter"); num_options = cupsGetConflicts(ppd, "InputSlot", "Envelope", &options); if (num_options != 2 || (val = cupsGetOption("PageRegion", num_options, options)) == NULL || _cups_strcasecmp(val, "Letter") || (val = cupsGetOption("PageSize", num_options, options)) == NULL || _cups_strcasecmp(val, "Letter")) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); status ++; } else puts("PASS"); fputs("ppdConflicts(): ", stdout); ppdMarkOption(ppd, "InputSlot", "Envelope"); if ((conflicts = ppdConflicts(ppd)) == 2) puts("PASS (2)"); else { printf("FAIL (%d)\n", conflicts); status ++; } fputs("cupsResolveConflicts(InputSlot=Envelope): ", stdout); num_options = 0; options = NULL; if (!cupsResolveConflicts(ppd, "InputSlot", "Envelope", &num_options, &options)) { puts("FAIL (Unable to resolve)"); status ++; } else if (num_options != 2 || !cupsGetOption("PageSize", num_options, options)) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); status ++; } else puts("PASS (Resolved by changing PageSize)"); cupsFreeOptions(num_options, options); fputs("cupsResolveConflicts(No option/choice): ", stdout); num_options = 0; options = NULL; if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) && num_options == 1 && !_cups_strcasecmp(options[0].name, "InputSlot") && !_cups_strcasecmp(options[0].value, "Tray")) puts("PASS (Resolved by changing InputSlot)"); else if (num_options > 0) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); status ++; } else { puts("FAIL (Unable to resolve)"); status ++; } cupsFreeOptions(num_options, options); fputs("ppdInstallableConflict(): ", stdout); if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") && !ppdInstallableConflict(ppd, "Duplex", "None")) puts("PASS"); else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble")) { puts("FAIL (Duplex=DuplexNoTumble did not conflict)"); status ++; } else { puts("FAIL (Duplex=None conflicted)"); status ++; } /* * ppdPageSizeLimits */ fputs("ppdPageSizeLimits: ", stdout); if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) { if (minsize.width != 36 || minsize.length != 36 || maxsize.width != 1080 || maxsize.length != 86400) { printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " "expected min=36x36, max=1080x86400)\n", minsize.width, minsize.length, maxsize.width, maxsize.length); status ++; } else puts("PASS"); } else { puts("FAIL (returned 0)"); status ++; } /* * cupsMarkOptions with PWG and IPP size names. */ fputs("cupsMarkOptions(media=iso-a4): ", stdout); num_options = cupsAddOption("media", "iso-a4", 0, &options); cupsMarkOptions(ppd, num_options, options); cupsFreeOptions(num_options, options); size = ppdPageSize(ppd, NULL); if (!size || strcmp(size->name, "A4")) { printf("FAIL (%s)\n", size ? size->name : "unknown"); status ++; } else puts("PASS"); fputs("cupsMarkOptions(media=na_letter_8.5x11in): ", stdout); num_options = cupsAddOption("media", "na_letter_8.5x11in", 0, &options); cupsMarkOptions(ppd, num_options, options); cupsFreeOptions(num_options, options); size = ppdPageSize(ppd, NULL); if (!size || strcmp(size->name, "Letter")) { printf("FAIL (%s)\n", size ? size->name : "unknown"); status ++; } else puts("PASS"); fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout); num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0, &options); cupsMarkOptions(ppd, num_options, options); cupsFreeOptions(num_options, options); size = ppdPageSize(ppd, NULL); if (!size || strcmp(size->name, "Letter.Fullbleed")) { printf("FAIL (%s)\n", size ? size->name : "unknown"); status ++; } else puts("PASS"); fputs("cupsMarkOptions(media=A4): ", stdout); num_options = cupsAddOption("media", "A4", 0, &options); cupsMarkOptions(ppd, num_options, options); cupsFreeOptions(num_options, options); size = ppdPageSize(ppd, NULL); if (!size || strcmp(size->name, "A4")) { printf("FAIL (%s)\n", size ? size->name : "unknown"); status ++; } else puts("PASS"); /* * Custom sizes... */ fputs("cupsMarkOptions(media=Custom.8x10in): ", stdout); num_options = cupsAddOption("media", "Custom.8x10in", 0, &options); cupsMarkOptions(ppd, num_options, options); cupsFreeOptions(num_options, options); size = ppdPageSize(ppd, NULL); if (!size || strcmp(size->name, "Custom") || size->width != 576 || size->length != 720) { printf("FAIL (%s - %gx%g)\n", size ? size->name : "unknown", size ? size->width : 0.0, size ? size->length : 0.0); status ++; } else puts("PASS"); /* * Test localization... */ fputs("ppdLocalizeIPPReason(text): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && !strcmp(buffer, "Foo Reason")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"Foo Reason\")\n", buffer); } fputs("ppdLocalizeIPPReason(http): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", "http", buffer, sizeof(buffer)) && !strcmp(buffer, "http://foo/bar.html")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"http://foo/bar.html\")\n", buffer); } fputs("ppdLocalizeIPPReason(help): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", "help", buffer, sizeof(buffer)) && !strcmp(buffer, "help:anchor='foo'%20bookID=Vendor%20Help")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"help:anchor='foo'%%20bookID=Vendor%%20Help\")\n", buffer); } fputs("ppdLocalizeIPPReason(file): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", "file", buffer, sizeof(buffer)) && !strcmp(buffer, "/help/foo/bar.html")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"/help/foo/bar.html\")\n", buffer); } putenv("LANG=fr"); putenv("LC_ALL=fr"); putenv("LC_CTYPE=fr"); putenv("LC_MESSAGES=fr"); fputs("ppdLocalizeIPPReason(fr text): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && !strcmp(buffer, "La Long Foo Reason")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"La Long Foo Reason\")\n", buffer); } putenv("LANG=zh_TW"); putenv("LC_ALL=zh_TW"); putenv("LC_CTYPE=zh_TW"); putenv("LC_MESSAGES=zh_TW"); fputs("ppdLocalizeIPPReason(zh_TW text): ", stdout); if (ppdLocalizeIPPReason(ppd, "foo", NULL, buffer, sizeof(buffer)) && !strcmp(buffer, "Number 1 Foo Reason")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"Number 1 Foo Reason\")\n", buffer); } /* * cupsMarkerName localization... */ putenv("LANG=en"); putenv("LC_ALL=en"); putenv("LC_CTYPE=en"); putenv("LC_MESSAGES=en"); fputs("ppdLocalizeMarkerName(bogus): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "bogus")) != NULL) { status ++; printf("FAIL (\"%s\" instead of NULL)\n", text); } else puts("PASS"); fputs("ppdLocalizeMarkerName(cyan): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && !strcmp(text, "Cyan Toner")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"Cyan Toner\")\n", text ? text : "(null)"); } putenv("LANG=fr"); putenv("LC_ALL=fr"); putenv("LC_CTYPE=fr"); putenv("LC_MESSAGES=fr"); fputs("ppdLocalizeMarkerName(fr cyan): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && !strcmp(text, "La Toner Cyan")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"La Toner Cyan\")\n", text ? text : "(null)"); } putenv("LANG=zh_TW"); putenv("LC_ALL=zh_TW"); putenv("LC_CTYPE=zh_TW"); putenv("LC_MESSAGES=zh_TW"); fputs("ppdLocalizeMarkerName(zh_TW cyan): ", stdout); if ((text = ppdLocalizeMarkerName(ppd, "cyan")) != NULL && !strcmp(text, "Number 1 Cyan Toner")) puts("PASS"); else { status ++; printf("FAIL (\"%s\" instead of \"Number 1 Cyan Toner\")\n", text ? text : "(null)"); } ppdClose(ppd); /* * Test new constraints... */ fputs("ppdOpenFile(test2.ppd): ", stdout); if ((ppd = ppdOpenFile("test2.ppd")) != NULL) puts("PASS"); else { ppd_status_t err; /* Last error in file */ int line; /* Line number in file */ status ++; err = ppdLastError(&line); printf("FAIL (%s on line %d)\n", ppdErrorString(err), line); } fputs("ppdMarkDefaults: ", stdout); ppdMarkDefaults(ppd); if ((conflicts = ppdConflicts(ppd)) == 0) puts("PASS"); else { status ++; printf("FAIL (%d conflicts)\n", conflicts); } fputs("ppdEmitString (defaults): ", stdout); if ((s = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL && !strcmp(s, default2_code)) puts("PASS"); else { status ++; printf("FAIL (%d bytes instead of %d)\n", s ? (int)strlen(s) : 0, (int)strlen(default2_code)); if (s) puts(s); } if (s) free(s); fputs("ppdConflicts(): ", stdout); ppdMarkOption(ppd, "PageSize", "Env10"); ppdMarkOption(ppd, "InputSlot", "Envelope"); ppdMarkOption(ppd, "Quality", "Photo"); if ((conflicts = ppdConflicts(ppd)) == 1) puts("PASS (1)"); else { printf("FAIL (%d)\n", conflicts); status ++; } fputs("cupsResolveConflicts(Quality=Photo): ", stdout); num_options = 0; options = NULL; if (cupsResolveConflicts(ppd, "Quality", "Photo", &num_options, &options)) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); status ++; } else puts("PASS (Unable to resolve)"); cupsFreeOptions(num_options, options); fputs("cupsResolveConflicts(No option/choice): ", stdout); num_options = 0; options = NULL; if (cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options) && num_options == 1 && !_cups_strcasecmp(options->name, "Quality") && !_cups_strcasecmp(options->value, "Normal")) puts("PASS"); else if (num_options > 0) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); status ++; } else { puts("FAIL (Unable to resolve!)"); status ++; } cupsFreeOptions(num_options, options); fputs("cupsResolveConflicts(loop test): ", stdout); ppdMarkOption(ppd, "PageSize", "A4"); ppdMarkOption(ppd, "InputSlot", "Tray"); ppdMarkOption(ppd, "Quality", "Photo"); num_options = 0; options = NULL; if (!cupsResolveConflicts(ppd, NULL, NULL, &num_options, &options)) puts("PASS"); else if (num_options > 0) { printf("FAIL (%d options:", num_options); for (i = 0; i < num_options; i ++) printf(" %s=%s", options[i].name, options[i].value); puts(")"); } else puts("FAIL (No conflicts!)"); fputs("ppdInstallableConflict(): ", stdout); if (ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble") && !ppdInstallableConflict(ppd, "Duplex", "None")) puts("PASS"); else if (!ppdInstallableConflict(ppd, "Duplex", "DuplexNoTumble")) { puts("FAIL (Duplex=DuplexNoTumble did not conflict)"); status ++; } else { puts("FAIL (Duplex=None conflicted)"); status ++; } /* * ppdPageSizeLimits */ ppdMarkDefaults(ppd); fputs("ppdPageSizeLimits(default): ", stdout); if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) { if (minsize.width != 36 || minsize.length != 36 || maxsize.width != 1080 || maxsize.length != 86400) { printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " "expected min=36x36, max=1080x86400)\n", minsize.width, minsize.length, maxsize.width, maxsize.length); status ++; } else puts("PASS"); } else { puts("FAIL (returned 0)"); status ++; } ppdMarkOption(ppd, "InputSlot", "Manual"); fputs("ppdPageSizeLimits(InputSlot=Manual): ", stdout); if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) { if (minsize.width != 100 || minsize.length != 100 || maxsize.width != 1000 || maxsize.length != 1000) { printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " "expected min=100x100, max=1000x1000)\n", minsize.width, minsize.length, maxsize.width, maxsize.length); status ++; } else puts("PASS"); } else { puts("FAIL (returned 0)"); status ++; } ppdMarkOption(ppd, "Quality", "Photo"); fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) { if (minsize.width != 200 || minsize.length != 200 || maxsize.width != 1000 || maxsize.length != 1000) { printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " "expected min=200x200, max=1000x1000)\n", minsize.width, minsize.length, maxsize.width, maxsize.length); status ++; } else puts("PASS"); } else { puts("FAIL (returned 0)"); status ++; } ppdMarkOption(ppd, "InputSlot", "Tray"); fputs("ppdPageSizeLimits(Quality=Photo): ", stdout); if (ppdPageSizeLimits(ppd, &minsize, &maxsize)) { if (minsize.width != 300 || minsize.length != 300 || maxsize.width != 1080 || maxsize.length != 86400) { printf("FAIL (got min=%.0fx%.0f, max=%.0fx%.0f, " "expected min=300x300, max=1080x86400)\n", minsize.width, minsize.length, maxsize.width, maxsize.length); status ++; } else puts("PASS"); } else { puts("FAIL (returned 0)"); status ++; } } else { const char *filename; /* PPD filename */ struct stat fileinfo; /* File information */ if (!strncmp(argv[1], "-d", 2)) { const char *printer; /* Printer name */ if (argv[1][2]) printer = argv[1] + 2; else if (argv[2]) printer = argv[2]; else { puts("Usage: ./testppd -d printer"); return (1); } filename = cupsGetPPD(printer); if (!filename) { printf("%s: %s\n", printer, cupsLastErrorString()); return (1); } } else filename = argv[1]; if (lstat(filename, &fileinfo)) { printf("%s: %s\n", filename, strerror(errno)); return (1); } if (S_ISLNK(fileinfo.st_mode)) { char realfile[1024]; /* Real file path */ ssize_t realsize; /* Size of real file path */ if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0) strlcpy(realfile, "Unknown", sizeof(realfile)); else realfile[realsize] = '\0'; if (stat(realfile, &fileinfo)) printf("%s: symlink to \"%s\", %s\n", filename, realfile, strerror(errno)); else printf("%s: symlink to \"%s\", %ld bytes\n", filename, realfile, (long)fileinfo.st_size); } else printf("%s: regular file, %ld bytes\n", filename, (long)fileinfo.st_size); if ((ppd = ppdOpenFile(filename)) == NULL) { ppd_status_t err; /* Last error in file */ int line; /* Line number in file */ status ++; err = ppdLastError(&line); printf("%s: %s on line %d\n", argv[1], ppdErrorString(err), line); } else { int j, k; /* Looping vars */ ppd_group_t *group; /* Option group */ ppd_option_t *option; /* Option */ ppd_coption_t *coption; /* Custom option */ ppd_cparam_t *cparam; /* Custom parameter */ ppd_const_t *c; /* UIConstraints */ char lang[255], /* LANG environment variable */ lc_all[255], /* LC_ALL environment variable */ lc_ctype[255], /* LC_CTYPE environment variable */ lc_messages[255];/* LC_MESSAGES environment variable */ if (argc > 2) { snprintf(lang, sizeof(lang), "LANG=%s", argv[2]); putenv(lang); snprintf(lc_all, sizeof(lc_all), "LC_ALL=%s", argv[2]); putenv(lc_all); snprintf(lc_ctype, sizeof(lc_ctype), "LC_CTYPE=%s", argv[2]); putenv(lc_ctype); snprintf(lc_messages, sizeof(lc_messages), "LC_MESSAGES=%s", argv[2]); putenv(lc_messages); } ppdLocalize(ppd); ppdMarkDefaults(ppd); if (argc > 3) { text = ppdLocalizeIPPReason(ppd, argv[3], NULL, buffer, sizeof(buffer)); printf("ppdLocalizeIPPReason(%s)=%s\n", argv[3], text ? text : "(null)"); return (text == NULL); } for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) { printf("%s (%s):\n", group->name, group->text); for (j = group->num_options, option = group->options; j > 0; j --, option ++) { printf(" %s (%s):\n", option->keyword, option->text); for (k = 0; k < option->num_choices; k ++) printf(" - %s%s (%s)\n", option->choices[k].marked ? "*" : "", option->choices[k].choice, option->choices[k].text); if ((coption = ppdFindCustomOption(ppd, option->keyword)) != NULL) { for (cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params); cparam; cparam = (ppd_cparam_t *)cupsArrayNext(coption->params)) { switch (cparam->type) { case PPD_CUSTOM_CURVE : printf(" %s(%s): PPD_CUSTOM_CURVE (%g to %g)\n", cparam->name, cparam->text, cparam->minimum.custom_curve, cparam->maximum.custom_curve); break; case PPD_CUSTOM_INT : printf(" %s(%s): PPD_CUSTOM_INT (%d to %d)\n", cparam->name, cparam->text, cparam->minimum.custom_int, cparam->maximum.custom_int); break; case PPD_CUSTOM_INVCURVE : printf(" %s(%s): PPD_CUSTOM_INVCURVE (%g to %g)\n", cparam->name, cparam->text, cparam->minimum.custom_invcurve, cparam->maximum.custom_invcurve); break; case PPD_CUSTOM_PASSCODE : printf(" %s(%s): PPD_CUSTOM_PASSCODE (%d to %d)\n", cparam->name, cparam->text, cparam->minimum.custom_passcode, cparam->maximum.custom_passcode); break; case PPD_CUSTOM_PASSWORD : printf(" %s(%s): PPD_CUSTOM_PASSWORD (%d to %d)\n", cparam->name, cparam->text, cparam->minimum.custom_password, cparam->maximum.custom_password); break; case PPD_CUSTOM_POINTS : printf(" %s(%s): PPD_CUSTOM_POINTS (%g to %g)\n", cparam->name, cparam->text, cparam->minimum.custom_points, cparam->maximum.custom_points); break; case PPD_CUSTOM_REAL : printf(" %s(%s): PPD_CUSTOM_REAL (%g to %g)\n", cparam->name, cparam->text, cparam->minimum.custom_real, cparam->maximum.custom_real); break; case PPD_CUSTOM_STRING : printf(" %s(%s): PPD_CUSTOM_STRING (%d to %d)\n", cparam->name, cparam->text, cparam->minimum.custom_string, cparam->maximum.custom_string); break; } } } } } puts("\nSizes:"); for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++) printf(" %s = %gx%g, [%g %g %g %g]\n", size->name, size->width, size->length, size->left, size->bottom, size->right, size->top); puts("\nConstraints:"); for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++) printf(" *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1, c->option2, c->choice2); if (ppd->num_consts == 0) puts(" NO CONSTRAINTS"); puts("\nFilters:"); for (i = 0; i < ppd->num_filters; i ++) printf(" %s\n", ppd->filters[i]); if (ppd->num_filters == 0) puts(" NO FILTERS"); puts("\nAttributes:"); for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs); attr; attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec, attr->text, attr->value ? attr->value : ""); puts("\nPPD Cache:"); if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL) printf(" Unable to create: %s\n", cupsLastErrorString()); else { _ppdCacheWriteFile(pc, "t.cache", NULL); puts(" Wrote t.cache."); } } if (!strncmp(argv[1], "-d", 2)) unlink(filename); } #ifdef __APPLE__ if (getenv("MallocStackLogging") && getenv("MallocStackLoggingNoCompact")) { char command[1024]; /* malloc_history command */ snprintf(command, sizeof(command), "malloc_history %d -all_by_size", getpid()); fflush(stdout); system(command); } #endif /* __APPLE__ */ ppdClose(ppd); return (status); }