]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cgi-bin/ipp-var.c
Import CUPS 1.4svn-r7226.
[thirdparty/cups.git] / cgi-bin / ipp-var.c
index 292cfea24664ba3de4ce104892b68889d5c50f48..098d0863072a1b21315a8bc591d1dfbb8989ecc3 100644 (file)
@@ -1,34 +1,30 @@
 /*
- * "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $"
+ * "$Id: ipp-var.c 6889 2007-08-29 22:23:35Z mike $"
  *
  *   CGI <-> IPP variable routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 1997-2006 by Easy Software Products.
+ *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
- *   property of Easy Software Products and are protected by Federal
- *   copyright law.  Distribution and use rights are outlined in the file
- *   "LICENSE.txt" which should have been included with this file.  If this
- *   file is missing or damaged please contact Easy Software Products
- *   at:
- *
- *       Attn: CUPS Licensing Information
- *       Easy Software Products
- *       44141 Airport View Drive, Suite 204
- *       Hollywood, Maryland 20636 USA
- *
- *       Voice: (301) 373-9600
- *       EMail: cups-info@cups.org
- *         WWW: http://www.cups.org
+ *   property of Apple Inc. and are protected by Federal copyright
+ *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ *   which should have been included with this file.  If this file is
+ *   file is missing or damaged, see the license at "http://www.cups.org/".
  *
  * Contents:
  *
  *   cgiGetAttributes()    - Get the list of attributes that are needed
  *                           by the template file.
- *   cupsGetIPPObjects()   - Get the objects in an IPP response.
+ *   cgiGetIPPObjects()    - Get the objects in an IPP response.
+ *   cgiMoveJobs()         - Move one or more jobs.
+ *   cgiPrintTestPage()    - Print a test page.
  *   cgiRewriteURL()       - Rewrite a printer URI into a web browser URL...
  *   cgiSetIPPObjectVars() - Set CGI variables from an IPP object.
  *   cgiSetIPPVars()       - Set CGI variables from an IPP response.
+ *   cgiShowIPPError()     - Show the last IPP error message.
+ *   cgiShowJobs()         - Show print jobs.
+ *   cgiText()             - Return localized text.
  */
 
 /*
@@ -105,6 +101,7 @@ cgiGetAttributes(ipp_t      *request,       /* I - IPP request */
   */
 
   num_attrs = 0;
+  attrs[0]  = NULL;                    /* Eliminate compiler warning */
 
   while ((ch = getc(in)) != EOF)
     if (ch == '\\')
@@ -161,11 +158,13 @@ cgiGetAttributes(ipp_t      *request,     /* I - IPP request */
     for (i = 0; i < num_attrs; i ++)
       free(attrs[i]);
   }
+
+  fclose(in);
 }
 
 
 /*
- * 'cupsGetIPPObjects()' - Get the objects in an IPP response.
+ * 'cgiGetIPPObjects()' - Get the objects in an IPP response.
  */
 
 cups_array_t *                         /* O - Array of objects */
@@ -263,6 +262,355 @@ cgiGetIPPObjects(ipp_t *response, /* I - IPP response */
 }
 
 
