printing/print_iprint.c

説明を見る。
00001 /*
00002  * Support code for Novell iPrint using the Common UNIX Printing
00003  * System ("CUPS") libraries
00004  *
00005  * Copyright 1999-2003 by Michael R Sweet.
00006  * Portions Copyright 2005 by Joel J. Smith.
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  * 
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021  */
00022 
00023 #include "includes.h"
00024 #include "printing.h"
00025 
00026 #ifdef HAVE_IPRINT
00027 #include <cups/cups.h>
00028 #include <cups/language.h>
00029 
00030 #define OPERATION_NOVELL_LIST_PRINTERS          0x401A
00031 #define OPERATION_NOVELL_MGMT                   0x401C
00032 #define NOVELL_SERVER_SYSNAME                   "sysname="
00033 #define NOVELL_SERVER_SYSNAME_NETWARE           "NetWare IA32"
00034 #define NOVELL_SERVER_VERSION_STRING            "iprintserverversion="
00035 #define NOVELL_SERVER_VERSION_OES_SP1           33554432
00036 
00037 /*
00038  * 'iprint_passwd_cb()' - The iPrint password callback...
00039  */
00040 
00041 static const char *                             /* O - Password or NULL */
00042 iprint_passwd_cb(const char *prompt)    /* I - Prompt */
00043 {
00044        /*
00045         * Always return NULL to indicate that no password is available...
00046         */
00047 
00048         return (NULL);
00049 }
00050 
00051 static const char *iprint_server(void)
00052 {
00053         if ((lp_iprint_server() != NULL) && (strlen(lp_iprint_server()) > 0)) {
00054                 DEBUG(10, ("iprint server explicitly set to %s\n",
00055                            lp_iprint_server()));
00056                 return lp_iprint_server();
00057         }
00058 
00059         DEBUG(10, ("iprint server left to default %s\n", cupsServer()));
00060         return cupsServer();
00061 }
00062 
00063 /*
00064  * Pass in an already connected http_t*
00065  * Returns the server version if one can be found, multiplied by
00066  * -1 for all NetWare versions.  Returns 0 if a server version
00067  * cannot be determined
00068  */
00069 
00070 static int iprint_get_server_version(http_t *http, char* serviceUri)
00071 {
00072         ipp_t           *request = NULL,        /* IPP Request */
00073                         *response = NULL;       /* IPP Response */
00074         ipp_attribute_t *attr;                  /* Current attribute */
00075         cups_lang_t     *language = NULL;       /* Default language */
00076         char            *ver;                   /* server version pointer */
00077         char            *vertmp;                /* server version tmp pointer */
00078         int             serverVersion = 0;      /* server version */
00079         char            *os;                    /* server os */
00080         int             osFlag = 0;             /* 0 for NetWare, 1 for anything else */
00081         char            *temp;                  /* pointer for string manipulation */
00082 
00083        /*
00084         * Build an OPERATION_NOVELL_MGMT("get-server-version") request,
00085         * which requires the following attributes:
00086         *
00087         *    attributes-charset
00088         *    attributes-natural-language
00089         *    operation-name
00090         *    service-uri
00091         */
00092 
00093         request = ippNew();
00094 
00095         request->request.op.operation_id = (ipp_op_t)OPERATION_NOVELL_MGMT;
00096         request->request.op.request_id   = 1;
00097 
00098         language = cupsLangDefault();
00099 
00100         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00101                      "attributes-charset", NULL, "utf-8");
00102 
00103         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00104                      "attributes-natural-language", NULL, language->language);
00105 
00106         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
00107                      "service-uri", NULL, serviceUri);
00108 
00109         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
00110                       "operation-name", NULL, "get-server-version");
00111 
00112        /*
00113         * Do the request and get back a response...
00114         */
00115 
00116         if (((response = cupsDoRequest(http, request, "/ipp/")) == NULL) ||
00117             (response->request.status.status_code >= IPP_OK_CONFLICT))
00118                 goto out;
00119 
00120         if (((attr = ippFindAttribute(response, "server-version",
00121                                       IPP_TAG_STRING)) != NULL)) {
00122                 if ((ver = strstr(attr->values[0].string.text,
00123                                   NOVELL_SERVER_VERSION_STRING)) != NULL) {
00124                         ver += strlen(NOVELL_SERVER_VERSION_STRING);
00125                        /*
00126                         * Strangely, libcups stores a IPP_TAG_STRING (octet
00127                         * string) as a null-terminated string with no length
00128                         * even though it could be binary data with nulls in
00129                         * it.  Luckily, in this case the value is not binary.
00130                         */
00131                         serverVersion = strtol(ver, &vertmp, 10);
00132 
00133                         /* Check for not found, overflow or negative version */
00134                         if ((ver == vertmp) || (serverVersion < 0))
00135                                 serverVersion = 0;
00136                 }
00137 
00138                 if ((os = strstr(attr->values[0].string.text,
00139                                   NOVELL_SERVER_SYSNAME)) != NULL) {
00140                         os += strlen(NOVELL_SERVER_SYSNAME);
00141                         if ((temp = strchr(os,'<')) != NULL)
00142                                 *temp = '\0';
00143                         if (strcmp(os,NOVELL_SERVER_SYSNAME_NETWARE))
00144                                 osFlag = 1; /* 1 for non-NetWare systems */
00145                 }
00146         }
00147 
00148  out:
00149         if (response)
00150                 ippDelete(response);
00151 
00152         if (language)
00153                 cupsLangFree(language);
00154 
00155         if (osFlag == 0)
00156                 serverVersion *= -1;
00157 
00158         return serverVersion;
00159 }
00160 
00161 
00162 static int iprint_cache_add_printer(http_t *http,
00163                                    int reqId,
00164                                    char* url)
00165 {
00166         ipp_t           *request = NULL,        /* IPP Request */
00167                         *response = NULL;       /* IPP Response */
00168         ipp_attribute_t *attr;                  /* Current attribute */
00169         cups_lang_t     *language = NULL;       /* Default language */
00170         char            *name,                  /* printer-name attribute */
00171                         *info,                  /* printer-info attribute */
00172                         smb_enabled,            /* smb-enabled attribute */
00173                         secure;                 /* security-enabled attrib. */
00174 
00175         char            *httpPath;      /* path portion of the printer-uri */
00176 
00177         static const char *pattrs[] =   /* Requested printer attributes */
00178                         {
00179                           "printer-name",
00180                           "security-enabled",
00181                           "printer-info",
00182                           "smb-enabled"
00183                         };       
00184 
00185         request = ippNew();
00186 
00187         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
00188         request->request.op.request_id   = reqId;
00189 
00190         language = cupsLangDefault();
00191 
00192         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00193                      "attributes-charset", NULL, "utf-8");
00194 
00195         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00196                      "attributes-natural-language", NULL, language->language);
00197 
00198         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, url);
00199 
00200         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
00201                       "requested-attributes",
00202                       (sizeof(pattrs) / sizeof(pattrs[0])),
00203                       NULL, pattrs);
00204 
00205         /*
00206          * Do the request and get back a response...
00207          */
00208 
00209         if ((httpPath = strstr(url,"://")) == NULL ||
00210                         (httpPath = strchr(httpPath+3,'/')) == NULL)
00211         {
00212                 ippDelete(request);
00213                 request = NULL;
00214                 goto out;
00215         }
00216 
00217         if ((response = cupsDoRequest(http, request, httpPath)) == NULL) {
00218                 ipp_status_t lastErr = cupsLastError();
00219 
00220                /*
00221                 * Ignore printers that cannot be queried without credentials
00222                 */
00223                 if (lastErr == IPP_FORBIDDEN || 
00224                     lastErr == IPP_NOT_AUTHENTICATED ||
00225                     lastErr == IPP_NOT_AUTHORIZED)
00226                         goto out;
00227 
00228                 DEBUG(0,("Unable to get printer list - %s\n",
00229                       ippErrorString(lastErr)));
00230                 goto out;
00231         }
00232 
00233         for (attr = response->attrs; attr != NULL;) {
00234                /*
00235                 * Skip leading attributes until we hit a printer...
00236                 */
00237 
00238                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
00239                         attr = attr->next;
00240 
00241                 if (attr == NULL)
00242                         break;
00243 
00244                /*
00245                 * Pull the needed attributes from this printer...
00246                 */
00247 
00248                 name       = NULL;
00249                 info       = NULL;
00250                 smb_enabled= 1;
00251                 secure     = 0;
00252 
00253                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER) {
00254                         if (strcmp(attr->name, "printer-name") == 0 &&
00255                             attr->value_tag == IPP_TAG_NAME)
00256                                 name = attr->values[0].string.text;
00257 
00258                         if (strcmp(attr->name, "printer-info") == 0 &&
00259                             (attr->value_tag == IPP_TAG_TEXT ||
00260                             attr->value_tag == IPP_TAG_TEXTLANG))
00261                                 info = attr->values[0].string.text;
00262 
00263                        /*
00264                         * If the smb-enabled attribute is present and the
00265                         * value is set to 0, don't show the printer.
00266                         * If the attribute is not present, assume that the
00267                         * printer should show up
00268                         */
00269                         if (!strcmp(attr->name, "smb-enabled") &&
00270                             ((attr->value_tag == IPP_TAG_INTEGER &&
00271                             !attr->values[0].integer) ||
00272                             (attr->value_tag == IPP_TAG_BOOLEAN &&
00273                             !attr->values[0].boolean)))
00274                                 smb_enabled = 0;
00275 
00276                        /*
00277                         * If the security-enabled attribute is present and the
00278                         * value is set to 1, don't show the printer.
00279                         * If the attribute is not present, assume that the
00280                         * printer should show up
00281                         */
00282                         if (!strcmp(attr->name, "security-enabled") &&
00283                             ((attr->value_tag == IPP_TAG_INTEGER &&
00284                             attr->values[0].integer) ||
00285                             (attr->value_tag == IPP_TAG_BOOLEAN &&
00286                             attr->values[0].boolean)))
00287                                 secure = 1;
00288 
00289                         attr = attr->next;
00290                 }
00291 
00292                /*
00293                 * See if we have everything needed...
00294                 * Make sure the printer is not a secure printer
00295                 * and make sure smb printing hasn't been explicitly
00296                 * disabled for the printer
00297                 */
00298 
00299                 if (name != NULL && !secure && smb_enabled) 
00300                         pcap_cache_add(name, info);
00301         }
00302 
00303  out:
00304         if (response)
00305                 ippDelete(response);
00306         return(0);
00307 }
00308 
00309 BOOL iprint_cache_reload(void)
00310 {
00311         http_t          *http = NULL;           /* HTTP connection to server */
00312         ipp_t           *request = NULL,        /* IPP Request */
00313                         *response = NULL;       /* IPP Response */
00314         ipp_attribute_t *attr;                  /* Current attribute */
00315         cups_lang_t     *language = NULL;       /* Default language */
00316         int             i;
00317         BOOL ret = False;
00318 
00319         DEBUG(5, ("reloading iprint printcap cache\n"));
00320 
00321        /*
00322         * Make sure we don't ask for passwords...
00323         */
00324 
00325         cupsSetPasswordCB(iprint_passwd_cb);
00326 
00327        /*
00328         * Try to connect to the server...
00329         */
00330 
00331         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00332                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00333                          iprint_server(), strerror(errno)));
00334                 goto out;
00335         }
00336 
00337        /*
00338         * Build a OPERATION_NOVELL_LIST_PRINTERS request, which requires the following attributes:
00339         *
00340         *    attributes-charset
00341         *    attributes-natural-language
00342         */
00343 
00344         request = ippNew();
00345 
00346         request->request.op.operation_id =
00347                 (ipp_op_t)OPERATION_NOVELL_LIST_PRINTERS;
00348         request->request.op.request_id   = 1;
00349 
00350         language = cupsLangDefault();
00351 
00352         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00353                      "attributes-charset", NULL, "utf-8");
00354 
00355         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00356                      "attributes-natural-language", NULL, language->language);
00357 
00358         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
00359                      "ipp-server", NULL, "ippSrvr");
00360 
00361        /*
00362         * Do the request and get back a response...
00363         */
00364 
00365         if ((response = cupsDoRequest(http, request, "/ipp")) == NULL) {
00366                 DEBUG(0,("Unable to get printer list - %s\n",
00367                          ippErrorString(cupsLastError())));
00368                 goto out;
00369         }
00370 
00371         for (attr = response->attrs; attr != NULL;) {
00372                /*
00373                 * Skip leading attributes until we hit a printer...
00374                 */
00375 
00376                 while (attr != NULL && attr->group_tag != IPP_TAG_PRINTER)
00377                         attr = attr->next;
00378 
00379                 if (attr == NULL)
00380                         break;
00381 
00382                /*
00383                 * Pull the needed attributes from this printer...
00384                 */
00385 
00386                 while (attr != NULL && attr->group_tag == IPP_TAG_PRINTER)
00387                 {
00388                         if (strcmp(attr->name, "printer-name") == 0 &&
00389                             (attr->value_tag == IPP_TAG_URI ||
00390                              attr->value_tag == IPP_TAG_NAME ||
00391                              attr->value_tag == IPP_TAG_TEXT ||
00392                              attr->value_tag == IPP_TAG_NAMELANG ||
00393                              attr->value_tag == IPP_TAG_TEXTLANG))
00394                         {
00395                                 for (i = 0; i<attr->num_values; i++)
00396                                 {
00397                                         char *url = attr->values[i].string.text;
00398                                         if (!url || !strlen(url))
00399                                                 continue;
00400                                         iprint_cache_add_printer(http, i+2, url);
00401                                 }
00402                         }
00403                         attr = attr->next;
00404                 }
00405         }
00406 
00407         ret = True;
00408 
00409  out:
00410         if (response)
00411                 ippDelete(response);
00412 
00413         if (language)
00414                 cupsLangFree(language);
00415 
00416         if (http)
00417                 httpClose(http);
00418 
00419         return ret;
00420 }
00421 
00422 
00423 /*
00424  * 'iprint_job_delete()' - Delete a job.
00425  */
00426 
00427 static int iprint_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob)
00428 {
00429         int             ret = 1;                /* Return value */
00430         http_t          *http = NULL;           /* HTTP connection to server */
00431         ipp_t           *request = NULL,        /* IPP Request */
00432                         *response = NULL;       /* IPP Response */
00433         cups_lang_t     *language = NULL;       /* Default language */
00434         char            uri[HTTP_MAX_URI];      /* printer-uri attribute */
00435         char            httpPath[HTTP_MAX_URI]; /* path portion of the printer-uri */
00436 
00437 
00438         DEBUG(5,("iprint_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob));
00439 
00440        /*
00441         * Make sure we don't ask for passwords...
00442         */
00443 
00444         cupsSetPasswordCB(iprint_passwd_cb);
00445 
00446        /*
00447         * Try to connect to the server...
00448         */
00449 
00450         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00451                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00452                          iprint_server(), strerror(errno)));
00453                 goto out;
00454         }
00455 
00456        /*
00457         * Build an IPP_CANCEL_JOB request, which uses the following
00458         * attributes:
00459         *
00460         *    attributes-charset
00461         *    attributes-natural-language
00462         *    printer-uri
00463         *    job-id
00464         *    requesting-user-name
00465         */
00466 
00467         request = ippNew();
00468 
00469         request->request.op.operation_id = IPP_CANCEL_JOB;
00470         request->request.op.request_id   = 1;
00471 
00472         language = cupsLangDefault();
00473 
00474         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00475                      "attributes-charset", NULL, "utf-8");
00476 
00477         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00478                      "attributes-natural-language", NULL, language->language);
00479 
00480         slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), sharename);
00481 
00482         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
00483 
00484         ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", pjob->sysjob);
00485 
00486         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
00487                      NULL, pjob->user);
00488 
00489        /*
00490         * Do the request and get back a response...
00491         */
00492 
00493         slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", sharename);
00494 
00495         if ((response = cupsDoRequest(http, request, httpPath)) != NULL) {
00496                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
00497                         DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
00498                                 ippErrorString(cupsLastError())));
00499                 } else {
00500                         ret = 0;
00501                 }
00502         } else {
00503                 DEBUG(0,("Unable to cancel job %d - %s\n", pjob->sysjob,
00504                         ippErrorString(cupsLastError())));
00505         }
00506 
00507  out:
00508         if (response)
00509                 ippDelete(response);
00510 
00511         if (language)
00512                 cupsLangFree(language);
00513 
00514         if (http)
00515                 httpClose(http);
00516 
00517         return ret;
00518 }
00519 
00520 
00521 /*
00522  * 'iprint_job_pause()' - Pause a job.
00523  */
00524 
00525 static int iprint_job_pause(int snum, struct printjob *pjob)
00526 {
00527         int             ret = 1;                /* Return value */
00528         http_t          *http = NULL;           /* HTTP connection to server */
00529         ipp_t           *request = NULL,        /* IPP Request */
00530                         *response = NULL;       /* IPP Response */
00531         cups_lang_t     *language = NULL;       /* Default language */
00532         char            uri[HTTP_MAX_URI];      /* printer-uri attribute */
00533         char            httpPath[HTTP_MAX_URI]; /* path portion of the printer-uri */
00534 
00535 
00536         DEBUG(5,("iprint_job_pause(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
00537 
00538        /*
00539         * Make sure we don't ask for passwords...
00540         */
00541 
00542         cupsSetPasswordCB(iprint_passwd_cb);
00543 
00544        /*
00545         * Try to connect to the server...
00546         */
00547 
00548         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00549                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00550                          iprint_server(), strerror(errno)));
00551                 goto out;
00552         }
00553 
00554        /*
00555         * Build an IPP_HOLD_JOB request, which requires the following
00556         * attributes:
00557         *
00558         *    attributes-charset
00559         *    attributes-natural-language
00560         *    printer-uri
00561         *    job-id
00562         *    requesting-user-name
00563         */
00564 
00565         request = ippNew();
00566 
00567         request->request.op.operation_id = IPP_HOLD_JOB;
00568         request->request.op.request_id   = 1;
00569 
00570         language = cupsLangDefault();
00571 
00572         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00573                      "attributes-charset", NULL, "utf-8");
00574 
00575         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00576                      "attributes-natural-language", NULL, language->language);
00577 
00578         slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), PRINTERNAME(snum));
00579 
00580         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
00581 
00582         ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", pjob->sysjob);
00583 
00584         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
00585                      NULL, pjob->user);
00586 
00587        /*
00588         * Do the request and get back a response...
00589         */
00590 
00591         slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", PRINTERNAME(snum));
00592 
00593         if ((response = cupsDoRequest(http, request, httpPath)) != NULL) {
00594                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
00595                         DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
00596                                 ippErrorString(cupsLastError())));
00597                 } else {
00598                         ret = 0;
00599                 }
00600         } else {
00601                 DEBUG(0,("Unable to hold job %d - %s\n", pjob->sysjob,
00602                         ippErrorString(cupsLastError())));
00603         }
00604 
00605  out:
00606         if (response)
00607                 ippDelete(response);
00608 
00609         if (language)
00610                 cupsLangFree(language);
00611 
00612         if (http)
00613                 httpClose(http);
00614 
00615         return ret;
00616 }
00617 
00618 
00619 /*
00620  * 'iprint_job_resume()' - Resume a paused job.
00621  */
00622 
00623 static int iprint_job_resume(int snum, struct printjob *pjob)
00624 {
00625         int             ret = 1;                /* Return value */
00626         http_t          *http = NULL;           /* HTTP connection to server */
00627         ipp_t           *request = NULL,        /* IPP Request */
00628                         *response = NULL;       /* IPP Response */
00629         cups_lang_t     *language = NULL;       /* Default language */
00630         char            uri[HTTP_MAX_URI];      /* printer-uri attribute */
00631         char            httpPath[HTTP_MAX_URI]; /* path portion of the printer-uri */
00632 
00633 
00634         DEBUG(5,("iprint_job_resume(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
00635 
00636        /*
00637         * Make sure we don't ask for passwords...
00638         */
00639 
00640         cupsSetPasswordCB(iprint_passwd_cb);
00641 
00642        /*
00643         * Try to connect to the server...
00644         */
00645 
00646         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00647                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00648                          iprint_server(), strerror(errno)));
00649                 goto out;
00650         }
00651 
00652        /*
00653         * Build an IPP_RELEASE_JOB request, which requires the following
00654         * attributes:
00655         *
00656         *    attributes-charset
00657         *    attributes-natural-language
00658         *    printer-uri
00659         *    job-id
00660         *    requesting-user-name
00661         */
00662 
00663         request = ippNew();
00664 
00665         request->request.op.operation_id = IPP_RELEASE_JOB;
00666         request->request.op.request_id   = 1;
00667 
00668         language = cupsLangDefault();
00669 
00670         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00671                      "attributes-charset", NULL, "utf-8");
00672 
00673         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00674                      "attributes-natural-language", NULL, language->language);
00675 
00676         slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), PRINTERNAME(snum));
00677 
00678         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
00679 
00680         ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", pjob->sysjob);
00681 
00682         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
00683                      NULL, pjob->user);
00684 
00685        /*
00686         * Do the request and get back a response...
00687         */
00688 
00689         slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", PRINTERNAME(snum));
00690 
00691         if ((response = cupsDoRequest(http, request, httpPath)) != NULL) {
00692                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
00693                         DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
00694                                 ippErrorString(cupsLastError())));
00695                 } else {
00696                         ret = 0;
00697                 }
00698         } else {
00699                 DEBUG(0,("Unable to release job %d - %s\n", pjob->sysjob,
00700                         ippErrorString(cupsLastError())));
00701         }
00702 
00703  out:
00704         if (response)
00705                 ippDelete(response);
00706 
00707         if (language)
00708                 cupsLangFree(language);
00709 
00710         if (http)
00711                 httpClose(http);
00712 
00713         return ret;
00714 }
00715 
00716 
00717 /*
00718  * 'iprint_job_submit()' - Submit a job for printing.
00719  */
00720 
00721 static int iprint_job_submit(int snum, struct printjob *pjob)
00722 {
00723         int             ret = 1;                /* Return value */
00724         http_t          *http = NULL;           /* HTTP connection to server */
00725         ipp_t           *request = NULL,        /* IPP Request */
00726                         *response = NULL;       /* IPP Response */
00727         ipp_attribute_t *attr;          /* Current attribute */
00728         cups_lang_t     *language = NULL;       /* Default language */
00729         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
00730         char            *clientname = NULL;     /* hostname of client for job-originating-host attribute */
00731 
00732         DEBUG(5,("iprint_job_submit(%d, %p (%d))\n", snum, pjob, pjob->sysjob));
00733 
00734        /*
00735         * Make sure we don't ask for passwords...
00736         */
00737 
00738         cupsSetPasswordCB(iprint_passwd_cb);
00739 
00740        /*
00741         * Try to connect to the server...
00742         */
00743 
00744         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00745                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00746                          iprint_server(), strerror(errno)));
00747                 goto out;
00748         }
00749 
00750        /*
00751         * Build an IPP_PRINT_JOB request, which requires the following
00752         * attributes:
00753         *
00754         *    attributes-charset
00755         *    attributes-natural-language
00756         *    printer-uri
00757         *    requesting-user-name
00758         *    [document-data]
00759         */
00760 
00761         request = ippNew();
00762 
00763         request->request.op.operation_id = IPP_PRINT_JOB;
00764         request->request.op.request_id   = 1;
00765 
00766         language = cupsLangDefault();
00767 
00768         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00769                      "attributes-charset", NULL, "utf-8");
00770 
00771         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00772                      "attributes-natural-language", NULL, language->language);
00773 
00774         slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), PRINTERNAME(snum));
00775 
00776         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
00777                      "printer-uri", NULL, uri);
00778 
00779         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
00780                      NULL, pjob->user);
00781 
00782         clientname = client_name();
00783         if (strcmp(clientname, "UNKNOWN") == 0) {
00784                 clientname = client_addr();
00785         }
00786 
00787         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
00788                      "job-originating-host-name", NULL,
00789                      clientname);
00790 
00791         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
00792                      pjob->jobname);
00793 
00794        /*
00795         * Do the request and get back a response...
00796         */
00797 
00798         slprintf(uri, sizeof(uri) - 1, "/ipp/%s", PRINTERNAME(snum));
00799 
00800         if ((response = cupsDoFileRequest(http, request, uri, pjob->filename)) != NULL) {
00801                 if (response->request.status.status_code >= IPP_OK_CONFLICT) {
00802                         DEBUG(0,("Unable to print file to %s - %s\n", PRINTERNAME(snum),
00803                                  ippErrorString(cupsLastError())));
00804                 } else {
00805                         ret = 0;
00806                 }
00807         } else {
00808                 DEBUG(0,("Unable to print file to `%s' - %s\n", PRINTERNAME(snum),
00809                          ippErrorString(cupsLastError())));
00810         }
00811 
00812         if ( ret == 0 )
00813                 unlink(pjob->filename);
00814         /* else print_job_end will do it for us */
00815 
00816         if ( ret == 0 ) {
00817 
00818                 attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER);
00819                 if (attr != NULL && attr->group_tag == IPP_TAG_JOB)
00820                 {
00821                         pjob->sysjob = attr->values[0].integer;
00822                 }
00823         }
00824 
00825  out:
00826         if (response)
00827                 ippDelete(response);
00828 
00829         if (language)
00830                 cupsLangFree(language);
00831 
00832         if (http)
00833                 httpClose(http);
00834 
00835         return ret;
00836 }
00837 
00838 /*
00839  * 'iprint_queue_get()' - Get all the jobs in the print queue.
00840  */
00841 
00842 static int iprint_queue_get(const char *sharename,
00843                             enum printing_types printing_type,
00844                             char *lpq_command,
00845                             print_queue_struct **q, 
00846                             print_status_struct *status)
00847 {
00848         fstring         printername;
00849         http_t          *http = NULL;           /* HTTP connection to server */
00850         ipp_t           *request = NULL,        /* IPP Request */
00851                         *response = NULL;       /* IPP Response */
00852         ipp_attribute_t *attr = NULL;           /* Current attribute */
00853         cups_lang_t     *language = NULL;       /* Default language */
00854         char            uri[HTTP_MAX_URI]; /* printer-uri attribute */
00855         char            serviceUri[HTTP_MAX_URI]; /* service-uri attribute */
00856         char            httpPath[HTTP_MAX_URI]; /* path portion of the uri */
00857         int             jobUseUnixTime = 0;     /* Whether job times should
00858                                                  * be assumed to be Unix time */
00859         int             qcount = 0,             /* Number of active queue entries */
00860                         qalloc = 0;             /* Number of queue entries allocated */
00861         print_queue_struct *queue = NULL,       /* Queue entries */
00862                         *temp;          /* Temporary pointer for queue */
00863         const char      *user_name,     /* job-originating-user-name attribute */
00864                         *job_name;      /* job-name attribute */
00865         int             job_id;         /* job-id attribute */
00866         int             job_k_octets;   /* job-k-octets attribute */
00867         time_t          job_time;       /* time-at-creation attribute */
00868         time_t          printer_current_time = 0;       /* printer's current time */
00869         time_t          printer_up_time = 0;    /* printer's uptime */
00870         ipp_jstate_t    job_status;     /* job-status attribute */
00871         int             job_priority;   /* job-priority attribute */
00872         static const char *jattrs[] =   /* Requested job attributes */
00873                         {
00874                           "job-id",
00875                           "job-k-octets",
00876                           "job-name",
00877                           "job-originating-user-name",
00878                           "job-priority",
00879                           "job-state",
00880                           "time-at-creation",
00881                         };
00882         static const char *pattrs[] =   /* Requested printer attributes */
00883                         {
00884                           "printer-state",
00885                           "printer-state-message",
00886                           "printer-current-time",
00887                           "printer-up-time"
00888                         };
00889 
00890         *q = NULL;
00891 
00892         /* HACK ALERT!!!  The porblem with support the 'printer name' 
00893            option is that we key the tdb off the sharename.  So we will 
00894            overload the lpq_command string to pass in the printername 
00895            (which is basically what we do for non-cups printers ... using 
00896            the lpq_command to get the queue listing). */
00897 
00898         fstrcpy( printername, lpq_command );
00899 
00900         DEBUG(5,("iprint_queue_get(%s, %p, %p)\n", printername, q, status));
00901 
00902        /*
00903         * Make sure we don't ask for passwords...
00904         */
00905 
00906         cupsSetPasswordCB(iprint_passwd_cb);
00907 
00908        /*
00909         * Try to connect to the server...
00910         */
00911 
00912         if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
00913                 DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
00914                          iprint_server(), strerror(errno)));
00915                 goto out;
00916         }
00917 
00918        /*
00919         * Generate the printer URI and the service URI that goes with it...
00920         */
00921 
00922         slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), printername);
00923         slprintf(serviceUri, sizeof(serviceUri) - 1, "ipp://%s/ipp/", iprint_server());
00924 
00925        /*
00926         * For Linux iPrint servers from OES SP1 on, the iPrint server
00927         * uses Unix time for job start times unless it detects the iPrint
00928         * client in an http User-Agent header.  (This was done to accomodate
00929         * CUPS broken behavior.  According to RFC 2911, section 4.3.14, job
00930         * start times are supposed to be relative to how long the printer has
00931         * been up.)  Since libcups doesn't allow us to set that header before
00932         * the request is sent, this ugly hack allows us to detect the server
00933         * version and decide how to interpret the job time.
00934         */
00935         if (iprint_get_server_version(http, serviceUri) >=
00936             NOVELL_SERVER_VERSION_OES_SP1)
00937                 jobUseUnixTime = 1;
00938 
00939         request = ippNew();
00940 
00941         request->request.op.operation_id = IPP_GET_PRINTER_ATTRIBUTES;
00942         request->request.op.request_id   = 2;
00943 
00944         language = cupsLangDefault();
00945 
00946         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
00947                      "attributes-charset", NULL, "utf-8");
00948 
00949         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
00950                      "attributes-natural-language", NULL, language->language);
00951 
00952         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
00953                      "printer-uri", NULL, uri);
00954 
00955         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
00956                       "requested-attributes",
00957                       (sizeof(pattrs) / sizeof(pattrs[0])),
00958                       NULL, pattrs);
00959 
00960        /*
00961         * Do the request and get back a response...
00962         */
00963 
00964         slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername);
00965 
00966         if ((response = cupsDoRequest(http, request, httpPath)) == NULL) {
00967                 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
00968                          ippErrorString(cupsLastError())));
00969                 *q = queue;
00970                 goto out;
00971         }
00972 
00973         if (response->request.status.status_code >= IPP_OK_CONFLICT) {
00974                 DEBUG(0,("Unable to get printer status for %s - %s\n", printername,
00975                          ippErrorString(response->request.status.status_code)));
00976                 *q = queue;
00977                 goto out;
00978         }
00979 
00980        /*
00981         * Get the current printer status and convert it to the SAMBA values.
00982         */
00983 
00984         if ((attr = ippFindAttribute(response, "printer-state", IPP_TAG_ENUM)) != NULL) {
00985                 if (attr->values[0].integer == IPP_PRINTER_STOPPED)
00986                         status->status = LPSTAT_STOPPED;
00987                 else
00988                         status->status = LPSTAT_OK;
00989         }
00990 
00991         if ((attr = ippFindAttribute(response, "printer-state-message",
00992                                      IPP_TAG_TEXT)) != NULL)
00993                 fstrcpy(status->message, attr->values[0].string.text);
00994 
00995         if ((attr = ippFindAttribute(response, "printer-current-time",
00996                                      IPP_TAG_DATE)) != NULL)
00997                 printer_current_time = ippDateToTime(attr->values[0].date);
00998 
00999         if ((attr = ippFindAttribute(response, "printer-up-time",
01000                                      IPP_TAG_INTEGER)) != NULL)
01001                 printer_up_time = attr->values[0].integer;
01002 
01003         ippDelete(response);
01004         response = NULL;
01005 
01006        /*
01007         * Build an IPP_GET_JOBS request, which requires the following
01008         * attributes:
01009         *
01010         *    attributes-charset
01011         *    attributes-natural-language
01012         *    requested-attributes
01013         *    printer-uri
01014         */
01015 
01016         request = ippNew();
01017 
01018         request->request.op.operation_id = IPP_GET_JOBS;
01019         request->request.op.request_id   = 3;
01020 
01021         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
01022                      "attributes-charset", NULL, "utf-8");
01023 
01024         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
01025                      "attributes-natural-language", NULL, language->language);
01026 
01027         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
01028                      "printer-uri", NULL, uri);
01029 
01030         ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
01031                       "requested-attributes",
01032                       (sizeof(jattrs) / sizeof(jattrs[0])),
01033                       NULL, jattrs);
01034 
01035        /*
01036         * Do the request and get back a response...
01037         */
01038 
01039         slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", printername);
01040 
01041         if ((response = cupsDoRequest(http, request, httpPath)) == NULL) {
01042                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
01043                          ippErrorString(cupsLastError())));
01044                 goto out;
01045         }
01046 
01047         if (response->request.status.status_code >= IPP_OK_CONFLICT) {
01048                 DEBUG(0,("Unable to get jobs for %s - %s\n", uri,
01049                          ippErrorString(response->request.status.status_code)));
01050                 goto out;
01051         }
01052 
01053        /*
01054         * Process the jobs...
01055         */
01056 
01057         qcount = 0;
01058         qalloc = 0;
01059         queue  = NULL;
01060 
01061         for (attr = response->attrs; attr != NULL; attr = attr->next) {
01062                /*
01063                 * Skip leading attributes until we hit a job...
01064                 */
01065 
01066                 while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
01067                         attr = attr->next;
01068 
01069                 if (attr == NULL)
01070                         break;
01071 
01072                /*
01073                 * Allocate memory as needed...
01074                 */
01075                 if (qcount >= qalloc) {
01076                         qalloc += 16;
01077 
01078                         queue = SMB_REALLOC_ARRAY(queue, print_queue_struct, qalloc);
01079 
01080                         if (queue == NULL) {
01081                                 DEBUG(0,("iprint_queue_get: Not enough memory!"));
01082                                 qcount = 0;
01083                                 goto out;
01084                         }
01085                 }
01086 
01087                 temp = queue + qcount;
01088                 memset(temp, 0, sizeof(print_queue_struct));
01089 
01090                /*
01091                 * Pull the needed attributes from this job...
01092                 */
01093 
01094                 job_id       = 0;
01095                 job_priority = 50;
01096                 job_status   = IPP_JOB_PENDING;
01097                 job_time     = 0;
01098                 job_k_octets = 0;
01099                 user_name    = NULL;
01100                 job_name     = NULL;
01101 
01102                 while (attr != NULL && attr->group_tag == IPP_TAG_JOB) {
01103                         if (attr->name == NULL) {
01104                                 attr = attr->next;
01105                                 break;
01106                         }
01107 
01108                         if (strcmp(attr->name, "job-id") == 0 &&
01109                             attr->value_tag == IPP_TAG_INTEGER)
01110                                 job_id = attr->values[0].integer;
01111 
01112                         if (strcmp(attr->name, "job-k-octets") == 0 &&
01113                             attr->value_tag == IPP_TAG_INTEGER)
01114                                 job_k_octets = attr->values[0].integer;
01115 
01116                         if (strcmp(attr->name, "job-priority") == 0 &&
01117                             attr->value_tag == IPP_TAG_INTEGER)
01118                                 job_priority = attr->values[0].integer;
01119 
01120                         if (strcmp(attr->name, "job-state") == 0 &&
01121                             attr->value_tag == IPP_TAG_ENUM)
01122                                 job_status = (ipp_jstate_t)(attr->values[0].integer);
01123 
01124                         if (strcmp(attr->name, "time-at-creation") == 0 &&
01125                             attr->value_tag == IPP_TAG_INTEGER)
01126                         {
01127                                /*
01128                                 * If jobs times are in Unix time, the accuracy of the job
01129                                 * start time depends upon the iPrint server's time being
01130                                 * set correctly.  Otherwise, the accuracy depends upon
01131                                 * the Samba server's time being set correctly
01132                                 */
01133 
01134                                 if (jobUseUnixTime)
01135                                         job_time = attr->values[0].integer; 
01136                                 else
01137                                         job_time = time(NULL) - printer_up_time + attr->values[0].integer;
01138                         }
01139 
01140                         if (strcmp(attr->name, "job-name") == 0 &&
01141                             (attr->value_tag == IPP_TAG_NAMELANG ||
01142                              attr->value_tag == IPP_TAG_NAME))
01143                                 job_name = attr->values[0].string.text;
01144 
01145                         if (strcmp(attr->name, "job-originating-user-name") == 0 &&
01146                             (attr->value_tag == IPP_TAG_NAMELANG ||
01147                              attr->value_tag == IPP_TAG_NAME))
01148                                 user_name = attr->values[0].string.text;
01149 
01150                         attr = attr->next;
01151                 }
01152 
01153                /*
01154                 * See if we have everything needed...
01155                 */
01156 
01157                 if (user_name == NULL || job_name == NULL || job_id == 0) {
01158                         if (attr == NULL)
01159                                 break;
01160                         else
01161                                 continue;
01162                 }
01163 
01164                 temp->job      = job_id;
01165                 temp->size     = job_k_octets * 1024;
01166                 temp->status   = job_status == IPP_JOB_PENDING ? LPQ_QUEUED :
01167                                  job_status == IPP_JOB_STOPPED ? LPQ_PAUSED :
01168                                  job_status == IPP_JOB_HELD ? LPQ_PAUSED :
01169                                  LPQ_PRINTING;
01170                 temp->priority = job_priority;
01171                 temp->time     = job_time;
01172                 strncpy(temp->fs_user, user_name, sizeof(temp->fs_user) - 1);
01173                 strncpy(temp->fs_file, job_name, sizeof(temp->fs_file) - 1);
01174 
01175                 qcount ++;
01176 
01177                 if (attr == NULL)
01178                         break;
01179         }
01180 
01181        /*
01182         * Return the job queue...
01183         */
01184 
01185         *q = queue;
01186 
01187  out:
01188         if (response)
01189                 ippDelete(response);
01190 
01191         if (language)
01192                 cupsLangFree(language);
01193 
01194         if (http)
01195                 httpClose(http);
01196 
01197         return qcount;
01198 }
01199 
01200 
01201 /*
01202  * 'iprint_queue_pause()' - Pause a print queue.
01203  */
01204 
01205 static int iprint_queue_pause(int snum)
01206 {
01207         return(-1); /* Not supported without credentials */
01208 }
01209 
01210 
01211 /*
01212  * 'iprint_queue_resume()' - Restart a print queue.
01213  */
01214 
01215 static int iprint_queue_resume(int snum)
01216 {
01217         return(-1); /* Not supported without credentials */
01218 }
01219 
01220 /*******************************************************************
01221  * iPrint printing interface definitions...
01222  ******************************************************************/
01223 
01224 struct printif  iprint_printif =
01225 {
01226         PRINT_IPRINT,
01227         iprint_queue_get,
01228         iprint_queue_pause,
01229         iprint_queue_resume,
01230         iprint_job_delete,
01231         iprint_job_pause,
01232         iprint_job_resume,
01233         iprint_job_submit,
01234 };
01235 
01236 #else
01237  /* this keeps fussy compilers happy */
01238  void print_iprint_dummy(void);
01239  void print_iprint_dummy(void) {}
01240 #endif /* HAVE_IPRINT */

Sambaに対してSat Aug 29 21:23:14 2009に生成されました。  doxygen 1.4.7