X-Git-Url: http://git.samba.org/samba.git/?a=blobdiff_plain;f=source3%2Fprinting%2Fprint_cups.c;h=a85fba89974f316c5e49e33f6d1942b5b87a2d2e;hb=d096de56b16c50c7cc22df08895dc29567ee15d7;hp=ad01a68c8e6bc431ba18a5cbc12c6ac5303d1d28;hpb=293136c04b7eb5293ef18273e13fca00c85bb5f0;p=nivanova%2Fsamba-autobuild%2F.git diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index ad01a68c8e6..a85fba89974 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -2,29 +2,46 @@ * Support code for the Common UNIX Printing System ("CUPS") * * Copyright 1999-2003 by Michael R Sweet. + * Copyright 2008 Jeremy Allison. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * along with this program; if not, see . + */ + +/* + * JRA. Converted to utf8 pull/push. */ #include "includes.h" #include "printing.h" +#include "printing/pcap.h" #ifdef HAVE_CUPS #include #include +static SIG_ATOMIC_T gotalarm; + +/*************************************************************** + Signal function to tell us we timed out. +****************************************************************/ + +static void gotalarm_sig(int signum) +{ + gotalarm = 1; +} + +extern userdom_struct current_user_info; /* * 'cups_passwd_cb()' - The CUPS password callback... @@ -33,50 +50,124 @@ static const char * /* O - Password or NULL */ cups_passwd_cb(const char *prompt) /* I - Prompt */ { - /* - * Always return NULL to indicate that no password is available... - */ + /* + * Always return NULL to indicate that no password is available... + */ - return (NULL); + return (NULL); } -static const char *cups_server(void) +static http_t *cups_connect(TALLOC_CTX *frame) { - if ((lp_cups_server() != NULL) && (strlen(lp_cups_server()) > 0)) { - DEBUG(10, ("cups server explicitly set to %s\n", - lp_cups_server())); - return lp_cups_server(); + http_t *http = NULL; + char *server = NULL, *p = NULL; + int port; + int timeout = lp_cups_connection_timeout(); + size_t size; + + if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) { + if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) { + return NULL; + } + } else { + server = talloc_strdup(frame,cupsServer()); + } + if (!server) { + return NULL; + } + + p = strchr(server, ':'); + if (p) { + port = atoi(p+1); + *p = '\0'; + } else { + port = ippPort(); + } + + DEBUG(10, ("connecting to cups server %s:%d\n", + server, port)); + + gotalarm = 0; + + if (timeout) { + CatchSignal(SIGALRM, gotalarm_sig); + alarm(timeout); + } + +#ifdef HAVE_HTTPCONNECTENCRYPT + http = httpConnectEncrypt(server, port, lp_cups_encrypt()); +#else + http = httpConnect(server, port); +#endif + + + CatchSignal(SIGALRM, SIG_IGN); + alarm(0); + + if (http == NULL) { + DEBUG(0,("Unable to connect to CUPS server %s:%d - %s\n", + server, port, strerror(errno))); } - DEBUG(10, ("cups server left to default %s\n", cupsServer())); - return cupsServer(); + return http; } -/* - * 'cups_printer_fn()' - Call a function for every printer known to the - * system. - */ +static void send_pcap_info(const char *name, const char *info, void *pd) +{ + int fd = *(int *)pd; + size_t namelen = name ? strlen(name)+1 : 0; + size_t infolen = info ? strlen(info)+1 : 0; + + DEBUG(11,("send_pcap_info: writing namelen %u\n", (unsigned int)namelen)); + if (sys_write(fd, &namelen, sizeof(namelen)) != sizeof(namelen)) { + DEBUG(10,("send_pcap_info: namelen write failed %s\n", + strerror(errno))); + return; + } + DEBUG(11,("send_pcap_info: writing infolen %u\n", (unsigned int)infolen)); + if (sys_write(fd, &infolen, sizeof(infolen)) != sizeof(infolen)) { + DEBUG(10,("send_pcap_info: infolen write failed %s\n", + strerror(errno))); + return; + } + if (namelen) { + DEBUG(11,("send_pcap_info: writing name %s\n", name)); + if (sys_write(fd, name, namelen) != namelen) { + DEBUG(10,("send_pcap_info: name write failed %s\n", + strerror(errno))); + return; + } + } + if (infolen) { + DEBUG(11,("send_pcap_info: writing info %s\n", info)); + if (sys_write(fd, info, infolen) != infolen) { + DEBUG(10,("send_pcap_info: info write failed %s\n", + strerror(errno))); + return; + } + } +} -void cups_printer_fn(void (*fn)(char *, char *)) +static bool cups_cache_reload_async(int fd) { - /* I - Function to call */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ + TALLOC_CTX *frame = talloc_stackframe(); + struct pcap_cache *tmp_pcap_cache = NULL; + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ + cups_lang_t *language = NULL; /* Default language */ char *name, /* printer-name attribute */ - *make_model, /* printer-make-and-model attribute */ *info; /* printer-info attribute */ static const char *requested[] =/* Requested attributes */ { "printer-name", - "printer-make-and-model", "printer-info" - }; - + }; + bool ret = False; + size_t size; - DEBUG(5,("cups_printer_fn(%p)\n", fn)); + DEBUG(5, ("reloading cups printcap cache\n")); /* * Make sure we don't ask for passwords... @@ -88,11 +179,8 @@ void cups_printer_fn(void (*fn)(char *, char *)) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return; + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -112,7 +200,7 @@ void cups_printer_fn(void (*fn)(char *, char *)) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -126,16 +214,13 @@ void cups_printer_fn(void (*fn)(char *, char *)) * Do the request and get back a response... */ - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { + if ((response = cupsDoRequest(http, request, "/")) == NULL) { DEBUG(0,("Unable to get printer list - %s\n", ippErrorString(cupsLastError()))); - httpClose(http); - return; + goto out; } - for (attr = response->attrs; attr != NULL;) - { + for (attr = response->attrs; attr != NULL;) { /* * Skip leading attributes until we hit a printer... */ @@ -151,22 +236,28 @@ void cups_printer_fn(void (*fn)(char *, char *)) */ name = NULL; - make_model = NULL; info = NULL; - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; + attr->value_tag == IPP_TAG_NAME) { + if (!pull_utf8_talloc(frame, + &name, + attr->values[0].string.text, + &size)) { + goto out; + } + } if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; + attr->value_tag == IPP_TAG_TEXT) { + if (!pull_utf8_talloc(frame, + &info, + attr->values[0].string.text, + &size)) { + goto out; + } + } attr = attr->next; } @@ -178,16 +269,13 @@ void cups_printer_fn(void (*fn)(char *, char *)) if (name == NULL) break; - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - + if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) { + goto out; + } } ippDelete(response); - + response = NULL; /* * Build a CUPS_GET_CLASSES request, which requires the following @@ -203,10 +291,8 @@ void cups_printer_fn(void (*fn)(char *, char *)) request->request.op.operation_id = CUPS_GET_CLASSES; request->request.op.request_id = 1; - language = cupsLangDefault(); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -220,16 +306,13 @@ void cups_printer_fn(void (*fn)(char *, char *)) * Do the request and get back a response... */ - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { + if ((response = cupsDoRequest(http, request, "/")) == NULL) { DEBUG(0,("Unable to get printer list - %s\n", ippErrorString(cupsLastError()))); - httpClose(http); - return; + goto out; } - for (attr = response->attrs; attr != NULL;) - { + for (attr = response->attrs; attr != NULL;) { /* * Skip leading attributes until we hit a printer... */ @@ -245,22 +328,28 @@ void cups_printer_fn(void (*fn)(char *, char *)) */ name = NULL; - make_model = NULL; info = NULL; - while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) - { + while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) { if (strcmp(attr->name, "printer-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - name = attr->values[0].string.text; - - if (strcmp(attr->name, "printer-make-and-model") == 0 && - attr->value_tag == IPP_TAG_TEXT) - make_model = attr->values[0].string.text; + attr->value_tag == IPP_TAG_NAME) { + if (!pull_utf8_talloc(frame, + &name, + attr->values[0].string.text, + &size)) { + goto out; + } + } if (strcmp(attr->name, "printer-info") == 0 && - attr->value_tag == IPP_TAG_TEXT) - info = attr->values[0].string.text; + attr->value_tag == IPP_TAG_TEXT) { + if (!pull_utf8_talloc(frame, + &info, + attr->values[0].string.text, + &size)) { + goto out; + } + } attr = attr->next; } @@ -272,134 +361,271 @@ void cups_printer_fn(void (*fn)(char *, char *)) if (name == NULL) break; - if (info == NULL || !info[0]) - (*fn)(name, make_model); - else - (*fn)(name, info); - - + if (!pcap_cache_add_specific(&tmp_pcap_cache, name, info)) { + goto out; + } } - ippDelete(response); + ret = True; - /* - * Close the connection to the server... - */ + out: + if (response) + ippDelete(response); - httpClose(http); + if (language) + cupsLangFree(language); + + if (http) + httpClose(http); + + /* Send all the entries up the pipe. */ + if (tmp_pcap_cache) { + pcap_printer_fn_specific(tmp_pcap_cache, + send_pcap_info, + (void *)&fd); + + pcap_cache_destroy_specific(&tmp_pcap_cache); + } + TALLOC_FREE(frame); + return ret; } +static struct pcap_cache *local_pcap_copy; +struct fd_event *cache_fd_event; -/* - * 'cups_printername_ok()' - Provide the equivalent of pcap_printername_ok() - * for CUPS. - * O - 1 if printer name OK - * I - Name of printer - */ -int cups_printername_ok(const char *name) +static bool cups_pcap_load_async(struct tevent_context *ev, + struct messaging_context *msg_ctx, + int *pfd) { - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ - char uri[HTTP_MAX_URI]; /* printer-uri attribute */ + int fds[2]; + pid_t pid; + NTSTATUS status; + *pfd = -1; - DEBUG(5,("cups_printername_ok(\"%s\")\n", name)); + if (cache_fd_event) { + DEBUG(3,("cups_pcap_load_async: already waiting for " + "a refresh event\n" )); + return false; + } - /* - * Make sure we don't ask for passwords... - */ + DEBUG(5,("cups_pcap_load_async: asynchronously loading cups printers\n")); - cupsSetPasswordCB(cups_passwd_cb); + if (pipe(fds) == -1) { + return false; + } - /* - * Try to connect to the server... - */ + pid = sys_fork(); + if (pid == (pid_t)-1) { + DEBUG(10,("cups_pcap_load_async: fork failed %s\n", + strerror(errno) )); + close(fds[0]); + close(fds[1]); + return false; + } - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(3,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (0); + if (pid) { + DEBUG(10,("cups_pcap_load_async: child pid = %u\n", + (unsigned int)pid )); + /* Parent. */ + close(fds[1]); + *pfd = fds[0]; + return true; } - /* - * Build an IPP_GET_PRINTER_ATTRS request, which requires the following - * attributes: - * - * attributes-charset - * attributes-natural-language - * requested-attributes - * printer-uri - */ + /* Child. */ - request = ippNew(); + close_all_print_db(); - request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; - request->request.op.request_id = 1; + status = reinit_after_fork(msg_ctx, ev, procid_self(), true); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("cups_pcap_load_async: reinit_after_fork() failed\n")); + smb_panic("cups_pcap_load_async: reinit_after_fork() failed"); + } - language = cupsLangDefault(); + close(fds[0]); + cups_cache_reload_async(fds[1]); + close(fds[1]); + _exit(0); +} - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); +static void cups_async_callback(struct event_context *event_ctx, + struct fd_event *event, + uint16 flags, + void *p) +{ + TALLOC_CTX *frame = talloc_stackframe(); + int fd = *(int *)p; + struct pcap_cache *tmp_pcap_cache = NULL; - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, - "attributes-natural-language", NULL, language->language); + DEBUG(5,("cups_async_callback: callback received for printer data. " + "fd = %d\n", fd)); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, - "requested-attributes", NULL, "printer-uri"); + while (1) { + char *name = NULL, *info = NULL; + size_t namelen = 0, infolen = 0; + ssize_t ret = -1; - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", name); + ret = sys_read(fd, &namelen, sizeof(namelen)); + if (ret == 0) { + /* EOF */ + break; + } + if (ret != sizeof(namelen)) { + DEBUG(10,("cups_async_callback: namelen read failed %d %s\n", + errno, strerror(errno))); + break; + } - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, - "printer-uri", NULL, uri); + DEBUG(11,("cups_async_callback: read namelen %u\n", + (unsigned int)namelen)); - /* - * Do the request and get back a response... - */ + ret = sys_read(fd, &infolen, sizeof(infolen)); + if (ret == 0) { + /* EOF */ + break; + } + if (ret != sizeof(infolen)) { + DEBUG(10,("cups_async_callback: infolen read failed %s\n", + strerror(errno))); + break; + } - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(cupsLastError()))); - httpClose(http); - return (0); - } + DEBUG(11,("cups_async_callback: read infolen %u\n", + (unsigned int)infolen)); - httpClose(http); + if (namelen) { + name = TALLOC_ARRAY(frame, char, namelen); + if (!name) { + break; + } + ret = sys_read(fd, name, namelen); + if (ret == 0) { + /* EOF */ + break; + } + if (ret != namelen) { + DEBUG(10,("cups_async_callback: name read failed %s\n", + strerror(errno))); + break; + } + DEBUG(11,("cups_async_callback: read name %s\n", + name)); + } else { + name = NULL; + } + if (infolen) { + info = TALLOC_ARRAY(frame, char, infolen); + if (!info) { + break; + } + ret = sys_read(fd, info, infolen); + if (ret == 0) { + /* EOF */ + break; + } + if (ret != infolen) { + DEBUG(10,("cups_async_callback: info read failed %s\n", + strerror(errno))); + break; + } + DEBUG(11,("cups_async_callback: read info %s\n", + info)); + } else { + info = NULL; + } - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(3,("Unable to get printer status for %s - %s\n", name, - ippErrorString(response->request.status.status_code))); - ippDelete(response); - return (0); + /* Add to our local pcap cache. */ + pcap_cache_add_specific(&tmp_pcap_cache, name, info); + TALLOC_FREE(name); + TALLOC_FREE(info); } - else - { - ippDelete(response); - return (1); + + TALLOC_FREE(frame); + if (tmp_pcap_cache) { + /* We got a namelist, replace our local cache. */ + pcap_cache_destroy_specific(&local_pcap_copy); + local_pcap_copy = tmp_pcap_cache; + + /* And the systemwide pcap cache. */ + pcap_cache_replace(local_pcap_copy); + } else { + DEBUG(2,("cups_async_callback: failed to read a new " + "printer list\n")); } + close(fd); + TALLOC_FREE(p); + TALLOC_FREE(cache_fd_event); } +bool cups_cache_reload(struct tevent_context *ev, + struct messaging_context *msg_ctx) +{ + int *p_pipe_fd = TALLOC_P(NULL, int); + + if (!p_pipe_fd) { + return false; + } + + *p_pipe_fd = -1; + + /* Set up an async refresh. */ + if (!cups_pcap_load_async(ev, msg_ctx, p_pipe_fd)) { + return false; + } + if (!local_pcap_copy) { + /* We have no local cache, wait directly for + * async refresh to complete. + */ + DEBUG(10,("cups_cache_reload: sync read on fd %d\n", + *p_pipe_fd )); + + cups_async_callback(ev, NULL, + EVENT_FD_READ, + (void *)p_pipe_fd); + if (!local_pcap_copy) { + return false; + } + } else { + /* Replace the system cache with our + * local copy. */ + pcap_cache_replace(local_pcap_copy); + + DEBUG(10,("cups_cache_reload: async read on fd %d\n", + *p_pipe_fd )); + + /* Trigger an event when the pipe can be read. */ + cache_fd_event = event_add_fd(ev, + NULL, *p_pipe_fd, + EVENT_FD_READ, + cups_async_callback, + (void *)p_pipe_fd); + if (!cache_fd_event) { + close(*p_pipe_fd); + TALLOC_FREE(p_pipe_fd); + return false; + } + } + return true; +} /* * 'cups_job_delete()' - Delete a job. */ -static int -cups_job_delete(int snum, struct printjob *pjob) +static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob) { - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char *user = NULL; char uri[HTTP_MAX_URI]; /* printer-uri attribute */ + size_t size; - - DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); + DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob)); /* * Make sure we don't ask for passwords... @@ -411,11 +637,8 @@ cups_job_delete(int snum, struct printjob *pjob) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -436,7 +659,7 @@ cups_job_delete(int snum, struct printjob *pjob) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -445,32 +668,41 @@ cups_job_delete(int snum, struct printjob *pjob) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); + if (!push_utf8_talloc(frame, &user, pjob->user, &size)) { + goto out; + } + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); + NULL, user); /* * Do the request and get back a response... */ - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) + if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, + ippErrorString(cupsLastError()))); + } else { + ret = 0; + } + } else { DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); + ippErrorString(cupsLastError()))); } - else - DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - httpClose(http); + out: + if (response) + ippDelete(response); - return (ret); + if (language) + cupsLangFree(language); + + if (http) + httpClose(http); + + TALLOC_FREE(frame); + return ret; } @@ -478,16 +710,17 @@ cups_job_delete(int snum, struct printjob *pjob) * 'cups_job_pause()' - Pause a job. */ -static int -cups_job_pause(int snum, struct printjob *pjob) +static int cups_job_pause(int snum, struct printjob *pjob) { - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char *user = NULL; char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - + size_t size; DEBUG(5,("cups_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); @@ -501,11 +734,8 @@ cups_job_pause(int snum, struct printjob *pjob) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -526,7 +756,7 @@ cups_job_pause(int snum, struct printjob *pjob) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -535,32 +765,40 @@ cups_job_pause(int snum, struct printjob *pjob) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); + if (!push_utf8_talloc(frame, &user, pjob->user, &size)) { + goto out; + } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); + NULL, user); /* * Do the request and get back a response... */ - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) + if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, + ippErrorString(cupsLastError()))); + } else { + ret = 0; + } + } else { DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); + ippErrorString(cupsLastError()))); } - else - DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - httpClose(http); + out: + if (response) + ippDelete(response); + + if (language) + cupsLangFree(language); - return (ret); + if (http) + httpClose(http); + + TALLOC_FREE(frame); + return ret; } @@ -568,16 +806,17 @@ cups_job_pause(int snum, struct printjob *pjob) * 'cups_job_resume()' - Resume a paused job. */ -static int -cups_job_resume(int snum, struct printjob *pjob) +static int cups_job_resume(int snum, struct printjob *pjob) { - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char *user = NULL; char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - + size_t size; DEBUG(5,("cups_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); @@ -591,11 +830,8 @@ cups_job_resume(int snum, struct printjob *pjob) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -616,7 +852,7 @@ cups_job_resume(int snum, struct printjob *pjob) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -625,32 +861,40 @@ cups_job_resume(int snum, struct printjob *pjob) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri); + if (!push_utf8_talloc(frame, &user, pjob->user, &size)) { + goto out; + } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); + NULL, user); /* * Do the request and get back a response... */ - ret = 1; - - if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) + if ((response = cupsDoRequest(http, request, "/jobs")) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, + ippErrorString(cupsLastError()))); + } else { + ret = 0; + } + } else { DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - else - ret = 0; - - ippDelete(response); + ippErrorString(cupsLastError()))); } - else - DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob, - ippErrorString(cupsLastError()))); - httpClose(http); + out: + if (response) + ippDelete(response); + + if (language) + cupsLangFree(language); - return (ret); + if (http) + httpClose(http); + + TALLOC_FREE(frame); + return ret; } @@ -658,21 +902,28 @@ cups_job_resume(int snum, struct printjob *pjob) * 'cups_job_submit()' - Submit a job for printing. */ -static int -cups_job_submit(int snum, struct printjob *pjob) +static int cups_job_submit(int snum, struct printjob *pjob) { - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + ipp_attribute_t *attr_job_id = NULL; /* IPP Attribute "job-id" */ + cups_lang_t *language = NULL; /* Default language */ char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - char *clientname; /* hostname of client for job-originating-host attribute */ - pstring new_jobname; - int num_options = 0; - cups_option_t *options; - - DEBUG(5,("cups_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); + char *new_jobname = NULL; + int num_options = 0; + cups_option_t *options = NULL; + char *printername = NULL; + char *user = NULL; + char *jobname = NULL; + char *cupsoptions = NULL; + char *filename = NULL; + size_t size; + uint32_t jobid = (uint32_t)-1; + + DEBUG(5,("cups_job_submit(%d, %p)\n", snum, pjob)); /* * Make sure we don't ask for passwords... @@ -684,11 +935,8 @@ cups_job_submit(int snum, struct printjob *pjob) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -710,105 +958,146 @@ cups_job_submit(int snum, struct printjob *pjob) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); + if (!push_utf8_talloc(frame, &printername, lp_printername(snum), + &size)) { + goto out; + } slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); + printername); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, pjob->user); - - clientname = client_name(); - if (strcmp(clientname, "UNKNOWN") == 0) { - clientname = client_addr(); + if (!push_utf8_talloc(frame, &user, pjob->user, &size)) { + goto out; } + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", + NULL, user); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-originating-host-name", NULL, - clientname); + pjob->clientmachine); + + /* Get the jobid from the filename. */ + jobid = print_parse_jobid(pjob->filename); + if (jobid == (uint32_t)-1) { + DEBUG(0,("cups_job_submit: failed to parse jobid from name %s\n", + pjob->filename )); + jobid = 0; + } - pstr_sprintf(new_jobname,"%s%.8u %s", PRINT_SPOOL_PREFIX, - (unsigned int)pjob->smbjob, pjob->jobname); + if (!push_utf8_talloc(frame, &jobname, pjob->jobname, &size)) { + goto out; + } + new_jobname = talloc_asprintf(frame, + "%s%.8u %s", PRINT_SPOOL_PREFIX, + (unsigned int)jobid, + jobname); + if (new_jobname == NULL) { + goto out; + } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL, new_jobname); - /* - * add any options defined in smb.conf + /* + * add any options defined in smb.conf */ + if (!push_utf8_talloc(frame, &cupsoptions, lp_cups_options(snum), &size)) { + goto out; + } num_options = 0; options = NULL; - num_options = cupsParseOptions(lp_cups_options(snum), num_options, &options); + num_options = cupsParseOptions(cupsoptions, num_options, &options); if ( num_options ) - cupsEncodeOptions(request, num_options, options); + cupsEncodeOptions(request, num_options, options); /* * Do the request and get back a response... */ - slprintf(uri, sizeof(uri) - 1, "/printers/%s", PRINTERNAME(snum)); + slprintf(uri, sizeof(uri) - 1, "/printers/%s", printername); - ret = 1; - if ((response = cupsDoFileRequest(http, request, uri, - pjob->filename)) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum), + if (!push_utf8_talloc(frame, &filename, pjob->filename, &size)) { + goto out; + } + if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to print file to %s - %s\n", + lp_printername(snum), ippErrorString(cupsLastError()))); - else + } else { ret = 0; - - ippDelete(response); - } - else - DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum), + attr_job_id = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER); + if(attr_job_id) { + pjob->sysjob = attr_job_id->values[0].integer; + DEBUG(5,("cups_job_submit: job-id %d\n", pjob->sysjob)); + } else { + DEBUG(0,("Missing job-id attribute in IPP response")); + } + } + } else { + DEBUG(0,("Unable to print file to `%s' - %s\n", + lp_printername(snum), ippErrorString(cupsLastError()))); - - httpClose(http); + } if ( ret == 0 ) unlink(pjob->filename); /* else print_job_end will do it for us */ - return (ret); + out: + if (response) + ippDelete(response); + + if (language) + cupsLangFree(language); + + if (http) + httpClose(http); + + TALLOC_FREE(frame); + + return ret; } /* * 'cups_queue_get()' - Get all the jobs in the print queue. */ -static int -cups_queue_get(const char *printer_name, +static int cups_queue_get(const char *sharename, enum printing_types printing_type, char *lpq_command, - print_queue_struct **q, + print_queue_struct **q, print_status_struct *status) { - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - ipp_attribute_t *attr; /* Current attribute */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + char *printername = NULL; + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + ipp_attribute_t *attr = NULL; /* Current attribute */ + cups_lang_t *language = NULL; /* Default language */ char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - int qcount, /* Number of active queue entries */ - qalloc; /* Number of queue entries allocated */ - print_queue_struct *queue, /* Queue entries */ + int qcount = 0, /* Number of active queue entries */ + qalloc = 0; /* Number of queue entries allocated */ + print_queue_struct *queue = NULL, /* Queue entries */ *temp; /* Temporary pointer for queue */ - const char *user_name, /* job-originating-user-name attribute */ - *job_name; /* job-name attribute */ + char *user_name = NULL, /* job-originating-user-name attribute */ + *job_name = NULL; /* job-name attribute */ int job_id; /* job-id attribute */ int job_k_octets; /* job-k-octets attribute */ time_t job_time; /* time-at-creation attribute */ ipp_jstate_t job_status; /* job-status attribute */ int job_priority; /* job-priority attribute */ + size_t size; static const char *jattrs[] = /* Requested job attributes */ { "job-id", @@ -825,8 +1114,18 @@ cups_queue_get(const char *printer_name, "printer-state-message" }; + *q = NULL; - DEBUG(5,("cups_queue_get(%s, %p, %p)\n", printer_name, q, status)); + /* HACK ALERT!!! The problem with support the 'printer name' + option is that we key the tdb off the sharename. So we will + overload the lpq_command string to pass in the printername + (which is basically what we do for non-cups printers ... using + the lpq_command to get the queue listing). */ + + if (!push_utf8_talloc(frame, &printername, lpq_command, &size)) { + goto out; + } + DEBUG(5,("cups_queue_get(%s, %p, %p)\n", lpq_command, q, status)); /* * Make sure we don't ask for passwords... @@ -838,18 +1137,15 @@ cups_queue_get(const char *printer_name, * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (0); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* * Generate the printer URI... */ - slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printer_name); + slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", printername); /* * Build an IPP_GET_JOBS request, which requires the following @@ -869,7 +1165,7 @@ cups_queue_get(const char *printer_name, language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -886,22 +1182,16 @@ cups_queue_get(const char *printer_name, * Do the request and get back a response... */ - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { + if ((response = cupsDoRequest(http, request, "/")) == NULL) { DEBUG(0,("Unable to get jobs for %s - %s\n", uri, ippErrorString(cupsLastError()))); - httpClose(http); - return (0); + goto out; } - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { DEBUG(0,("Unable to get jobs for %s - %s\n", uri, ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - - return (0); + goto out; } /* @@ -912,8 +1202,7 @@ cups_queue_get(const char *printer_name, qalloc = 0; queue = NULL; - for (attr = response->attrs; attr != NULL; attr = attr->next) - { + for (attr = response->attrs; attr != NULL; attr = attr->next) { /* * Skip leading attributes until we hit a job... */ @@ -927,23 +1216,16 @@ cups_queue_get(const char *printer_name, /* * Allocate memory as needed... */ - if (qcount >= qalloc) - { + if (qcount >= qalloc) { qalloc += 16; - temp = Realloc(queue, sizeof(print_queue_struct) * qalloc); + queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc); - if (temp == NULL) - { + if (queue == NULL) { DEBUG(0,("cups_queue_get: Not enough memory!")); - ippDelete(response); - httpClose(http); - - SAFE_FREE(queue); - return (0); + qcount = 0; + goto out; } - - queue = temp; } temp = queue + qcount; @@ -961,10 +1243,8 @@ cups_queue_get(const char *printer_name, user_name = NULL; job_name = NULL; - while (attr != NULL && attr->group_tag == IPP_TAG_JOB) - { - if (attr->name == NULL) - { + while (attr != NULL && attr->group_tag == IPP_TAG_JOB) { + if (attr->name == NULL) { attr = attr->next; break; } @@ -990,12 +1270,24 @@ cups_queue_get(const char *printer_name, job_time = attr->values[0].integer; if (strcmp(attr->name, "job-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - job_name = attr->values[0].string.text; + attr->value_tag == IPP_TAG_NAME) { + if (!pull_utf8_talloc(frame, + &job_name, + attr->values[0].string.text, + &size)) { + goto out; + } + } if (strcmp(attr->name, "job-originating-user-name") == 0 && - attr->value_tag == IPP_TAG_NAME) - user_name = attr->values[0].string.text; + attr->value_tag == IPP_TAG_NAME) { + if (!pull_utf8_talloc(frame, + &user_name, + attr->values[0].string.text, + &size)) { + goto out; + } + } attr = attr->next; } @@ -1004,12 +1296,11 @@ cups_queue_get(const char *printer_name, * See if we have everything needed... */ - if (user_name == NULL || job_name == NULL || job_id == 0) - { - if (attr == NULL) - break; - else - continue; + if (user_name == NULL || job_name == NULL || job_id == 0) { + if (attr == NULL) + break; + else + continue; } temp->job = job_id; @@ -1020,16 +1311,17 @@ cups_queue_get(const char *printer_name, LPQ_PRINTING; temp->priority = job_priority; temp->time = job_time; - strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1); - strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1); + strlcpy(temp->fs_user, user_name, sizeof(temp->fs_user)); + strlcpy(temp->fs_file, job_name, sizeof(temp->fs_file)); qcount ++; if (attr == NULL) - break; + break; } ippDelete(response); + response = NULL; /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the @@ -1046,10 +1338,8 @@ cups_queue_get(const char *printer_name, request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; request->request.op.request_id = 1; - language = cupsLangDefault(); - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); @@ -1066,31 +1356,23 @@ cups_queue_get(const char *printer_name, * Do the request and get back a response... */ - if ((response = cupsDoRequest(http, request, "/")) == NULL) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name, + if ((response = cupsDoRequest(http, request, "/")) == NULL) { + DEBUG(0,("Unable to get printer status for %s - %s\n", printername, ippErrorString(cupsLastError()))); - httpClose(http); - *q = queue; - return (qcount); + goto out; } - if (response->request.status.status_code >= IPP_OK_CONFLICT) - { - DEBUG(0,("Unable to get printer status for %s - %s\n", printer_name, + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to get printer status for %s - %s\n", printername, ippErrorString(response->request.status.status_code))); - ippDelete(response); - httpClose(http); - *q = queue; - return (qcount); + goto out; } /* * Get the current printer status and convert it to the SAMBA values. */ - if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) - { + if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) { if (attr->values[0].integer == IPP_PRINTER_STOPPED) status->status = LPSTAT_STOPPED; else @@ -1098,19 +1380,37 @@ cups_queue_get(const char *printer_name, } if ((attr = ippFindAttribute(response, "printer-state-message", - IPP_TAG_TEXT)) != NULL) - fstrcpy(status->message, attr->values[0].string.text); + IPP_TAG_TEXT)) != NULL) { + char *msg = NULL; + if (!pull_utf8_talloc(frame, &msg, + attr->values[0].string.text, + &size)) { + SAFE_FREE(queue); + qcount = 0; + goto out; + } + fstrcpy(status->message, msg); + } - ippDelete(response); + out: /* * Return the job queue... */ - httpClose(http); - *q = queue; - return (qcount); + + if (response) + ippDelete(response); + + if (language) + cupsLangFree(language); + + if (http) + httpClose(http); + + TALLOC_FREE(frame); + return qcount; } @@ -1118,17 +1418,18 @@ cups_queue_get(const char *printer_name, * 'cups_queue_pause()' - Pause a print queue. */ -static int -cups_queue_pause(int snum) +static int cups_queue_pause(int snum) { - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char *printername = NULL; + char *username = NULL; char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - + size_t size; DEBUG(5,("cups_queue_pause(%d)\n", snum)); @@ -1142,11 +1443,8 @@ cups_queue_pause(int snum) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -1167,42 +1465,56 @@ cups_queue_pause(int snum) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); + if (!push_utf8_talloc(frame, &printername, lp_printername(snum), + &size)) { + goto out; + } slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); + printername); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); + if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) { + goto out; + } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); + NULL, username); /* * Do the request and get back a response... */ - ret = 1; + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to pause printer %s - %s\n", + lp_printername(snum), + ippErrorString(cupsLastError()))); + } else { + ret = 0; + } + } else { + DEBUG(0,("Unable to pause printer %s - %s\n", + lp_printername(snum), + ippErrorString(cupsLastError()))); + } - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; + out: + if (response) + ippDelete(response); - ippDelete(response); - } - else - DEBUG(0,("Unable to pause printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); + if (language) + cupsLangFree(language); - httpClose(http); + if (http) + httpClose(http); - return (ret); + TALLOC_FREE(frame); + return ret; } @@ -1210,17 +1522,18 @@ cups_queue_pause(int snum) * 'cups_queue_resume()' - Restart a print queue. */ -static int -cups_queue_resume(int snum) +static int cups_queue_resume(int snum) { - extern userdom_struct current_user_info; - int ret; /* Return value */ - http_t *http; /* HTTP connection to server */ - ipp_t *request, /* IPP Request */ - *response; /* IPP Response */ - cups_lang_t *language; /* Default language */ + TALLOC_CTX *frame = talloc_stackframe(); + int ret = 1; /* Return value */ + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + cups_lang_t *language = NULL; /* Default language */ + char *printername = NULL; + char *username = NULL; char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - + size_t size; DEBUG(5,("cups_queue_resume(%d)\n", snum)); @@ -1234,11 +1547,8 @@ cups_queue_resume(int snum) * Try to connect to the server... */ - if ((http = httpConnect(cups_server(), ippPort())) == NULL) - { - DEBUG(0,("Unable to connect to CUPS server %s - %s\n", - cups_server(), strerror(errno))); - return (1); + if ((http = cups_connect(frame)) == NULL) { + goto out; } /* @@ -1259,42 +1569,56 @@ cups_queue_resume(int snum) language = cupsLangDefault(); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, - "attributes-charset", NULL, cupsLangEncoding(language)); + "attributes-charset", NULL, "utf-8"); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); + if (!push_utf8_talloc(frame, &printername, lp_printername(snum), + &size)) { + goto out; + } slprintf(uri, sizeof(uri) - 1, "ipp://localhost/printers/%s", - PRINTERNAME(snum)); + printername); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); + if (!push_utf8_talloc(frame, &username, current_user_info.unix_name, &size)) { + goto out; + } ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", - NULL, current_user_info.unix_name); + NULL, username); /* * Do the request and get back a response... */ - ret = 1; + if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) { + if (response->request.status.status_code >= IPP_OK_CONFLICT) { + DEBUG(0,("Unable to resume printer %s - %s\n", + lp_printername(snum), + ippErrorString(cupsLastError()))); + } else { + ret = 0; + } + } else { + DEBUG(0,("Unable to resume printer %s - %s\n", + lp_printername(snum), + ippErrorString(cupsLastError()))); + } - if ((response = cupsDoRequest(http, request, "/admin/")) != NULL) - { - if (response->request.status.status_code >= IPP_OK_CONFLICT) - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); - else - ret = 0; + out: + if (response) + ippDelete(response); - ippDelete(response); - } - else - DEBUG(0,("Unable to resume printer %s - %s\n", PRINTERNAME(snum), - ippErrorString(cupsLastError()))); + if (language) + cupsLangFree(language); - httpClose(http); + if (http) + httpClose(http); - return (ret); + TALLOC_FREE(frame); + return ret; } /******************************************************************* @@ -1313,7 +1637,180 @@ struct printif cups_printif = cups_job_submit, }; +bool cups_pull_comment_location(TALLOC_CTX *mem_ctx, + const char *printername, + char **comment, + char **location) +{ + TALLOC_CTX *frame = talloc_stackframe(); + http_t *http = NULL; /* HTTP connection to server */ + ipp_t *request = NULL, /* IPP Request */ + *response = NULL; /* IPP Response */ + ipp_attribute_t *attr; /* Current attribute */ + cups_lang_t *language = NULL; /* Default language */ + char uri[HTTP_MAX_URI]; + char *server = NULL; + char *sharename = NULL; + char *name = NULL; + static const char *requested[] =/* Requested attributes */ + { + "printer-name", + "printer-info", + "printer-location" + }; + bool ret = False; + size_t size; + + DEBUG(5, ("pulling %s location\n", printername)); + + /* + * Make sure we don't ask for passwords... + */ + + cupsSetPasswordCB(cups_passwd_cb); + + /* + * Try to connect to the server... + */ + + if ((http = cups_connect(frame)) == NULL) { + goto out; + } + + request = ippNew(); + + request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES; + request->request.op.request_id = 1; + + language = cupsLangDefault(); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET, + "attributes-charset", NULL, "utf-8"); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, + "attributes-natural-language", NULL, language->language); + + if (lp_cups_server() != NULL && strlen(lp_cups_server()) > 0) { + if (!push_utf8_talloc(frame, &server, lp_cups_server(), &size)) { + goto out; + } + } else { + server = talloc_strdup(frame,cupsServer()); + } + if (server) { + goto out; + } + if (!push_utf8_talloc(frame, &sharename, printername, &size)) { + goto out; + } + slprintf(uri, sizeof(uri) - 1, "ipp://%s/printers/%s", + server, sharename); + + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, + "printer-uri", NULL, uri); + + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_NAME, + "requested-attributes", + (sizeof(requested) / sizeof(requested[0])), + NULL, requested); + + /* + * Do the request and get back a response... + */ + + if ((response = cupsDoRequest(http, request, "/")) == NULL) { + DEBUG(0,("Unable to get printer attributes - %s\n", + ippErrorString(cupsLastError()))); + goto out; + } + + for (attr = response->attrs; attr != NULL;) { + /* + * Skip leading attributes until we hit a printer... + */ + + while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER) + attr = attr->next; + + if (attr == NULL) + break; + + /* + * Pull the needed attributes from this printer... + */ + + while ( attr && (attr->group_tag == IPP_TAG_PRINTER) ) { + if (strcmp(attr->name, "printer-name") == 0 && + attr->value_tag == IPP_TAG_NAME) { + if (!pull_utf8_talloc(frame, + &name, + attr->values[0].string.text, + &size)) { + goto out; + } + } + + /* Grab the comment if we don't have one */ + if ( (strcmp(attr->name, "printer-info") == 0) + && (attr->value_tag == IPP_TAG_TEXT)) + { + if (!pull_utf8_talloc(mem_ctx, + comment, + attr->values[0].string.text, + &size)) { + goto out; + } + DEBUG(5,("cups_pull_comment_location: Using cups comment: %s\n", + *comment)); + } + + /* Grab the location if we don't have one */ + if ( (strcmp(attr->name, "printer-location") == 0) + && (attr->value_tag == IPP_TAG_TEXT)) + { + if (!pull_utf8_talloc(mem_ctx, + location, + attr->values[0].string.text, + &size)) { + goto out; + } + DEBUG(5,("cups_pull_comment_location: Using cups location: %s\n", + *location)); + } + + attr = attr->next; + } + + /* + * We have everything needed... + */ + + if (name != NULL) + break; + } + + ret = True; + + out: + if (response) + ippDelete(response); + + if (request) { + ippDelete(request); + } + + if (language) + cupsLangFree(language); + + if (http) + httpClose(http); + + TALLOC_FREE(frame); + return ret; +} + #else /* this keeps fussy compilers happy */ + void print_cups_dummy(void); void print_cups_dummy(void) {} #endif /* HAVE_CUPS */