+/*
+ * 'cgiMoveJobs()' - Move one or more jobs.
+ *
+ * At least one of dest or job_id must be non-zero/NULL.
+ */
+
+void
+cgiMoveJobs(http_t     *http,          /* I - Connection to server */
+            const char *dest,          /* I - Destination or NULL */
+            int        job_id)         /* I - Job ID or 0 for all */
+{
+  int          i;                      /* Looping var */
+  const char   *user;                  /* Username */
+  ipp_t                *request,               /* IPP request */
+               *response;              /* IPP response */
+  ipp_attribute_t *attr;               /* Current attribute */
+  const char   *name;                  /* Destination name */
+  const char   *job_printer_uri;       /* JOB_PRINTER_URI form variable */
+  char         current_dest[1024];     /* Current destination */
+
+
+ /*
+  * See who is logged in...
+  */
+
+  if ((user = getenv("REMOTE_USER")) == NULL)
+    user = "guest";
+
+ /*
+  * See if the user has already selected a new destination...
+  */
+
+  if ((job_printer_uri = cgiGetVariable("JOB_PRINTER_URI")) == NULL)
+  {
+   /*
+    * Make sure necessary form variables are set...
+    */
+
+    if (job_id)
+    {
+      char     temp[255];              /* Temporary string */
+
+
+      sprintf(temp, "%d", job_id);
+      cgiSetVariable("JOB_ID", temp);
+    }
+
+    if (dest)
+      cgiSetVariable("PRINTER_NAME", dest);
+
+   /*
+    * No new destination specified, show the user what the available
+    * printers/classes are...
+    */
+
+    if (!dest)
+    {
+     /*
+      * Get the current destination for job N...
+      */
+
+      char     job_uri[1024];          /* Job URI */
+
+
+      request = ippNewRequest(IPP_GET_JOB_ATTRIBUTES);
+
+      snprintf(job_uri, sizeof(job_uri), "ipp://localhost/jobs/%d", job_id);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+                   NULL, job_uri);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                   "requested-attributes", NULL, "job-printer-uri");
+      
+      if ((response = cupsDoRequest(http, request, "/")) != NULL)
+      {
+        if ((attr = ippFindAttribute(response, "job-printer-uri",
+                                    IPP_TAG_URI)) != NULL)
+       {
+        /*
+         * Pull the name from the URI...
+         */
+
+         strlcpy(current_dest, strrchr(attr->values[0].string.text, '/') + 1,
+                 sizeof(current_dest));
+          dest = current_dest;
+       }
+
+        ippDelete(response);
+      }
+
+      if (!dest)
+      {
+       /*
+        * Couldn't get the current destination...
+       */
+
+        cgiStartHTML(cgiText(_("Move Job")));
+       cgiShowIPPError(_("Unable to find destination for job!"));
+       cgiEndHTML();
+       return;
+      }
+    }
+
+   /*
+    * Get the list of available destinations...
+    */
+
+    request = ippNewRequest(CUPS_GET_PRINTERS);
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                 "requested-attributes", NULL, "printer-uri-supported");
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+                 "requesting-user-name", NULL, user);
+
+    if ((response = cupsDoRequest(http, request, "/")) != NULL)
+    {
+      for (i = 0, attr = ippFindAttribute(response, "printer-uri-supported",
+                                          IPP_TAG_URI);
+           attr;
+          attr = ippFindNextAttribute(response, "printer-uri-supported",
+                                      IPP_TAG_URI))
+      {
+       /*
+       * Pull the name from the URI...
+       */
+
+       name = strrchr(attr->values[0].string.text, '/') + 1;
+
+       /*
+        * If the name is not the same as the current destination, add it!
+       */
+
+        if (strcasecmp(name, dest))
+       {
+         cgiSetArray("JOB_PRINTER_URI", i, attr->values[0].string.text);
+         cgiSetArray("JOB_PRINTER_NAME", i, name);
+         i ++;
+       }
+      }
+
+      ippDelete(response);
+    }
+
+   /*
+    * Show the form...
+    */
+
+    if (job_id)
+      cgiStartHTML(cgiText(_("Move Job")));
+    else
+      cgiStartHTML(cgiText(_("Move All Jobs")));
+
+    cgiCopyTemplateLang("job-move.tmpl");
+  }
+  else
+  {
+   /*
+    * Try moving the job or jobs...
+    */
+
+    char       uri[1024],              /* Job/printer URI */
+               resource[1024],         /* Post resource */
+               refresh[1024];          /* Refresh URL */
+    const char *job_printer_name;      /* New printer name */
+
+
+    request = ippNewRequest(CUPS_MOVE_JOB);
+
+    if (job_id)
+    {
+     /*
+      * Move 1 job...
+      */
+
+      snprintf(resource, sizeof(resource), "/jobs/%d", job_id);
+
+      snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", job_id);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
+                   NULL, uri);
+    }
+    else
+    {
+     /*
+      * Move all active jobs on a destination...
+      */
+
+      snprintf(resource, sizeof(resource), "/%s/%s",
+               cgiGetVariable("SECTION"), dest);
+
+      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                       "localhost", ippPort(), "/%s/%s",
+                      cgiGetVariable("SECTION"), dest);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+                   NULL, uri);
+    }
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-printer-uri",
+                 NULL, job_printer_uri);
+
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+                 "requesting-user-name", NULL, user);
+
+    ippDelete(cupsDoRequest(http, request, resource));
+
+   /*
+    * Show the results...
+    */
+
+    job_printer_name = strrchr(job_printer_uri, '/') + 1;
+
+    if (cupsLastError() <= IPP_OK_CONFLICT)
+    {
+      cgiRewriteURL(job_printer_uri, resource, sizeof(resource), NULL);
+      cgiFormEncode(uri, resource, sizeof(uri));
+      snprintf(refresh, sizeof(refresh), "2;URL=%s", uri);
+      cgiSetVariable("refresh_page", refresh);
+    }
+
+    if (job_id)
+      cgiStartHTML(cgiText(_("Move Job")));
+    else
+      cgiStartHTML(cgiText(_("Move All Jobs")));
+
+    if (cupsLastError() > IPP_OK_CONFLICT)
+    {
+      if (job_id)
+       cgiShowIPPError(_("Unable to move job"));
+      else
+        cgiShowIPPError(_("Unable to move jobs"));
+    }
+    else
+    {
+      cgiSetVariable("JOB_PRINTER_NAME", job_printer_name);
+      cgiCopyTemplateLang("job-moved.tmpl");
+    }
+  }
+
+  cgiEndHTML();
+}
+
+
+/*
+ * 'cgiPrintTestPage()' - Print a test page.
+ */
+
+void
+cgiPrintTestPage(http_t     *http,     /* I - Connection to server */
+                 const char *dest)     /* I - Destination printer/class */
+{
+  ipp_t                *request,               /* IPP request */
+               *response;              /* IPP response */
+  char         uri[HTTP_MAX_URI],      /* Printer URI */
+               resource[1024],         /* POST resource path */
+               refresh[1024],          /* Refresh URL */
+               filename[1024];         /* Test page filename */
+  const char   *datadir;               /* CUPS_DATADIR env var */
+  const char   *user;                  /* Username */
+
+
+ /*
+  * See who is logged in...
+  */
+
+  if ((user = getenv("REMOTE_USER")) == NULL)
+    user = "guest";
+
+ /*
+  * Locate the test page file...
+  */
+
+  if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+    datadir = CUPS_DATADIR;
+
+  snprintf(filename, sizeof(filename), "%s/data/testprint.ps", datadir);
+
+ /*
+  * Point to the printer/class...
+  */
+
+  snprintf(resource, sizeof(resource), "/%s/%s", cgiGetVariable("SECTION"),
+           dest);
+
+  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                   "localhost", ippPort(), "/%s/%s", cgiGetVariable("SECTION"),
+                  dest);
+
+ /*
+  * Build an IPP_PRINT_JOB request, which requires the following
+  * attributes:
+  *
+  *    attributes-charset
+  *    attributes-natural-language
+  *    printer-uri
+  *    requesting-user-name
+  *    document-format
+  */
+
+  request = ippNewRequest(IPP_PRINT_JOB);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, uri);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+               "requesting-user-name", NULL, user);
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name",
+               NULL, "Test Page");
+
+  ippAddString(request, IPP_TAG_JOB, IPP_TAG_MIMETYPE, "document-format",
+               NULL, "application/postscript");
+
+ /*
+  * Do the request and get back a response...
+  */
+
+  if ((response = cupsDoFileRequest(http, request, resource,
+                                    filename)) != NULL)
+  {
+    cgiSetIPPVars(response, NULL, NULL, NULL, 0);
+
+    ippDelete(response);
+  }
+
+  if (cupsLastError() <= IPP_OK_CONFLICT)
+  {
+   /*
+    * Automatically reload the printer status page...
+    */
+
+    cgiFormEncode(uri, resource, sizeof(uri));
+    snprintf(refresh, sizeof(refresh), "2;URL=%s", uri);
+    cgiSetVariable("refresh_page", refresh);
+  }
+
+  cgiStartHTML(cgiText(_("Print Test Page")));
+
+  if (cupsLastError() > IPP_OK_CONFLICT)
+    cgiShowIPPError(_("Unable to print test page:"));
+  else
+  {
+    cgiSetVariable("PRINTER_NAME", dest);
+
+    cgiCopyTemplateLang("test-page.tmpl");
+  }
+
+  cgiEndHTML();
+}
+
+
 /*
  * 'cgiRewriteURL()' - Rewrite a printer URI into a web browser URL...
  */
