CHANGES IN CUPS V1.6.2
- - Documentation fixes
+ - Documentation fixes (STR #4239)
- Security: All file, directory, user, and group settings are now stored
in a separate cups-files.conf configuration file that cannot be set
through the CUPS web interface or APIs (STR #4223)
+ - The XML output of ipptool contained empty dictionaries (STR #4136)
+ - The scheduler did not delete job control backup files (STR #4244)
+ - cupsGetPPD3 could return a local PPD instead of the correct remote
+ PPD.
+ - The scheduler incorrectly advertised auth-info-required for local
+ queues needing local authentication (STR #4205)
+ - CUPS 1.6 clients using the ServerName directive in client.conf did not
+ work with CUPS 1.3.x or older servers (STR #4231)
- The SNMP backend now tries to work around broken printers that use a
newline to separate key/value pairs.
- The IPP backend did not send a cancel request to printers when a job
fi
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
- for file in $(TARGETS); do \
+ for file in $(RBACKENDS) $(UBACKENDS); do \
cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
done \
fi
value[256], /* Value string */
make_and_model[512], /* Manufacturer and model */
model[256], /* Model */
+ pdl[256], /* PDL */
device_id[2048]; /* 1284 device ID */
device_id[0] = '\0';
make_and_model[0] = '\0';
+ pdl[0] = '\0';
strlcpy(model, "Unknown", 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 ||
}
}
+ 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++ = toupper(*ptr++ & 255);
+ else
+ break;
+ }
+
+ *valptr = '\0';
+ }
+
+ ptr = device_id + strlen(device_id);
+ snprintf(ptr, sizeof(device_id) - (ptr - device_id), "CMD:%s;",
+ value + 1);
+ }
+
if (device_id[0])
device->device_id = strdup(device_id);
else
sizeof(prtMarkerSuppliesSupplyUnit[0]));
/* Offset to supply index */
-static const backend_state_t const printer_states[] =
+static const backend_state_t printer_states[] =
{
/* { CUPS_TC_lowPaper, "media-low-report" }, */
{ CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
{ CUPS_TC_outputFull, "output-area-full-warning" }
};
-static const backend_state_t const supply_states[] =
+static const backend_state_t supply_states[] =
{
{ CUPS_DEVELOPER_LOW, "developer-low-report" },
{ CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
$(INSTALL_DIR) $(SYMROOT); \
for file in $(TARGETS); do \
cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
done \
fi
#
# Configuration file makefile for CUPS.
#
-# Copyright 2007-2011 by Apple Inc.
+# Copyright 2007-2012 by Apple Inc.
# Copyright 1993-2006 by Easy Software Products.
#
# These coded instructions, statements, and computer programs are the
#DataDir @CUPS_DATADIR@
# Location of the static web content served by the scheduler...
-#DocRoot @CUPS_DOCROOT@
+#DocumentRoot @CUPS_DOCROOT@
# Location of the file logging all messages produced by the scheduler and any
# helper programs; may be the name "syslog". If not an absolute path, the value
uarch=`uname -m`
case "$uname" in
+ Darwin*)
+ uname="Darwin"
+ if test $uversion -lt 120; then
+ AC_MSG_ERROR([Sorry, this version of CUPS requires OS X 10.8 or higher.])
+ fi
+ ;;
+
GNU* | GNU/*)
uname="GNU"
;;
AC_CHECK_HEADER(Security/SecIdentitySearchPriv.h,
AC_DEFINE(HAVE_SECIDENTITYSEARCHPRIV_H))
- dnl Check for SecCertificateCopyData..
- AC_MSG_CHECKING(for SecCertificateCopyData)
- if test $uversion -ge 100; then
- AC_DEFINE(HAVE_SECCERTIFICATECOPYDATA)
- AC_MSG_RESULT(yes)
- else
- AC_MSG_RESULT(no)
- fi
-
- dnl Check for SecIdentitySearchCreateWithPolicy...
- AC_MSG_CHECKING(for SecIdentitySearchCreateWithPolicy)
- if test $uversion -ge 80; then
- AC_DEFINE(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
- AC_MSG_RESULT(yes)
- else
- AC_MSG_RESULT(no)
- fi
-
- dnl Check for SecPolicyCreateSSL...
- AC_MSG_CHECKING(for SecPolicyCreateSSL)
- if test $uversion -ge 110; then
- AC_DEFINE(HAVE_SECPOLICYCREATESSL)
- AC_MSG_RESULT(yes)
- else
- AC_MSG_RESULT(no)
- fi])
-
- AC_DEFINE(HAVE_CSSMERRORSTRING)
+ AC_DEFINE(HAVE_CSSMERRORSTRING)])
fi
fi
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
cp $(LIBCUPS) $(SYMROOT); \
+ dsymutil $(SYMROOT)/$(LIBCUPS); \
fi
installstatic:
int thread_id; /* Friendly thread ID */
# endif /* DEBUG */
+ /* dest.c, util.c */
+ int server_version; /* Server IPP version */
+
/* file.c */
cups_file_t *stdio_files[3];/* stdin, stdout, stderr */
char optname[1024], /* Option name */
value[2048], /* Option value */
*ptr; /* Pointer into name/value */
+ _cups_globals_t *cg = _cupsGlobals(); /* Thread global data */
static const char * const pattrs[] = /* Attributes we're interested in */
{
"auth-info-required",
appleGetPaperSize(media_default, sizeof(media_default));
#endif /* __APPLE__ */
- /*
- * Build a CUPS_GET_PRINTERS or IPP_GET_PRINTER_ATTRIBUTES request, which
- * require the following attributes:
- *
- * attributes-charset
- * attributes-natural-language
- * requesting-user-name
- * printer-uri [for IPP_GET_PRINTER_ATTRIBUTES]
- */
+ for (;;)
+ {
+ /*
+ * Build a CUPS_GET_PRINTERS or IPP_GET_PRINTER_ATTRIBUTES request, which
+ * require the following attributes:
+ *
+ * attributes-charset
+ * attributes-natural-language
+ * requesting-user-name
+ * printer-uri [for IPP_GET_PRINTER_ATTRIBUTES]
+ */
- request = ippNewRequest(op);
+ request = ippNewRequest(op);
- ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
- "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
- NULL, pattrs);
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
- "requesting-user-name", NULL, cupsUser());
+ ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+ "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+ NULL, pattrs);
- if (name && op != CUPS_GET_DEFAULT)
- {
- httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
- "localhost", ippPort(), "/printers/%s", name);
- ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
- uri);
- }
- else if (mask)
- {
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
- type);
- ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
- mask);
- }
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+ "requesting-user-name", NULL, cupsUser());
- /*
- * Do the request and get back a response...
- */
+ if (name && op != CUPS_GET_DEFAULT)
+ {
+ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+ "localhost", ippPort(), "/printers/%s", name);
+ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+ uri);
+ }
+ else if (mask)
+ {
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+ type);
+ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+ mask);
+ }
+
+ /*
+ * Do the request and get back a response...
+ */
+
+ response = cupsDoRequest(http, request, "/");
+ if (cg->server_version != 20 || !response ||
+ cupsLastError() != IPP_BAD_REQUEST)
+ break;
+
+ /*
+ * Retry as an IPP/1.1 request...
+ */
+
+ cg->server_version = 11;
+ ippDelete(response);
+ }
- if ((response = cupsDoRequest(http, request, "/")) != NULL)
+ if (response)
{
for (attr = response->attrs; attr != NULL; attr = attr->next)
{
*/
memset(cg, 0, sizeof(_cups_globals_t));
- cg->encryption = (http_encryption_t)-1;
- cg->password_cb = (cups_password_cb2_t)_cupsGetPassword;
- cg->any_root = 1;
- cg->expired_certs = 1;
- cg->expired_root = 1;
+ cg->encryption = (http_encryption_t)-1;
+ cg->password_cb = (cups_password_cb2_t)_cupsGetPassword;
+ cg->any_root = 1;
+ cg->expired_certs = 1;
+ cg->expired_root = 1;
+ cg->server_version = 20;
#ifdef DEBUG
/*
return (ippPort());
}
+/* For OS X 10.8 and earlier */
+int _httpAddrPort(http_addr_t *addr) { return (httpAddrPort(addr)); }
+
/*
* '_httpAddrSetPort()' - Set the port number associated with an address.
/**** New in CUPS 1.1.20 ****/
char _authstring[HTTP_MAX_VALUE],
- /* Current Authentication value (deprecated) */
+ /* Current Authorization value (deprecated) */
userpass[HTTP_MAX_VALUE];
/* Username:password string */
int digest_tries; /* Number of tries for digest auth */
/**** New in CUPS 1.3 ****/
char *field_authorization;
/* Authorization field */
- char *authstring; /* Current authorization field */
+ char *authstring; /* Current Authorization field */
# ifdef HAVE_GSSAPI
gss_OID gssmech; /* Authentication mechanism */
gss_ctx_id_t gssctx; /* Authentication context */
char *accept_encoding,
/* Accept-Encoding field */
*allow, /* Allow field */
- *server; /* Server field */
+ *server, /* Server field */
+ *default_accept_encoding,
+ *default_server,
+ *default_user_agent;
+ /* Default field values */
# ifdef HAVE_LIBZ
_http_coding_t coding; /* _HTTP_CODING_xxx */
z_stream stream; /* (De)compression stream */
/*
* Otherwise, just copy the host string...
*/
-
- ptr = http_copy_encode(ptr, host, end, ":/?#[]@\\\"", NULL,
+ ptr = http_copy_encode(ptr, host, end, "<>{}|^:/?#[]@\\\"", NULL,
encoding & HTTP_URI_CODING_HOSTNAME);
if (!ptr)
int length);
#ifdef HAVE_SSL
static int http_read_ssl(http_t *http, char *buf, int len);
-# if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+# ifdef HAVE_CDSASSL
static int http_set_credentials(http_t *http);
-# endif /* HAVE_CDSASSL ** HAVE_SECCERTIFICATECOPYDATA */
+# endif /* HAVE_CDSASSL */
#endif /* HAVE_SSL */
static off_t http_set_length(http_t *http);
static void http_set_timeout(int fd, double timeout);
{
# ifdef HAVE_LIBSSL
# elif defined(HAVE_GNUTLS)
-# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+# elif defined(HAVE_CDSASSL)
OSStatus error; /* Error code */
+ SecTrustRef peerTrust; /* Peer trust reference */
CFIndex count; /* Number of credentials */
- CFArrayRef peerCerts; /* Peer certificates */
SecCertificateRef secCert; /* Certificate reference */
CFDataRef data; /* Certificate data */
int i; /* Looping var */
# elif defined(HAVE_GNUTLS)
return (-1);
-# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
- if (!(error = SSLCopyPeerCertificates(http->tls, &peerCerts)) && peerCerts)
+# elif defined(HAVE_CDSASSL)
+ if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust)
{
if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL)
{
- for (i = 0, count = CFArrayGetCount(peerCerts); i < count; i++)
+ count = SecTrustGetCertificateCount(peerTrust);
+
+ for (i = 0; i < count; i ++)
{
- secCert = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
+ secCert = SecTrustGetCertificateAtIndex(peerTrust, i);
if ((data = SecCertificateCopyData(secCert)))
{
httpAddCredential(*credentials, CFDataGetBytePtr(data),
}
}
- CFRelease(peerCerts);
+ CFRelease(peerTrust);
}
return (error);
# elif defined(HAVE_GNUTLS)
return (NULL);
-# elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+# elif defined(HAVE_CDSASSL)
CFMutableArrayRef peerCerts; /* Peer credentials reference */
SecCertificateRef secCert; /* Certificate reference */
CFDataRef data; /* Credential data reference */
DEBUG_printf(("httpFlush(http=%p), state=%s", http,
http_states[http->state + 1]));
+ /*
+ * Nothing to do if we are in the "waiting" state...
+ */
+
+ if (http->state == HTTP_STATE_WAITING)
+ return;
+
/*
* Temporarily set non-blocking mode so we don't get stuck in httpRead()...
*/
return (0);
}
- else if (length > (size_t)http->data_remaining)
+ else if ((http->data_encoding == HTTP_ENCODING_LENGTH ||
+ http->coding == _HTTP_CODING_IDENTITY) &&
+ length > (size_t)http->data_remaining)
length = (size_t)http->data_remaining;
if (http->used == 0)
http->used = bytes;
}
+#ifdef HAVE_LIBZ
+ if (http->coding)
+ {
+ int zerr; /* Decompressor error */
+ off_t comp_avail; /* Maximum bytes for decompression */
+ z_stream stream; /* Copy of decompressor stream */
+
+ if (http->used > http->data_remaining)
+ comp_avail = http->data_remaining;
+ else
+ comp_avail = http->used;
+
+ DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
+ (int)comp_avail));
+
+ if (inflateCopy(&stream, &(http->stream)) != Z_OK)
+ {
+ DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
+ http->error = ENOMEM;
+ return (-1);
+ }
+
+ stream.next_in = (Bytef *)http->buffer;
+ stream.avail_in = comp_avail;
+ stream.next_out = (Bytef *)buffer;
+ stream.avail_out = length;
+
+ zerr = inflate(&stream, Z_SYNC_FLUSH);
+ inflateEnd(&stream);
+
+ if (zerr < Z_OK)
+ {
+ DEBUG_printf(("2httpPeek: zerr=%d", zerr));
+ http->error = EIO;
+ return (-1);
+ }
+
+ bytes = length - http->stream.avail_out;
+ }
+ else
+#endif /* HAVE_LIBZ */
if (http->used > 0)
{
if (length > (size_t)http->used)
return (bytes);
}
+/* For OS X 10.8 and earlier */
+ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
+{ return (httpPeek(http, buffer, length)); }
+
/*
* 'httpPost()' - Send a POST request to the server.
}
+/*
+ * 'httpSetDefaultField()' - Set the default value of an HTTP header.
+ *
+ * Currently only HTTP_FIELD_ACCEPT_ENCODING, HTTP_FIELD_SERVER, and
+ * HTTP_FIELD_USER_AGENT can be set.
+ *
+ * @since CUPS 1.7@
+ */
+
+void
+httpSetDefaultField(http_t *http, /* I - Connection to server */
+ http_field_t field, /* I - Field index */
+ const char *value)/* I - Value */
+{
+ DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")",
+ http, field, http_fields[field], value));
+
+ if (!http)
+ return;
+
+ switch (field)
+ {
+ case HTTP_FIELD_ACCEPT_ENCODING :
+ if (http->default_accept_encoding)
+ _cupsStrFree(http->default_accept_encoding);
+
+ http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
+ break;
+
+ case HTTP_FIELD_SERVER :
+ if (http->default_server)
+ _cupsStrFree(http->default_server);
+
+ http->default_server = value ? _cupsStrAlloc(value) : NULL;
+ break;
+
+ case HTTP_FIELD_USER_AGENT :
+ if (http->default_user_agent)
+ _cupsStrFree(http->default_user_agent);
+
+ http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
+ break;
+
+ default :
+ DEBUG_puts("1httpSetDefaultField: Ignored.");
+ break;
+ }
+}
+
+
/*
* 'httpSetExpect()' - Set the Expect: header in a request.
*
#endif /* HAVE_SSL */
if (!http->server)
- httpSetField(http, HTTP_FIELD_SERVER, CUPS_MINIMAL);
+ httpSetField(http, HTTP_FIELD_SERVER,
+ http->default_server ? http->default_server : CUPS_MINIMAL);
-#ifdef HAVE_LIBZ
/*
* Set the Accept-Encoding field if it isn't already...
*/
if (!http->accept_encoding)
- httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity");
+ httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
+ http->default_accept_encoding ? http->default_accept_encoding :
+#ifdef HAVE_LIBZ
+ "gzip, deflate, identity");
+#else
+ "identity");
#endif /* HAVE_LIBZ */
/*
*/
if (!http->fields[HTTP_FIELD_USER_AGENT][0])
- httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
+ httpSetField(http, HTTP_FIELD_USER_AGENT,
+ http->default_user_agent ? http->default_user_agent :
+ CUPS_MINIMAL);
-#ifdef HAVE_LIBZ
/*
* Set the Accept-Encoding field if it isn't already...
*/
- if (!http->accept_encoding)
- httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity");
-#endif /* HAVE_LIBZ */
+ if (!http->accept_encoding && http->default_accept_encoding)
+ httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
+ http->default_accept_encoding);
/*
* Encode the URI as needed...
#ifdef HAVE_SSL
-# if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+# if defined(HAVE_CDSASSL)
/*
* 'http_set_credentials()' - Set the SSL/TLS credentials.
*/
if ((credentials = http->tls_credentials) == NULL)
credentials = cg->tls_credentials;
-# if HAVE_SECPOLICYCREATESSL
/*
* Otherwise root around in the user's keychain to see if one can be found...
*/
if (dn_array)
CFRelease(dn_array);
}
-# endif /* HAVE_SECPOLICYCREATESSL */
if (credentials)
{
return (error);
}
-# endif /* HAVE_CDSASSL && HAVE_SECCERTIFICATECOPYDATA */
+# endif /* HAVE_CDSASSL */
#endif /* HAVE_SSL */
{
_cups_globals_t *cg = _cupsGlobals();
/* Pointer to library globals */
- int any_root; /* Allow any root */
char hostname[256], /* Hostname */
*hostptr; /* Pointer into hostname */
# elif defined(HAVE_CDSASSL)
OSStatus error; /* Error code */
const char *message = NULL;/* Error message */
-# ifdef HAVE_SECCERTIFICATECOPYDATA
cups_array_t *credentials; /* Credentials array */
cups_array_t *names; /* CUPS distinguished names */
CFArrayRef dn_array; /* CF distinguished names array */
CFDataRef data; /* Certificate data */
int i; /* Looping var */
http_credential_t *credential; /* Credential data */
-# endif /* HAVE_SECCERTIFICATECOPYDATA */
# elif defined(HAVE_SSPISSL)
TCHAR username[256]; /* Username returned from GetUserName() */
TCHAR commonName[256];/* Common name for certificate */
DEBUG_printf(("7http_setup_ssl(http=%p)", http));
/*
- * Always allow self-signed certificates for the local loopback address...
+ * Get the hostname to use for SSL...
*/
if (httpAddrLocalhost(http->hostaddr))
{
- any_root = 1;
strlcpy(hostname, "localhost", sizeof(hostname));
}
else
{
/*
- * Otherwise use the system-wide setting and make sure the hostname we have
- * does not end in a trailing dot.
+ * Otherwise make sure the hostname we have does not end in a trailing dot.
*/
- any_root = cg->any_root;
-
strlcpy(hostname, http->hostname, sizeof(hostname));
if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
*hostptr == '.')
}
# ifdef HAVE_LIBSSL
- (void)any_root;
-
context = SSL_CTX_new(SSLv23_client_method());
SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
}
# elif defined(HAVE_GNUTLS)
- (void)any_root;
-
credentials = (gnutls_certificate_client_credentials *)
malloc(sizeof(gnutls_certificate_client_credentials));
if (credentials == NULL)
http->tls_credentials = credentials;
# elif defined(HAVE_CDSASSL)
- if ((error = SSLNewContext(false, &http->tls)))
+ if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
+ kSSLStreamType)) == NULL)
{
- http->error = errno;
+ DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
+ http->error = errno = ENOMEM;
http->status = HTTP_ERROR;
_cupsSetHTTPError(HTTP_ERROR);
if (!error)
{
- error = SSLSetAllowsAnyRoot(http->tls, any_root);
- DEBUG_printf(("4http_setup_ssl: SSLSetAllowsAnyRoot(%d), error=%d",
- any_root, (int)error));
- }
-
- if (!error)
- {
- error = SSLSetAllowsExpiredCerts(http->tls, cg->expired_certs);
- DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredCerts(%d), error=%d",
- cg->expired_certs, (int)error));
- }
-
- if (!error)
- {
- error = SSLSetAllowsExpiredRoots(http->tls, cg->expired_root);
- DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredRoots(%d), error=%d",
- cg->expired_root, (int)error));
- }
-
- /*
- * In general, don't verify certificates since things like the common name
- * often do not match...
- */
-
- if (!error)
- {
- error = SSLSetEnableCertVerify(http->tls, false);
- DEBUG_printf(("4http_setup_ssl: SSLSetEnableCertVerify, error=%d",
+ error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth,
+ true);
+ DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
(int)error));
}
-# ifdef HAVE_SECCERTIFICATECOPYDATA
if (!error)
{
if (cg->client_cert_cb)
}
}
- /*
- * If there's a server certificate callback installed let it evaluate the
- * certificate(s) during the handshake...
- */
-
- if (!error && cg->server_cert_cb != NULL)
- {
- error = SSLSetSessionOption(http->tls,
- kSSLSessionOptionBreakOnServerAuth, true);
- DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnServerAuth, "
- "error=%d", (int)error));
- }
-# endif /* HAVE_SECCERTIFICATECOPYDATA */
-
/*
* Let the server know which hostname/domain we are trying to connect to
* in case it wants to serve up a certificate with a matching common name.
usleep(1000); /* in 1 millisecond */
break;
-# ifdef HAVE_SECCERTIFICATECOPYDATA
case errSSLServerAuthCompleted :
error = 0;
if (cg->server_cert_cb)
httpFreeCredentials(names);
}
break;
-# endif /* HAVE_SECCERTIFICATECOPYDATA */
case errSSLUnknownRootCert :
message = _("Unable to establish a secure connection to host "
http->status = HTTP_ERROR;
errno = ECONNREFUSED;
- SSLDisposeContext(http->tls);
+ CFRelease(http->tls);
http->tls = NULL;
/*
return (-1);
}
- _sspiSetAllowsAnyRoot(http->tls_credentials, any_root);
+ _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
_sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
if (!_sspiConnect(http->tls_credentials, hostname))
while (SSLClose(http->tls) == errSSLWouldBlock)
usleep(1000);
- SSLDisposeContext(http->tls);
+ CFRelease(http->tls);
if (http->tls_credentials)
CFRelease(http->tls_credentials);
_CUPS_API_1_7;
extern http_state_t httpReadRequest(http_t *http, char *resource,
size_t resourcelen) _CUPS_API_1_7;
+extern void httpSetDefaultField(http_t *http, http_field_t field,
+ const char *value) _CUPS_API_1_7;
extern http_state_t httpWriteResponse(http_t *http,
http_status_t status) _CUPS_API_1_7;
*
* Contents:
*
- * _cupsBufferGet() - Get a read/write buffer.
- * _cupsBufferRelease() - Release a read/write buffer.
- * ippAddBoolean() - Add a boolean attribute to an IPP message.
- * ippAddBooleans() - Add an array of boolean values.
- * ippAddCollection() - Add a collection value.
- * ippAddCollections() - Add an array of collection values.
- * ippAddDate() - Add a date attribute to an IPP message.
- * ippAddInteger() - Add a integer attribute to an IPP message.
- * ippAddIntegers() - Add an array of integer values.
- * ippAddOctetString() - Add an octetString value to an IPP message.
- * ippAddOutOfBand() - Add an out-of-band value to an IPP message.
- * ippAddRange() - Add a range of values to an IPP message.
- * ippAddRanges() - Add ranges of values to an IPP message.
- * ippAddResolution() - Add a resolution value to an IPP message.
- * ippAddResolutions() - Add resolution values to an IPP message.
- * ippAddSeparator() - Add a group separator to an IPP message.
- * ippAddString() - Add a language-encoded string to an IPP message.
- * ippAddStringf() - Add a formatted string to an IPP message.
- * ippAddStringfv() - Add a formatted string to an IPP message.
- * ippAddStrings() - Add language-encoded strings to an IPP message.
- * ippContainsInteger() - Determine whether an attribute contains the
- * specified value or is within the list of ranges.
- * ippContainsString() - Determine whether an attribute contains the
- * specified string value.
- * ippCopyAttribute() - Copy an attribute.
- * ippCopyAttributes() - Copy attributes from one IPP message to another.
- * ippDateToTime() - Convert from RFC 1903 Date/Time format to UNIX
- * time in seconds.
- * ippDelete() - Delete an IPP message.
- * ippDeleteAttribute() - Delete a single attribute in an IPP message.
- * ippDeleteValues() - Delete values in an attribute.
- * ippFindAttribute() - Find a named attribute in a request.
- * ippFindNextAttribute() - Find the next named attribute in a request.
- * ippFirstAttribute() - Return the first attribute in the message.
- * ippGetBoolean() - Get a boolean value for an attribute.
- * ippGetCollection() - Get a collection value for an attribute.
- * ippGetCount() - Get the number of values in an attribute.
- * ippGetDate() - Get a date value for an attribute.
- * ippGetGroupTag() - Get the group associated with an attribute.
- * ippGetInteger() - Get the integer/enum value for an attribute.
- * ippGetName() - Get the attribute name.
- * ippGetOperation() - Get the operation ID in an IPP message.
- * ippGetRange() - Get a rangeOfInteger value from an attribute.
- * ippGetRequestId() - Get the request ID from an IPP message.
- * ippGetResolution() - Get a resolution value for an attribute.
- * ippGetState() - Get the IPP message state.
- * ippGetStatusCode() - Get the status code from an IPP response or event
- * message.
- * ippGetString() - Get the string and optionally the language code
- * for an attribute.
- * ippGetValueTag() - Get the value tag for an attribute.
- * ippGetVersion() - Get the major and minor version number from an
- * IPP message.
- * ippLength() - Compute the length of an IPP message.
- * ippNextAttribute() - Return the next attribute in the message.
- * ippNew() - Allocate a new IPP message.
- * ippNewRequest() - Allocate a new IPP request message.
- * ippNewResponse() - Allocate a new IPP response message.
- * ippRead() - Read data for an IPP message from a HTTP
- * connection.
- * ippReadFile() - Read data for an IPP message from a file.
- * ippReadIO() - Read data for an IPP message.
- * ippSetBoolean() - Set a boolean value in an attribute.
- * ippSetCollection() - Set a collection value in an attribute.
- * ippSetDate() - Set a date value in an attribute.
- * ippSetGroupTag() - Set the group tag of an attribute.
- * ippSetInteger() - Set an integer or enum value in an attribute.
- * ippSetName() - Set the name of an attribute.
- * ippSetOperation() - Set the operation ID in an IPP request message.
- * ippSetRange() - Set a rangeOfInteger value in an attribute.
- * ippSetRequestId() - Set the request ID in an IPP message.
- * ippSetResolution() - Set a resolution value in an attribute.
- * ippSetState() - Set the current state of the IPP message.
- * ippSetStatusCode() - Set the status code in an IPP response or event
- * message.
- * ippSetString() - Set a string value in an attribute.
- * ippSetStringf() - Set a formatted string value of an attribute.
- * ippSetStringf() - Set a formatted string value of an attribute.
- * ippSetValueTag() - Set the value tag of an attribute.
- * ippSetVersion() - Set the version number in an IPP message.
- * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
- * ippWrite() - Write data for an IPP message to a HTTP
- * connection.
- * ippWriteFile() - Write data for an IPP message to a file.
- * ippWriteIO() - Write data for an IPP message.
- * ipp_add_attr() - Add a new attribute to the message.
- * ipp_free_values() - Free attribute values.
- * ipp_get_code() - Convert a C locale/charset name into an IPP
- * language/charset code.
- * ipp_lang_code() - Convert a C locale name into an IPP language
- * code.
- * ipp_length() - Compute the length of an IPP message or
- * collection value.
- * ipp_read_http() - Semi-blocking read on a HTTP connection...
- * ipp_read_file() - Read IPP data from a file.
- * ipp_set_value() - Get the value element from an attribute,
- * expanding it as needed.
- * ipp_write_file() - Write IPP data to a file.
+ * _cupsBufferGet() - Get a read/write buffer.
+ * _cupsBufferRelease() - Release a read/write buffer.
+ * ippAddBoolean() - Add a boolean attribute to an IPP message.
+ * ippAddBooleans() - Add an array of boolean values.
+ * ippAddCollection() - Add a collection value.
+ * ippAddCollections() - Add an array of collection values.
+ * ippAddDate() - Add a date attribute to an IPP message.
+ * ippAddInteger() - Add a integer attribute to an IPP message.
+ * ippAddIntegers() - Add an array of integer values.
+ * ippAddOctetString() - Add an octetString value to an IPP message.
+ * ippAddOutOfBand() - Add an out-of-band value to an IPP message.
+ * ippAddRange() - Add a range of values to an IPP message.
+ * ippAddRanges() - Add ranges of values to an IPP message.
+ * ippAddResolution() - Add a resolution value to an IPP message.
+ * ippAddResolutions() - Add resolution values to an IPP message.
+ * ippAddSeparator() - Add a group separator to an IPP message.
+ * ippAddString() - Add a language-encoded string to an IPP message.
+ * ippAddStringf() - Add a formatted string to an IPP message.
+ * ippAddStringfv() - Add a formatted string to an IPP message.
+ * ippAddStrings() - Add language-encoded strings to an IPP message.
+ * ippContainsInteger() - Determine whether an attribute contains the
+ * specified value or is within the list of ranges.
+ * ippContainsString() - Determine whether an attribute contains the
+ * specified string value.
+ * ippCopyAttribute() - Copy an attribute.
+ * ippCopyAttributes() - Copy attributes from one IPP message to another.
+ * ippDateToTime() - Convert from RFC 1903 Date/Time format to UNIX
+ * time in seconds.
+ * ippDelete() - Delete an IPP message.
+ * ippDeleteAttribute() - Delete a single attribute in an IPP message.
+ * ippDeleteValues() - Delete values in an attribute.
+ * ippFindAttribute() - Find a named attribute in a request.
+ * ippFindNextAttribute() - Find the next named attribute in a request.
+ * ippFirstAttribute() - Return the first attribute in the message.
+ * ippGetBoolean() - Get a boolean value for an attribute.
+ * ippGetCollection() - Get a collection value for an attribute.
+ * ippGetCount() - Get the number of values in an attribute.
+ * ippGetDate() - Get a date value for an attribute.
+ * ippGetGroupTag() - Get the group associated with an attribute.
+ * ippGetInteger() - Get the integer/enum value for an attribute.
+ * ippGetName() - Get the attribute name.
+ * ippGetOperation() - Get the operation ID in an IPP message.
+ * ippGetRange() - Get a rangeOfInteger value from an attribute.
+ * ippGetRequestId() - Get the request ID from an IPP message.
+ * ippGetResolution() - Get a resolution value for an attribute.
+ * ippGetState() - Get the IPP message state.
+ * ippGetStatusCode() - Get the status code from an IPP response or
+ * event message.
+ * ippGetString() - Get the string and optionally the language code
+ * for an attribute.
+ * ippGetValueTag() - Get the value tag for an attribute.
+ * ippGetVersion() - Get the major and minor version number from an
+ * IPP message.
+ * ippLength() - Compute the length of an IPP message.
+ * ippNextAttribute() - Return the next attribute in the message.
+ * ippNew() - Allocate a new IPP message.
+ * ippNewRequest() - Allocate a new IPP request message.
+ * ippNewResponse() - Allocate a new IPP response message.
+ * ippRead() - Read data for an IPP message from a HTTP
+ * connection.
+ * ippReadFile() - Read data for an IPP message from a file.
+ * ippReadIO() - Read data for an IPP message.
+ * ippSetBoolean() - Set a boolean value in an attribute.
+ * ippSetCollection() - Set a collection value in an attribute.
+ * ippSetDate() - Set a date value in an attribute.
+ * ippSetGroupTag() - Set the group tag of an attribute.
+ * ippSetInteger() - Set an integer or enum value in an attribute.
+ * ippSetName() - Set the name of an attribute.
+ * ippSetOperation() - Set the operation ID in an IPP request message.
+ * ippSetRange() - Set a rangeOfInteger value in an attribute.
+ * ippSetRequestId() - Set the request ID in an IPP message.
+ * ippSetResolution() - Set a resolution value in an attribute.
+ * ippSetState() - Set the current state of the IPP message.
+ * ippSetStatusCode() - Set the status code in an IPP response or event
+ * message.
+ * ippSetString() - Set a string value in an attribute.
+ * ippSetStringf() - Set a formatted string value of an attribute.
+ * ippSetStringf() - Set a formatted string value of an attribute.
+ * ippSetValueTag() - Set the value tag of an attribute.
+ * ippSetVersion() - Set the version number in an IPP message.
+ * ippTimeToDate() - Convert from UNIX time to RFC 1903 format.
+ * ippValidateAttribute() - Validate the contents of an attribute.
+ * ippValidateAttributes() - Validate all attributes in an IPP message.
+ * ippWrite() - Write data for an IPP message to a HTTP
+ * connection.
+ * ippWriteFile() - Write data for an IPP message to a file.
+ * ippWriteIO() - Write data for an IPP message.
+ * ipp_add_attr() - Add a new attribute to the message.
+ * ipp_free_values() - Free attribute values.
+ * ipp_get_code() - Convert a C locale/charset name into an IPP
+ * language/charset code.
+ * ipp_lang_code() - Convert a C locale name into an IPP language
+ * code.
+ * ipp_length() - Compute the length of an IPP message or
+ * collection value.
+ * ipp_read_http() - Semi-blocking read on a HTTP connection...
+ * ipp_read_file() - Read IPP data from a file.
+ * ipp_set_error() - Set a formatted, localized error string.
+ * ipp_set_value() - Get the value element from an attribute,
+ * expanding it as needed.
+ * ipp_write_file() - Write IPP data to a file.
*/
/*
*/
#include "cups-private.h"
+#include <regex.h>
#ifdef WIN32
# include <io.h>
#endif /* WIN32 */
size_t length);
static ssize_t ipp_read_file(int *fd, ipp_uchar_t *buffer,
size_t length);
+static void ipp_set_error(ipp_status_t status, const char *format,
+ ...);
static _ipp_value_t *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr,
int element);
static ssize_t ipp_write_file(int *fd, ipp_uchar_t *buffer,
ipp_tag_t tag; /* Current tag */
ipp_tag_t value_tag; /* Current value tag */
_ipp_value_t *value; /* Current value */
- static const int maxlen[] = /* Maximum length of strings */
- {
- IPP_MAX_TEXT - 1,
- IPP_MAX_NAME - 1,
- 0,
- IPP_MAX_KEYWORD - 1,
- IPP_MAX_URI - 1,
- IPP_MAX_URISCHEME - 1,
- IPP_MAX_CHARSET - 1,
- IPP_MAX_LANGUAGE - 1,
- IPP_MAX_MIMETYPE - 1
- };
DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
case IPP_TAG_CHARSET :
case IPP_TAG_LANGUAGE :
case IPP_TAG_MIMETYPE :
- if (n > maxlen[tag - IPP_TAG_TEXT])
- {
- _cupsSetError(IPP_INTERNAL_ERROR,
- _("IPP string value too large."), 1);
- DEBUG_printf(("1ippReadIO: bad %s value length %d.",
- ippTagString(tag), n));
- _cupsBufferRelease((char *)buffer);
- return (IPP_ERROR);
- }
-
if (n > 0)
{
if ((*cb)(src, buffer, n) < n)
_cupsBufferRelease((char *)buffer);
return (IPP_ERROR);
}
- else if (n > (2 + IPP_MAX_LANGUAGE + IPP_MAX_TEXT))
- {
- if (tag == IPP_TAG_TEXTLANG)
- _cupsSetError(IPP_INTERNAL_ERROR,
- _("IPP textWithLanguage value more than "
- "maximum 1090 bytes."), 1);
- else
- _cupsSetError(IPP_INTERNAL_ERROR,
- _("IPP nameWithLanguage value more than "
- "maximum 1090 bytes."), 1);
- DEBUG_printf(("1ippReadIO: bad stringWithLanguage value "
- "length %d.", n));
- _cupsBufferRelease((char *)buffer);
- return (IPP_ERROR);
- }
if ((*cb)(src, buffer, n) < n)
{
_cupsBufferRelease((char *)buffer);
return (IPP_ERROR);
}
- else if (n >= IPP_MAX_TEXT)
- {
- _cupsSetError(IPP_INTERNAL_ERROR,
- _("IPP text length too large."), 1);
- DEBUG_printf(("1ippReadIO: bad text value length %d.",
- n));
- _cupsBufferRelease((char *)buffer);
- return (IPP_ERROR);
- }
bufptr[2 + n] = '\0';
value->string.text = _cupsStrAlloc((char *)bufptr + 2);
}
+/*
+ * 'ippValidateAttribute()' - Validate the contents of an attribute.
+ *
+ * This function validates the contents of an attribute based on the name and
+ * value tag. 1 is returned if the attribute is valid, 0 otherwise. On
+ * failure, cupsLastErrorString() is set to a human-readable message.
+ *
+ * @since CUPS 1.7@
+ */
+
+int /* O - 1 if valid, 0 otherwise */
+ippValidateAttribute(
+ ipp_attribute_t *attr) /* I - Attribute */
+{
+ int i; /* Looping var */
+ char scheme[64], /* Scheme from URI */
+ userpass[256], /* Username/password from URI */
+ hostname[256], /* Hostname from URI */
+ resource[1024]; /* Resource from URI */
+ int port, /* Port number from URI */
+ uri_status; /* URI separation status */
+ const char *ptr; /* Pointer into string */
+ ipp_attribute_t *colattr; /* Collection attribute */
+ regex_t re; /* Regular expression */
+ ipp_uchar_t *date; /* Current date value */
+ static const char * const uri_status_strings[] =
+ { /* URI status strings */
+ "URI too large",
+ "Bad arguments to function",
+ "Bad resource in URI",
+ "Bad port number in URI",
+ "Bad hostname/address in URI",
+ "Bad username in URI",
+ "Bad scheme in URI",
+ "Bad/empty URI",
+ "OK",
+ "Missing scheme in URI",
+ "Unknown scheme in URI",
+ "Missing resource in URI"
+ };
+
+
+ /*
+ * Skip separators.
+ */
+
+ if (!attr->name)
+ return (1);
+
+ /*
+ * Validate the attribute name.
+ */
+
+ for (ptr = attr->name; *ptr; ptr ++)
+ if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' && *ptr != '_')
+ break;
+
+ if (*ptr || ptr == attr->name)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad attribute name - invalid character "
+ "(RFC 2911 section 4.1.3)."), attr->name);
+ return (0);
+ }
+
+ if ((ptr - attr->name) > 255)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad attribute name - bad length %d "
+ "(RFC 2911 section 4.1.3)."), attr->name,
+ (int)(ptr - attr->name));
+ return (0);
+ }
+
+ switch (attr->value_tag)
+ {
+ case IPP_TAG_INTEGER :
+ break;
+
+ case IPP_TAG_BOOLEAN :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].boolean != 0 &&
+ attr->values[i].boolean != 1)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad boolen value %d "
+ "(RFC 2911 section 4.1.11)."), attr->name,
+ attr->values[i].boolean);
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_ENUM :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].integer < 1)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad enum value %d - out of range "
+ "(RFC 2911 section 4.1.4)."), attr->name,
+ attr->values[i].integer);
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_STRING :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].unknown.length > IPP_MAX_OCTETSTRING)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad octetString value - bad length %d "
+ "(RFC 2911 section 4.1.10)."), attr->name,
+ attr->values[i].unknown.length);
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_DATE :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ date = attr->values[i].date;
+
+ if (date[2] < 1 || date[2] > 12)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime month %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[2]);
+ return (0);
+ }
+
+ if (date[3] < 1 || date[3] > 31)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime day %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[3]);
+ return (0);
+ }
+
+ if (date[4] > 23)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime hours %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[4]);
+ return (0);
+ }
+
+ if (date[5] > 59)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime minutes %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[5]);
+ return (0);
+ }
+
+ if (date[6] > 60)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime seconds %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[6]);
+ return (0);
+ }
+
+ if (date[7] > 9)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime deciseconds %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[7]);
+ return (0);
+ }
+
+ if (date[8] != '-' && date[8] != '+')
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime UTC sign '%c' "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[8]);
+ return (0);
+ }
+
+ if (date[9] > 11)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime UTC hours %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[9]);
+ return (0);
+ }
+
+ if (date[10] > 59)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad dateTime UTC minutes %u "
+ "(RFC 2911 section 4.1.14)."), attr->name, date[10]);
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_RESOLUTION :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].resolution.xres <= 0)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad resolution value %dx%d%s - cross "
+ "feed resolution must be positive "
+ "(RFC 2911 section 4.1.15)."), attr->name,
+ attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_INCH ? "dpi" :
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_CM ? "dpcm" : "unknown");
+ return (0);
+ }
+
+ if (attr->values[i].resolution.yres <= 0)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad resolution value %dx%d%s - feed "
+ "resolution must be positive "
+ "(RFC 2911 section 4.1.15)."), attr->name,
+ attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_INCH ? "dpi" :
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_CM ? "dpcm" : "unknown");
+ return (0);
+ }
+
+ if (attr->values[i].resolution.units != IPP_RES_PER_INCH &&
+ attr->values[i].resolution.units != IPP_RES_PER_CM)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad resolution value %dx%d%s - bad "
+ "units value (RFC 2911 section 4.1.15)."),
+ attr->name, attr->values[i].resolution.xres,
+ attr->values[i].resolution.yres,
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_INCH ? "dpi" :
+ attr->values[i].resolution.units ==
+ IPP_RES_PER_CM ? "dpcm" : "unknown");
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_RANGE :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (attr->values[i].range.lower > attr->values[i].range.upper)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad rangeOfInteger value %d-%d - lower "
+ "greater than upper (RFC 2911 section 4.1.13)."),
+ attr->name, attr->values[i].range.lower,
+ attr->values[i].range.upper);
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_BEGIN_COLLECTION :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ for (colattr = attr->values[i].collection->attrs;
+ colattr;
+ colattr = colattr->next)
+ {
+ if (!ippValidateAttribute(colattr))
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_TEXT :
+ case IPP_TAG_TEXTLANG :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+ {
+ if ((*ptr & 0xe0) == 0xc0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if ((*ptr & 0xf0) == 0xe0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if ((*ptr & 0xf8) == 0xf0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if (*ptr & 0x80)
+ break;
+ }
+
+ if (*ptr)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad text value \"%s\" - bad UTF-8 "
+ "sequence (RFC 2911 section 4.1.1)."), attr->name,
+ attr->values[i].string.text);
+ return (0);
+ }
+
+ if ((ptr - attr->values[i].string.text) > (IPP_MAX_TEXT - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad text value \"%s\" - bad length %d "
+ "(RFC 2911 section 4.1.1)."), attr->name,
+ attr->values[i].string.text,
+ (int)(ptr - attr->values[i].string.text));
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_NAME :
+ case IPP_TAG_NAMELANG :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+ {
+ if ((*ptr & 0xe0) == 0xc0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if ((*ptr & 0xf0) == 0xe0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if ((*ptr & 0xf8) == 0xf0)
+ {
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ ptr ++;
+ if ((*ptr & 0xc0) != 0x80)
+ break;
+ }
+ else if (*ptr & 0x80)
+ break;
+ }
+
+ if (*ptr)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad name value \"%s\" - bad UTF-8 "
+ "sequence (RFC 2911 section 4.1.2)."), attr->name,
+ attr->values[i].string.text);
+ return (0);
+ }
+
+ if ((ptr - attr->values[i].string.text) > (IPP_MAX_NAME - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad name value \"%s\" - bad length %d "
+ "(RFC 2911 section 4.1.2)."), attr->name,
+ attr->values[i].string.text,
+ (int)(ptr - attr->values[i].string.text));
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_KEYWORD :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+ if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' &&
+ *ptr != '_')
+ break;
+
+ if (*ptr || ptr == attr->values[i].string.text)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad keyword value \"%s\" - invalid "
+ "character (RFC 2911 section 4.1.3)."),
+ attr->name, attr->values[i].string.text);
+ return (0);
+ }
+
+ if ((ptr - attr->values[i].string.text) > (IPP_MAX_KEYWORD - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad keyword value \"%s\" - bad "
+ "length %d (RFC 2911 section 4.1.3)."),
+ attr->name, attr->values[i].string.text,
+ (int)(ptr - attr->values[i].string.text));
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_URI :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ uri_status = httpSeparateURI(HTTP_URI_CODING_ALL,
+ attr->values[i].string.text,
+ scheme, sizeof(scheme),
+ userpass, sizeof(userpass),
+ hostname, sizeof(hostname),
+ &port, resource, sizeof(resource));
+
+ if (uri_status < HTTP_URI_OK)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad URI value \"%s\" - %s "
+ "(RFC 2911 section 4.1.5)."), attr->name,
+ attr->values[i].string.text,
+ uri_status_strings[uri_status -
+ HTTP_URI_OVERFLOW]);
+ return (0);
+ }
+
+ if (strlen(attr->values[i].string.text) > (IPP_MAX_URI - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad URI value \"%s\" - bad length %d "
+ "(RFC 2911 section 4.1.5)."), attr->name,
+ attr->values[i].string.text,
+ (int)strlen(attr->values[i].string.text));
+ }
+ }
+ break;
+
+ case IPP_TAG_URISCHEME :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ ptr = attr->values[i].string.text;
+ if (islower(*ptr & 255))
+ {
+ for (ptr ++; *ptr; ptr ++)
+ if (!islower(*ptr & 255) && !isdigit(*ptr & 255) &&
+ *ptr != '+' && *ptr != '-' && *ptr != '.')
+ break;
+ }
+
+ if (*ptr || ptr == attr->values[i].string.text)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad uriScheme value \"%s\" - bad "
+ "characters (RFC 2911 section 4.1.6)."),
+ attr->name, attr->values[i].string.text);
+ return (0);
+ }
+
+ if ((ptr - attr->values[i].string.text) > (IPP_MAX_URISCHEME - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad uriScheme value \"%s\" - bad "
+ "length %d (RFC 2911 section 4.1.6)."),
+ attr->name, attr->values[i].string.text,
+ (int)(ptr - attr->values[i].string.text));
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_CHARSET :
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+ if (!isprint(*ptr & 255) || isupper(*ptr & 255) ||
+ isspace(*ptr & 255))
+ break;
+
+ if (*ptr || ptr == attr->values[i].string.text)
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad charset value \"%s\" - bad "
+ "characters (RFC 2911 section 4.1.7)."),
+ attr->name, attr->values[i].string.text);
+ return (0);
+ }
+
+ if ((ptr - attr->values[i].string.text) > (IPP_MAX_CHARSET - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad charset value \"%s\" - bad "
+ "length %d (RFC 2911 section 4.1.7)."),
+ attr->name, attr->values[i].string.text,
+ (int)(ptr - attr->values[i].string.text));
+ return (0);
+ }
+ }
+ break;
+
+ case IPP_TAG_LANGUAGE :
+ /*
+ * The following regular expression is derived from the ABNF for
+ * language tags in RFC 4646. All I can say is that this is the
+ * easiest way to check the values...
+ */
+
+ if ((i = regcomp(&re,
+ "^("
+ "(([a-z]{2,3}(-[a-z][a-z][a-z]){0,3})|[a-z]{4,8})"
+ /* language */
+ "(-[a-z][a-z][a-z][a-z]){0,1}" /* script */
+ "(-([a-z][a-z]|[0-9][0-9][0-9])){0,1}" /* region */
+ "(-([a-z]{5,8}|[0-9][0-9][0-9]))*" /* variant */
+ "(-[a-wy-z](-[a-z0-9]{2,8})+)*" /* extension */
+ "(-x(-[a-z0-9]{1,8})+)*" /* privateuse */
+ "|"
+ "x(-[a-z0-9]{1,8})+" /* privateuse */
+ "|"
+ "[a-z]{1,3}(-[a-z][0-9]{2,8}){1,2}" /* grandfathered */
+ ")$",
+ REG_NOSUB | REG_EXTENDED)) != 0)
+ {
+ char temp[256]; /* Temporary error string */
+
+ regerror(i, &re, temp, sizeof(temp));
+ ipp_set_error(IPP_STATUS_ERROR_INTERNAL,
+ _("Unable to compile naturalLanguage regular "
+ "expression: %s."), temp);
+ return (0);
+ }
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+ "characters (RFC 2911 section 4.1.8)."),
+ attr->name, attr->values[i].string.text);
+ regfree(&re);
+ return (0);
+ }
+
+ if (strlen(attr->values[i].string.text) > (IPP_MAX_LANGUAGE - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+ "length %d (RFC 2911 section 4.1.8)."),
+ attr->name, attr->values[i].string.text,
+ (int)strlen(attr->values[i].string.text));
+ regfree(&re);
+ return (0);
+ }
+ }
+
+ regfree(&re);
+ break;
+
+ case IPP_TAG_MIMETYPE :
+ /*
+ * The following regular expression is derived from the ABNF for
+ * MIME media types in RFC 2045 and 4288. All I can say is that this is
+ * the easiest way to check the values...
+ */
+
+ if ((i = regcomp(&re,
+ "^"
+ "[-a-zA-Z0-9!#$&.+^_]{1,127}" /* type-name */
+ "/"
+ "[-a-zA-Z0-9!#$&.+^_]{1,127}" /* subtype-name */
+ "(;[-a-zA-Z0-9!#$&.+^_]{1,127}=" /* parameter= */
+ "([-a-zA-Z0-9!#$&.+^_]{1,127}|\"[^\"]*\"))*"
+ /* value */
+ "$",
+ REG_NOSUB | REG_EXTENDED)) != 0)
+ {
+ char temp[256]; /* Temporary error string */
+
+ regerror(i, &re, temp, sizeof(temp));
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("Unable to compile mimeMediaType regular "
+ "expression: %s."), temp);
+ return (0);
+ }
+
+ for (i = 0; i < attr->num_values; i ++)
+ {
+ if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+ "characters (RFC 2911 section 4.1.9)."),
+ attr->name, attr->values[i].string.text);
+ regfree(&re);
+ return (0);
+ }
+
+ if (strlen(attr->values[i].string.text) > (IPP_MAX_MIMETYPE - 1))
+ {
+ ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+ _("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+ "length %d (RFC 2911 section 4.1.9)."),
+ attr->name, attr->values[i].string.text,
+ (int)strlen(attr->values[i].string.text));
+ regfree(&re);
+ return (0);
+ }
+ }
+
+ regfree(&re);
+ break;
+
+ default :
+ break;
+ }
+
+ return (1);
+}
+
+
+/*
+ * 'ippValidateAttributes()' - Validate all attributes in an IPP message.
+ *
+ * This function validates the contents of the IPP message, including each
+ * attribute. Like @link ippValidateAttribute@, cupsLastErrorString() is set
+ * to a human-readable message on failure.
+ *
+ * @since CUPS 1.7@
+ */
+
+int /* O - 1 if valid, 0 otherwise */
+ippValidateAttributes(ipp_t *ipp) /* I - IPP message */
+{
+ ipp_attribute_t *attr; /* Current attribute */
+
+
+ if (!ipp)
+ return (1);
+
+ for (attr = ipp->attrs; attr; attr = attr->next)
+ if (!ippValidateAttribute(attr))
+ return (0);
+
+ return (1);
+}
+
+
/*
* 'ippWrite()' - Write data for an IPP message to a HTTP connection.
*/
}
+/*
+ * 'ipp_set_error()' - Set a formatted, localized error string.
+ */
+
+static void
+ipp_set_error(ipp_status_t status, /* I - Status code */
+ const char *format, /* I - Printf-style error string */
+ ...) /* I - Additional arguments as needed */
+{
+ va_list ap; /* Pointer to additional args */
+ char buffer[2048]; /* Message buffer */
+ cups_lang_t *lang = cupsLangDefault();
+ /* Current language */
+
+
+ va_start(ap, format);
+ vsnprintf(buffer, sizeof(buffer), _cupsLangString(lang, format), ap);
+ va_end(ap);
+
+ _cupsSetError(status, buffer, 0);
+}
+
+
/*
* 'ipp_set_value()' - Get the value element from an attribute, expanding it as
* needed.
*/
# include "http.h"
+# include <stdarg.h>
/*
extern int ippSetStringfv(ipp_t *ipp, ipp_attribute_t **attr,
int element, const char *format,
va_list ap) _CUPS_API_1_7;
+extern int ippValidateAttribute(ipp_attribute_t *attr)
+ _CUPS_API_1_7;
+extern int ippValidateAttributes(ipp_t *ipp) _CUPS_API_1_7;
/*
_pwg_finishings_t *b);
static void pwg_free_finishings(_pwg_finishings_t *f);
static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
-static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize);
+static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize,
+ const char *dashchars);
/*
else
pc->mandatory = _cupsArrayNewStrings(value, ' ');
}
+ else if (!_cups_strcasecmp(line, "SupportFile"))
+ {
+ if (!pc->support_files)
+ pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ cupsArrayAdd(pc->support_files, value);
+ }
else
{
DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line,
pwg_name = pwg_keyword;
new_known_pwg = 0;
- pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name));
+ pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name), "_.");
_pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
_PWG_FROMPTS(ppd_size->width),
_PWG_FROMPTS(ppd_size->length));
*/
pwg_name = pwg_keyword;
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
+ "_");
}
map->pwg = _cupsStrAlloc(pwg_name);
*/
pwg_name = pwg_keyword;
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
+ "_");
}
map->pwg = _cupsStrAlloc(pwg_name);
i > 0;
i --, choice ++, map ++)
{
- pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+ pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_");
map->pwg = _cupsStrAlloc(pwg_keyword);
map->ppd = _cupsStrAlloc(choice->choice);
if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
+ /*
+ * Support files...
+ */
+
+ pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+ (cups_acopy_func_t)_cupsStrAlloc,
+ (cups_afree_func_t)_cupsStrFree);
+
+ for (ppd_attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+ ppd_attr;
+ ppd_attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
+ cupsArrayAdd(pc->support_files, ppd_attr->value);
+
+ if ((ppd_attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL)
+ cupsArrayAdd(pc->support_files, ppd_attr->value);
+
/*
* Return the cache data...
*/
cupsArrayDelete(pc->mandatory);
+ cupsArrayDelete(pc->support_files);
+
free(pc);
}
value = (char *)cupsArrayNext(pc->mandatory))
cupsFilePutConf(fp, "Mandatory", value);
+ /*
+ * Support files...
+ */
+
+ for (value = (char *)cupsArrayFirst(pc->support_files);
+ value;
+ value = (char *)cupsArrayNext(pc->support_files))
+ cupsFilePutConf(fp, "SupportFile", value);
+
/*
* IPP attributes, if any...
*/
static void
pwg_unppdize_name(const char *ppd, /* I - PPD keyword */
char *name, /* I - Name buffer */
- size_t namesize) /* I - Size of name buffer */
+ size_t namesize, /* I - Size of name buffer */
+ const char *dashchars)/* I - Characters to be replaced by dashes */
{
char *ptr, /* Pointer into name buffer */
*end; /* End of name buffer */
{
if (_cups_isalnum(*ppd) || *ppd == '-')
*ptr++ = tolower(*ppd & 255);
- else if (*ppd == '_' || *ppd == '.')
+ else if (strchr(dashchars, *ppd))
*ptr++ = '-';
+ else
+ *ptr++ = *ppd;
if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
_cups_isupper(ppd[1]) && ptr < end)
* Constants...
*/
-# define _PPD_CACHE_VERSION 5 /* Version number in cache file */
+# define _PPD_CACHE_VERSION 6 /* Version number in cache file */
/*
char *password; /* cupsJobPassword value */
cups_array_t *mandatory; /* cupsMandatory value */
char *charge_info_uri; /* cupsChargeInfoURI value */
+ cups_array_t *support_files; /* Support files - ICC profiles, etc. */
};
_PWG_MEDIA_MM("prc_1_102x165mm", NULL, "EnvPRC1", 102, 165),
_PWG_MEDIA_MM("prc_2_102x176mm", NULL, "EnvPRC2", 102, 176),
_PWG_MEDIA_MM("prc_4_110x208mm", NULL, "EnvPRC4", 110, 208),
- _PWG_MEDIA_MM("prc_5_110x220mm", NULL, "EnvPRC5", 110, 220),
_PWG_MEDIA_MM("prc_8_120x309mm", NULL, "EnvPRC8", 120, 309),
_PWG_MEDIA_MM("prc_6_120x320mm", NULL, NULL, 120, 320),
_PWG_MEDIA_MM("prc_3_125x176mm", NULL, "EnvPRC3", 125, 176),
{
char uri[HTTP_MAX_URI]; /* Job/printer URI */
ipp_t *request; /* IPP request */
+ _cups_globals_t *cg = _cupsGlobals(); /* Thread global data */
/*
request = ippNewRequest(job_id < 0 ? IPP_PURGE_JOBS : IPP_CANCEL_JOB);
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
if (name)
{
httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
*response; /* Create-Job response */
ipp_attribute_t *attr; /* job-id attribute */
int job_id = 0; /* job-id value */
+ _cups_globals_t *cg = _cupsGlobals(); /* Thread global data */
DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
return (0);
}
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
NULL, "localhost", ippPort(), "/printers/%s", name);
snprintf(resource, sizeof(resource), "/printers/%s", name);
request = ippNewRequest(CUPS_GET_CLASSES);
+ ippSetVersion(request, 1, 1);
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", NULL, "printer-name");
request = ippNewRequest(CUPS_GET_DEFAULT);
+ ippSetVersion(request, 1, 1);
+
/*
* Do the request and get back a response...
*/
request = ippNewRequest(IPP_GET_JOBS);
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
"printer-uri", NULL, uri);
* See if the PPD file is available locally...
*/
- if (!cg->servername[0])
- cupsServer();
+ if (http)
+ httpGetHostname(http, hostname, sizeof(hostname));
+ else
+ {
+ strlcpy(hostname, cupsServer(), sizeof(hostname));
+ if (hostname[0] == '/')
+ strlcpy(hostname, "localhost", sizeof(hostname));
+ }
- if (!_cups_strcasecmp(cg->servername, "localhost"))
+ if (!_cups_strcasecmp(hostname, "localhost"))
{
char ppdname[1024]; /* PPD filename */
struct stat ppdinfo; /* PPD file information */
request = ippNewRequest(CUPS_GET_PRINTERS);
+ ippSetVersion(request, 1, 1);
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
"requested-attributes", NULL, "printer-name");
*/
request = ippNewRequest(CUPS_GET_PPD);
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", NULL,
name);
printer_uri[1024]; /* Printer URI */
ipp_t *request; /* Send-Document request */
http_status_t status; /* HTTP status */
+ _cups_globals_t *cg = _cupsGlobals(); /* Thread global data */
/*
return (HTTP_ERROR);
}
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
NULL, "localhost", ippPort(), "/printers/%s", name);
snprintf(resource, sizeof(resource), "/printers/%s", name);
classname[255], /* Temporary class name */
http_hostname[HTTP_MAX_HOST];
/* Hostname associated with connection */
+ _cups_globals_t *cg = _cupsGlobals(); /* Thread global data */
static const char * const requested_attrs[] =
{ /* Requested attributes */
"device-uri",
request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
+ ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
NULL, uri);
*/
# if defined(__GNUC__) && __GNUC__ > 2
-# if defined(__clang__) && defined(_CUPS_NO_DEPRECATED)
+# ifndef __has_extension
+# define __has_extension(x) 0
+# endif /* !__has_extension */
+# if __has_extension(attribute_unavailable_with_message) && defined(_CUPS_NO_DEPRECATED)
# define _CUPS_DEPRECATED __attribute__ ((unavailable))
# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m)))
# elif !defined(_CUPS_SOURCE) || defined(_CUPS_NO_DEPRECATED)
# define __attribute__(x)
# endif /* !__GNUC__ */
-#
#endif /* !_CUPS_VERSIONING_H_ */
/*
help/ref-classes-conf.html \
help/ref-client-conf.html \
help/ref-cupsd-conf.html \
+ help/ref-cups-files-conf.html \
help/ref-error_log.html \
help/ref-mailto-conf.html \
help/ref-page_log.html \
ipptoolfile - ipptool file format
<h2 class="title"><a name="DESCRIPTION">Description</a></h2>
-The <a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a> program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example:
+The <a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a> program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curly braces, for example:
<pre>
# This is a comment
</dd>
<dt>$notify-subscription-id
</dt>
-<dd>Inserts the last notify-subscription-id value returnd in a test response or 0 if
+<dd>Inserts the last notify-subscription-id value returned in a test response or 0 if
no notify-subscription-id has been seen.
</dd>
<dt>$port
#, c-format
msgid ""
"File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
msgstr ""
"S'han deshabilitat els URIs dels dispositius de fitxers. Per habilitar-los, "
-"vegeu la directriu FileDevice a «%s/cupsd.conf»."
+"vegeu la directriu FileDevice a «%s/cups-files.conf»."
#, c-format
msgid "Finished page %d."
#, c-format
msgid ""
"File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
msgstr ""
"Los URIs del dispositivo de archivo han sido deshabilitados. Para "
-"habilitarlos, vea la directiva FileDevice en \"%s/cupsd.conf\"."
+"habilitarlos, vea la directiva FileDevice en \"%s/cups-files.conf\"."
#, c-format
msgid "Finished page %d."
#, c-format
msgid ""
"File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
msgstr ""
-"ファイルデバイス URI は無効になっています。有効にするには、\"%s/cupsd.conf\" "
+"ファイルデバイス URI は無効になっています。有効にするには、\"%s/cups-files.conf\" "
"の FileDevice ディレクティブを参照してください。"
#, c-format
.\" which should have been included with this file. If this file is
.\" file is missing or damaged, see the license at "http://www.cups.org/".
.\"
-.TH cupsctl 8 "CUPS" "16 July 2012" "Apple Inc."
+.TH cupsctl 8 "CUPS" "12 December 2012" "Apple Inc."
.SH NAME
cupsctl \- configure cupsd.conf options
.SH SYNOPSIS
.nf
cupsctl --no-shared-printers
.fi
-.LP
-Enable printing using the file: pseudo-device:
-.nf
- cupsctl FileDevice=Yes
-.fi
.SH KNOWN ISSUES
You cannot set the Listen or Port directives using \fIcupsctl\fR.
.SH SEE ALSO
.\" which should have been included with this file. If this file is
.\" file is missing or damaged, see the license at "http://www.cups.org/".
.\"
-.TH ipptoolfile 5 "CUPS" "16 November 2012" "Apple Inc."
+.TH ipptoolfile 5 "CUPS" "3 December 2012" "Apple Inc."
.SH NAME
ipptoolfile \- ipptool file format
.SH DESCRIPTION
-The \fIipptool(1)\fR program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example:
+The \fIipptool(1)\fR program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curly braces, for example:
.nf
# This is a comment
Inserts the scheme from the URI provided to \fIipptool\fR.
.TP 5
$notify-subscription-id
-Inserts the last notify-subscription-id value returnd in a test response or 0 if
+Inserts the last notify-subscription-id value returned in a test response or 0 if
no notify-subscription-id has been seen.
.TP 5
$port
.\" which should have been included with this file. If this file is
.\" file is missing or damaged, see the license at "http://www.cups.org/".
.\"
-.TH ppdcfile 5 "CUPS" "20 May 2008" "Apple Inc."
+.TH ppdcfile 5 "CUPS" "3 December 2012" "Apple Inc."
.SH NAME
ppdcfile \- cups ppd compiler source file format
.SH DESCRIPTION
The CUPS PPD compiler reads meta files that contain descriptions
of one or more PPD files to be generated by \fIppdc\fR. This man
page provides a quick reference to the supported keywords and
-should be used in conjuction with the Common UNIX Printing System
-Developers Manual.
+should be used in conjunction with the online help for CUPS.
.PP
The source file format is plain ASCII text that can be edited
using your favorite text editor. Comments are supported using
the C (/* ... */) and C++ (// ...) comment mechanisms.
.PP
Printer driver information can be grouped and shared using
-curley braces ({ ... }); PPD files are written when a close
+curly braces ({ ... }); PPD files are written when a close
brace or end-of-file is seen and a PCFileName directive has been
defined.
.PP
done
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
- cp $(NOTIFIERS) $(SYMROOT); \
+ for file in $(NOTIFIERS); do \
+ cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
+ done \
fi
$(INSTALL_DIR) $(SYMROOT); \
for file in $(TARGETS); do \
cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
done \
fi
const char *prefix; /* WARN/FAIL prefix */
ppd_option_t *page_size, /* PageSize option */
*page_region; /* PageRegion option */
- _pwg_media_t *pwg_media; /* PWG media */
- char buf[1024]; /* PapeSize name that is supposed to be */
+ _pwg_media_t *pwg_media; /* PWG media */
+ char buf[PPD_MAX_NAME]; /* PapeSize name that is supposed to be */
const char *ptr; /* Pointer into string */
int width_2540ths, /* PageSize width in 2540ths */
length_2540ths; /* PageSize length in 2540ths */
_PWG_FROMPTS(size->width);
pwg_media = _pwgMediaForSize(width_2540ths, length_2540ths);
+ if (pwg_media &&
+ (fabs(pwg_media->width - width_2540ths) > 34 ||
+ fabs(pwg_media->length - length_2540ths) > 34))
+ pwg_media = NULL; /* Only flag matches within a point */
+
if (pwg_media && pwg_media->ppd &&
(pwg_media->ppd[0] < 'a' || pwg_media->ppd[0] > 'z'))
{
snprintf(buf, sizeof(buf), "%s.Transverse", pwg_media->ppd);
else
snprintf(buf, sizeof(buf), "%sRotated", pwg_media->ppd);
+
+ ppdlen = strlen(buf);
}
if (size->left == 0 && size->bottom == 0 &&
length_tmp = (fabs(size->length - ceil(size->length)) < 0.1) ?
ceil(size->length) : size->length;
- if (fmod(width_tmp, 18.0) == 0.0 || fmod(length_tmp, 18.0) == 0.0)
+ if (fmod(width_tmp, 9.0) == 0.0 && fmod(length_tmp, 9.0) == 0.0)
{
width_inch = width_tmp / 72.0;
length_inch = length_tmp / 72.0;
if (_cups_strcasecmp(size->name, buf))
{
- size_t buflen = strlen(buf); /* Length of proposed name */
+ size_t buflen = strlen(buf);
+ /* Length of proposed name */
if (_cups_strncasecmp(size->name, buf, buflen) ||
(strcmp(size->name + buflen, "in") &&
size->name[buflen] != '.'))
- _cupsLangPrintf(stdout,
- _(" %s Size \"%s\" should be \"%s\"."),
- prefix, size->name, buf);
+ {
+ char altbuf[PPD_MAX_NAME];
+ /* Alternate "wNNNhNNN" name */
+ size_t altlen; /* Length of alternate name */
+
+ snprintf(altbuf, sizeof(altbuf), "w%.0fh%.0f", size->width,
+ size->length);
+ altlen = strlen(altbuf);
+ if (_cups_strncasecmp(size->name, altbuf, altlen) ||
+ (size->name[altlen] && size->name[altlen] != '.'))
+ _cupsLangPrintf(stdout,
+ _(" %s Size \"%s\" should be \"%s\"."),
+ prefix, size->name, buf);
+ }
}
}
}
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
cp ipptool $(SYMROOT); \
+ dsymutil $(SYMROOT)/ipptool; \
fi
# include <dns_sd.h>
#endif /* HAVE_DNSSD */
#include <sys/stat.h>
+#include <sys/fcntl.h>
#include <poll.h>
#ifdef HAVE_SYS_MOUNT_H
# include <sys/mount.h>
* Connect to the server...
*/
- if ((http = _httpCreate(vars->hostname, vars->port, NULL, vars->family,
- vars->encryption, 1, _HTTP_MODE_CLIENT)) == NULL)
+ if ((http = httpConnect2(vars->hostname, vars->port, NULL, vars->family,
+ vars->encryption, 1, 30000, NULL)) == NULL)
{
print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
vars->port, cupsLastErrorString());
goto test_exit;
}
- if (httpReconnect(http))
- {
- print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
- vars->port, cupsLastErrorString());
- pass = 0;
- goto test_exit;
- }
+#ifdef HAVE_LIBZ
+ httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING,
+ "deflate, gzip, identity");
+#else
+ httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "identity");
+#endif /* HAVE_LIBZ */
if (vars->timeout > 0.0)
httpSetTimeout(http, vars->timeout, timeout_cb, NULL);
puts("<key>StatusCode</key>");
print_xml_string("string", "skip");
puts("<key>ResponseAttributes</key>");
- puts("<dict>");
- puts("</dict>");
+ puts("<dict />");
}
else if (Output == _CUPS_OUTPUT_TEST)
puts("SKIP]");
int out_of_order = 0; /* Are attribute groups out-of-order? */
cupsArrayClear(a);
-
switch (attrptr->group_tag)
{
case IPP_TAG_ZERO :
}
if (num_displayed > 0 && !Verbosity && response &&
- (Output == _CUPS_OUTPUT_TEST || Output == _CUPS_OUTPUT_PLIST))
+ Output == _CUPS_OUTPUT_TEST)
{
for (attrptr = response->attrs;
attrptr != NULL;
{
if (!attr->name || (group && *group != attr->group_tag))
{
- puts("</dict>");
- puts("<dict>");
+ if (attr->group_tag != IPP_TAG_ZERO)
+ {
+ puts("</dict>");
+ puts("<dict>");
+ }
if (group)
*group = attr->group_tag;
add_stringf(errors,
"\"%s\": Bad boolen value %d "
- "(RFC 2911 section 4.1.10).", attr->name,
+ "(RFC 2911 section 4.1.11).", attr->name,
attr->values[i].boolean);
}
}
add_stringf(errors,
"\"%s\": Bad dateTime month %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[2]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[2]);
}
if (date[3] < 1 || date[3] > 31)
add_stringf(errors,
"\"%s\": Bad dateTime day %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[3]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[3]);
}
if (date[4] > 23)
add_stringf(errors,
"\"%s\": Bad dateTime hours %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[4]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[4]);
}
if (date[5] > 59)
add_stringf(errors,
"\"%s\": Bad dateTime minutes %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[5]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[5]);
}
if (date[6] > 60)
add_stringf(errors,
"\"%s\": Bad dateTime seconds %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[6]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[6]);
}
if (date[7] > 9)
add_stringf(errors,
"\"%s\": Bad dateTime deciseconds %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[7]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[7]);
}
if (date[8] != '-' && date[8] != '+')
add_stringf(errors,
"\"%s\": Bad dateTime UTC sign '%c' "
- "(RFC 2911 section 4.1.13).", attr->name, date[8]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[8]);
}
if (date[9] > 11)
add_stringf(errors,
"\"%s\": Bad dateTime UTC hours %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[9]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[9]);
}
if (date[10] > 59)
add_stringf(errors,
"\"%s\": Bad dateTime UTC minutes %u "
- "(RFC 2911 section 4.1.13).", attr->name, date[10]);
+ "(RFC 2911 section 4.1.14).", attr->name, date[10]);
}
}
break;
add_stringf(errors,
"\"%s\": Bad resolution value %dx%d%s - cross "
"feed resolution must be positive "
- "(RFC 2911 section 4.1.13).", attr->name,
+ "(RFC 2911 section 4.1.15).", attr->name,
attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
add_stringf(errors,
"\"%s\": Bad resolution value %dx%d%s - feed "
"resolution must be positive "
- "(RFC 2911 section 4.1.13).", attr->name,
+ "(RFC 2911 section 4.1.15).", attr->name,
attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
add_stringf(errors,
"\"%s\": Bad resolution value %dx%d%s - bad "
- "units value (RFC 2911 section 4.1.13).",
+ "units value (RFC 2911 section 4.1.15).",
attr->name, attr->values[i].resolution.xres,
attr->values[i].resolution.yres,
attr->values[i].resolution.units ==
PageLog /tmp/cups-$user/log/page_log
EOF
+if test $ssltype != 0 -a `uname` = Darwin; then
+ echo "ServerCertificate $HOME/Library/Keychains/login.keychain" >> /tmp/cups-$user/cups-files.conf
+fi
+
#
# Setup lots of test queues - half with PPD files, half without...
#