@@ -307,7 +655,7 @@ cgiRewriteURL(const char *uri,              /* I - Current URI */
     if ((server = getenv("SERVER_NAME")) == NULL)
       server = "";
 
-    httpGetHostname(servername, sizeof(servername));
+    httpGetHostname(NULL, servername, sizeof(servername));
 
    /*
     * Then flag whether we are using SSL on this connection...
@@ -320,8 +668,8 @@ cgiRewriteURL(const char *uri,              /* I - Current URI */
   * Convert the URI to a URL...
   */
 
-  httpSeparateURI(uri, method, sizeof(method), userpass, sizeof(userpass),
-                  hostname, sizeof(hostname), &port,
+  httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
+                  sizeof(userpass), hostname, sizeof(hostname), &port,
                  rawresource, sizeof(rawresource));
 
   if (!strcmp(method, "ipp") ||
@@ -420,7 +768,7 @@ cgiSetIPPObjectVars(
 
   fprintf(stderr, "DEBUG2: cgiSetIPPObjectVars(obj=%p, prefix=\"%s\", "
                   "element=%d)\n",
-          obj, prefix, element);
+          obj, prefix ? prefix : "(null)", element);
 
  /*
   * Set common CGI template variables...
@@ -473,6 +821,144 @@ cgiSetIPPObjectVars(
       cgiSetArray("job_printer_name", element, valptr);
     }
 
+   /*
+    * Localize event names in "notify_events" variable...
+    */
+
+    if (!strcmp(name, "notify_events"))
+    {
+      size_t   remaining;              /* Remaining bytes in buffer */
+
+
+      value[0] = '\0';
+      valptr   = value;
+
+      for (i = 0; i < attr->num_values; i ++)
+      {
+        if (valptr >= (value + sizeof(value) - 3))
+         break;
+
+        if (i)
+       {
+         *valptr++ = ',';
+         *valptr++ = ' ';
+        }
+
+        remaining = sizeof(value) - (valptr - value);
+
+        if (!strcmp(attr->values[i].string.text, "printer-stopped"))
+         strlcpy(valptr, _("Printer Paused"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "printer-added"))
+         strlcpy(valptr, _("Printer Added"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "printer-modified"))
+         strlcpy(valptr, _("Printer Modified"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "printer-deleted"))
+         strlcpy(valptr, _("Printer Deleted"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "job-created"))
+         strlcpy(valptr, _("Job Created"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "job-completed"))
+         strlcpy(valptr, _("Job Completed"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "job-stopped"))
+         strlcpy(valptr, _("Job Stopped"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "job-config-changed"))
+         strlcpy(valptr, _("Job Options Changed"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "server-restarted"))
+         strlcpy(valptr, _("Server Restarted"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "server-started"))
+         strlcpy(valptr, _("Server Started"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "server-stopped"))
+         strlcpy(valptr, _("Server Stopped"), remaining);
+       else if (!strcmp(attr->values[i].string.text, "server-audit"))
+         strlcpy(valptr, _("Server Security Auditing"), remaining);
+       else
+          strlcpy(valptr, attr->values[i].string.text, remaining);
+
+        valptr += strlen(valptr);
+      }
+
+      cgiSetArray("notify_events", element, value);
+      continue;
+    }
+
+   /*
+    * Add "notify_printer_name" variable if we have a "notify_printer_uri"
+    * attribute...
+    */
+
+    if (!strcmp(name, "notify_printer_uri"))
+    {
+      if ((valptr = strrchr(attr->values[0].string.text, '/')) == NULL)
+       valptr = "unknown";
+      else
+       valptr ++;
+
+      cgiSetArray("notify_printer_name", element, valptr);
+    }
+
+   /*
+    * Add "notify_recipient_name" variable if we have a "notify_recipient_uri"
+    * attribute, and rewrite recipient URI...
+    */
+
+    if (!strcmp(name, "notify_recipient_uri"))
+    {
+      char     uri[1024],              /* New URI */
+               scheme[32],             /* Scheme portion of URI */
+               userpass[256],          /* Username/password portion of URI */
+               host[1024],             /* Hostname portion of URI */
+               resource[1024],         /* Resource portion of URI */
+               *options;               /* Options in URI */
+      int      port;                   /* Port number */
+
+
+      httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
+                      scheme, sizeof(scheme), userpass, sizeof(userpass),
+                     host, sizeof(host), &port, resource, sizeof(resource));
+
+      if (!strcmp(scheme, "rss"))
+      {
+       /*
+        * RSS notification...
+       */
+
+        if ((options = strchr(resource, '?')) != NULL)
+         *options = '\0';
+
+        if (host[0])
+       {
+        /*
+         * Link to remote feed...
+         */
+
+         httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "http",
+                         userpass, host, port, resource);
+          strlcpy(name, uri, sizeof(name));
+       }
+       else
+       {
+        /*
+         * Link to local feed...
+         */
+
+         snprintf(uri, sizeof(uri), "/rss%s", resource);
+          strlcpy(name, resource + 1, sizeof(name));
+       }
+      }
+      else
+      {
+       /*
+        * Other...
+       */
+
+        strlcpy(uri, attr->values[0].string.text, sizeof(uri));
+       strlcpy(name, resource, sizeof(name));
+      }
+
+      cgiSetArray("notify_recipient_uri", element, uri);
+      cgiSetArray("notify_recipient_name", element, name);
+      continue;
+    }
+
    /*
     * Add "admin_uri" variable if we have a "printer_uri_supported"
     * attribute...
@@ -496,7 +982,7 @@ cgiSetIPPObjectVars(
     for (i = 0; i < attr->num_values; i ++)
     {
       if (i)
-       strlcat(valptr, ",", sizeof(value) - (valptr - value));
+       strlcat(valptr, ", ", sizeof(value) - (valptr - value));
 
       valptr += strlen(valptr);
 
@@ -542,7 +1028,8 @@ cgiSetIPPObjectVars(
            break;
 
        case IPP_TAG_URI :
-           if (strchr(attr->values[i].string.text, ':') != NULL)
+           if (strchr(attr->values[i].string.text, ':') &&
+               strcmp(name, "device_uri"))
            {
             /*
              * Rewrite URIs...
@@ -558,7 +1045,7 @@ cgiSetIPPObjectVars(
 
                 snprintf(valptr, sizeof(value) - (valptr - value),
                         "<A HREF=\"%s\">%s</A>", url,
-                        strrchr(url, '/') + 1);
+                        strrchr(attr->values[i].string.text, '/') + 1);
              }
              else
                cgiRewriteURL(attr->values[i].string.text, valptr,
@@ -622,7 +1109,9 @@ cgiSetIPPVars(ipp_t      *response,        /* I - Response data to be copied... */
 
   fprintf(stderr, "DEBUG2: cgiSetIPPVars(response=%p, filter_name=\"%s\", "
                   "filter_value=\"%s\", prefix=\"%s\", parent_el=%d)\n",
-          response, filter_name, filter_value, prefix, parent_el);
+          response, filter_name ? filter_name : "(null)",
+         filter_value ? filter_value : "(null)",
+         prefix ? prefix : "(null)", parent_el);
 
  /*
   * Set common CGI template variables...
@@ -680,9 +1169,24 @@ cgiSetIPPVars(ipp_t      *response,       /* I - Response data to be copied... */
     attr = cgiSetIPPObjectVars(attr, prefix, element);
   }
 
-  fprintf(stderr, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element + 1);
+  fprintf(stderr, "DEBUG2: Returing %d from cgiSetIPPVars()...\n", element);
+
+  return (element);
+}
+
+
+/*
+ * 'cgiShowIPPError()' - Show the last IPP error message.
+ *
+ * The caller must still call cgiStartHTML() and cgiEndHTML().
+ */
 
-  return (element + 1);
+void
+cgiShowIPPError(const char *message)   /* I - Contextual message */
+{
+  cgiSetVariable("MESSAGE", cgiText(message));
+  cgiSetVariable("ERROR", cupsLastErrorString());
+  cgiCopyTemplateLang("error.tmpl");
 }
 
 
@@ -705,10 +1209,8 @@ cgiShowJobs(http_t     *http,             /* I - Connection to server */
                        count;          /* Number of jobs */
   const char           *var;           /* Form variable */
   void                 *search;        /* Search data */
-  char                 url[1024],      /* URL for prev/next/this */
-                       *urlptr,        /* Position in URL */
-                       *urlend;        /* End of URL */
-  cups_lang_t          *language;      /* Language information */
+  char                 url[1024],      /* Printer URI */
+                       val[1024];      /* Form variable */
 
 
  /*
@@ -720,23 +1222,12 @@ cgiShowJobs(http_t     *http,            /* I - Connection to server */
   *    printer-uri
   */
 
-  request = ippNew();
-
-  language = cupsLangDefault();
-
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
-               "attributes-charset", NULL, cupsLangEncoding(language));
-
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
-               "attributes-natural-language", NULL, language->language);
-
-  request->request.op.operation_id = IPP_GET_JOBS;
-  request->request.op.request_id   = 1;
+  request = ippNewRequest(IPP_GET_JOBS);
 
   if (dest)
   {
-    httpAssembleURIf(url, sizeof(url), "ipp", NULL, "localhost", ippPort(),
-                     "/printers/%s", dest);
+    httpAssembleURIf(HTTP_URI_CODING_ALL, url, sizeof(url), "ipp", NULL,
+                     "localhost", ippPort(), "/printers/%s", dest);
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                  NULL, url);
   }
@@ -760,7 +1251,8 @@ cgiShowJobs(http_t     *http,              /* I - Connection to server */
     * Get a list of matching job objects.
     */
 
-    if (!dest && (var = cgiGetVariable("QUERY")) != NULL)
+    if ((var = cgiGetVariable("QUERY")) != NULL &&
+        !cgiGetVariable("CLEAR"))
       search = cgiCompileSearch(var);
     else
       search = NULL;
@@ -788,13 +1280,16 @@ cgiShowJobs(http_t     *http,            /* I - Connection to server */
     if (first < 0)
       first = 0;
 
-    sprintf(url, "%d", count);
-    cgiSetVariable("TOTAL", url);
+    sprintf(val, "%d", count);
+    cgiSetVariable("TOTAL", val);
 
     if ((var = cgiGetVariable("ORDER")) != NULL)
       ascending = !strcasecmp(var, "asc");
     else
-      ascending = 1;
+    {
+      ascending = !which_jobs || !strcasecmp(which_jobs, "not-completed");
+      cgiSetVariable("ORDER", ascending ? "asc" : "dec");
+    }
 
     if (ascending)
     {
@@ -815,82 +1310,68 @@ cgiShowJobs(http_t     *http,            /* I - Connection to server */
     * Save navigation URLs...
     */
 
-    urlend = url + sizeof(url);
-
     if (dest)
-    {
-      snprintf(url, sizeof(url), "/%s/%s?", cgiGetVariable("SECTION"), dest);
-      urlptr = url + strlen(url);
-    }
-    else if ((var = cgiGetVariable("QUERY")) != NULL)
-    {
-      strlcpy(url, "/jobs/?QUERY=", sizeof(url));
-      urlptr = url + strlen(url);
-
-      cgiFormEncode(urlptr, var, urlend - urlptr);
-      urlptr += strlen(urlptr);
-
-      strlcpy(urlptr, "&", urlend - urlptr);
-      urlptr += strlen(urlptr);
-    }
+      snprintf(val, sizeof(val), "/%s/%s",  cgiGetVariable("SECTION"), dest);
     else
-    {
-      strlcpy(url, "/jobs/?", sizeof(url));
-      urlptr = url + strlen(url);
-    }
+      strlcpy(val, "/jobs/", sizeof(val));
 
-    if (which_jobs)
-    {
-      strlcpy(urlptr, "WHICH_JOBS=", urlend - urlptr);
-      urlptr += strlen(urlptr);
-
-      cgiFormEncode(urlptr, which_jobs, urlend - urlptr);
-      urlptr += strlen(urlptr);
-
-      strlcpy(urlptr, "&", urlend - urlptr);
-      urlptr += strlen(urlptr);
-    }
-
-    snprintf(urlptr, urlend - urlptr, "FIRST=%d", first);
-    cgiSetVariable("THISURL", url);
+    cgiSetVariable("THISURL", val);
 
     if (first > 0)
     {
-      snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s",
-              first - CUPS_PAGE_MAX, ascending ? "asc" : "dec");
-      cgiSetVariable("PREVURL", url);
+      sprintf(val, "%d", first - CUPS_PAGE_MAX);
+      cgiSetVariable("PREV", val);
     }
 
     if ((first + CUPS_PAGE_MAX) < count)
     {
-      snprintf(urlptr, urlend - urlptr, "FIRST=%d&ORDER=%s",
-              first + CUPS_PAGE_MAX, ascending ? "asc" : "dec");
-      cgiSetVariable("NEXTURL", url);
+      sprintf(val, "%d", first + CUPS_PAGE_MAX);
+      cgiSetVariable("NEXT", val);
     }
 
    /*
     * Then show everything...
     */
 
-    if (!dest)
-      cgiCopyTemplateLang("search.tmpl");
+    if (dest)
+      cgiSetVariable("SEARCH_DEST", dest);
+
+    cgiCopyTemplateLang("search.tmpl");
 
     cgiCopyTemplateLang("jobs-header.tmpl");
 
-    if (count > CUPS_PAGE_MAX)
-      cgiCopyTemplateLang("page.tmpl");
+    if (count > 0)
+      cgiCopyTemplateLang("pager.tmpl");
 
     cgiCopyTemplateLang("jobs.tmpl");
 
-    if (count > CUPS_PAGE_MAX)
-      cgiCopyTemplateLang("page.tmpl");
+    if (count > 0)
+      cgiCopyTemplateLang("pager.tmpl");
 
+    cupsArrayDelete(jobs);
     ippDelete(response);
   }
 }
 
 
+/*
+ * 'cgiText()' - Return localized text.
+ */
+
+const char *                           /* O - Localized message */
+cgiText(const char *message)           /* I - Message */
+{
+  static cups_lang_t   *language = NULL;
+                                       /* Language */
+
+
+  if (!language)
+    language = cupsLangDefault();
+
+  return (_cupsLangString(language, message));
+}
+
 
 /*
- * End of "$Id: ipp-var.c 4921 2006-01-12 21:26:26Z mike $".
+ * End of "$Id: ipp-var.c 6889 2007-08-29 22:23:35Z mike $".
  */