]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - cgi-bin/admin.c
Merge changes from CUPS 1.5svn-r9000.
[thirdparty/cups.git] / cgi-bin / admin.c
index 1601ef7c830657ca097a0b018d159c05dd8c522b..5617be2247bb0f268ef117014553fc1b2e46d901 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Administration CGI for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2010 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -52,8 +52,7 @@
  * Local globals...
  */
 
-static int     current_device;         /* Current device for add/modify */
-static time_t  last_device_time;       /* Last update time for device list */
+static int     current_device = 0;     /* Current device shown */
 
 
 /*
@@ -122,6 +121,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   */
 
   cgiSetVariable("SECTION", "admin");
+  cgiSetVariable("REFRESH_PAGE", "");
 
  /*
   * See if we have form data...
@@ -191,7 +191,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
   }
   else if (op && !strcmp(op, "redirect"))
   {
-    const char *url;                   /* Redirection URL... */
+    const char *url;                   /* Redirection URL... */
     char       prefix[1024];           /* URL prefix */
 
 
@@ -205,7 +205,50 @@ main(int  argc,                            /* I - Number of command-line arguments */
     fprintf(stderr, "DEBUG: redirecting with prefix %s!\n", prefix);
 
     if ((url = cgiGetVariable("URL")) != NULL)
-      printf("Location: %s%s\n\n", prefix, url);
+    {
+      char     encoded[1024],          /* Encoded URL string */
+               *ptr;                   /* Pointer into encoded string */
+
+
+      ptr = encoded;
+      if (*url != '/')
+        *ptr++ = '/';
+
+      for (; *url && ptr < (encoded + sizeof(encoded) - 4); url ++)
+      {
+        if (strchr("%@&+ <>#=", *url) || *url < ' ' || *url & 128)
+       {
+        /*
+         * Percent-encode this character; safe because we have at least 4
+         * bytes left in the array...
+         */
+
+         sprintf(ptr, "%%%02X", *url & 255);
+         ptr += 3;
+       }
+       else
+         *ptr++ = *url;
+      }
+
+      *ptr = '\0';
+
+      if (*url)
+      {
+       /*
+        * URL was too long, just redirect to the admin page...
+       */
+
+       printf("Location: %s/admin\n\n", prefix);
+      }
+      else
+      {
+       /*
+        * URL is OK, redirect there...
+       */
+
+        printf("Location: %s%s\n\n", prefix, encoded);
+      }
+    }
     else
       printf("Location: %s/admin\n\n", prefix);
   }
@@ -248,6 +291,21 @@ choose_device_cb(
     const char *device_location,       /* I - Location */
     const char *title)                 /* I - Page title */
 {
+ /*
+  * For modern browsers, start a multi-part page so we can show that something
+  * is happening.  Non-modern browsers just get everything at the end...
+  */
+
+  if (current_device == 0 && cgiSupportsMultipart())
+  {
+    cgiStartMultipart();
+    cgiStartHTML(title);
+    cgiCopyTemplateLang("choose-device.tmpl");
+    cgiEndHTML();
+    fflush(stdout);
+  }
+
+
  /*
   * Add the device to the array...
   */
@@ -260,23 +318,6 @@ choose_device_cb(
   cgiSetArray("device_location", current_device, device_location);
 
   current_device ++;
-
-  if (time(NULL) > last_device_time)
-  {
-   /*
-    * Update the page...
-    */
-
-    if (!last_device_time)
-      cgiStartMultipart();
-
-    cgiStartHTML(title);
-    cgiCopyTemplateLang("choose-device.tmpl");
-    cgiEndHTML();
-    fflush(stdout);
-
-    time(&last_device_time);
-  }
 }
 
 
@@ -345,6 +386,31 @@ do_add_rss_subscription(http_t *http)      /* I - HTTP connection */
     * and classes and (re)show the add page...
     */
 
+    if (cgiGetVariable("EVENT_JOB_CREATED"))
+      cgiSetVariable("EVENT_JOB_CREATED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_COMPLETED"))
+      cgiSetVariable("EVENT_JOB_COMPLETED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_STOPPED"))
+      cgiSetVariable("EVENT_JOB_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_JOB_CONFIG_CHANGED"))
+      cgiSetVariable("EVENT_JOB_CONFIG_CHANGED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_STOPPED"))
+      cgiSetVariable("EVENT_PRINTER_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_ADDED"))
+      cgiSetVariable("EVENT_PRINTER_ADDED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_MODIFIED"))
+      cgiSetVariable("EVENT_PRINTER_MODIFIED", "CHECKED");
+    if (cgiGetVariable("EVENT_PRINTER_DELETED"))
+      cgiSetVariable("EVENT_PRINTER_DELETED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_STARTED"))
+      cgiSetVariable("EVENT_SERVER_STARTED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_STOPPED"))
+      cgiSetVariable("EVENT_SERVER_STOPPED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_RESTARTED"))
+      cgiSetVariable("EVENT_SERVER_RESTARTED", "CHECKED");
+    if (cgiGetVariable("EVENT_SERVER_AUDIT"))
+      cgiSetVariable("EVENT_SERVER_AUDIT", "CHECKED");
+
     request  = ippNewRequest(CUPS_GET_PRINTERS);
     response = cupsDoRequest(http, request, "/");
 
@@ -467,6 +533,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
   ipp_attribute_t *attr;               /* member-uris attribute */
   char         uri[HTTP_MAX_URI];      /* Device or printer URI */
   const char   *name,                  /* Pointer to class name */
+               *op,                    /* Operation name */
                *ptr;                   /* Pointer to CGI variable */
   const char   *title;                 /* Title of page */
   static const char * const pattrs[] = /* Requested printer attributes */
@@ -478,6 +545,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
 
 
   title = cgiText(modify ? _("Modify Class") : _("Add Class"));
+  op    = cgiGetVariable("OP");
   name  = cgiGetVariable("PRINTER_NAME");
 
   if (cgiGetVariable("PRINTER_LOCATION") == NULL)
@@ -492,10 +560,22 @@ do_am_class(http_t *http,         /* I - HTTP connection */
 
     request = ippNewRequest(CUPS_GET_PRINTERS);
 
+    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+                 CUPS_PRINTER_LOCAL);
+    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+                 CUPS_PRINTER_CLASS | CUPS_PRINTER_REMOTE |
+                     CUPS_PRINTER_IMPLICIT);
+
    /*
     * Do the request and get back a response...
     */
 
+    cgiClearVariables();
+    if (op)
+      cgiSetVariable("OP", op);
+    if (name)
+      cgiSetVariable("PRINTER_NAME", name);
+
     if ((response = cupsDoRequest(http, request, "/")) != NULL)
     {
      /*
@@ -628,6 +708,15 @@ do_am_class(http_t *http,          /* I - HTTP connection */
     return;
   }
 
+  if (!name)
+  {
+    cgiStartHTML(title);
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
+    cgiCopyTemplateLang("error.tmpl");
+    cgiEndHTML();
+    return;
+  }
+
   for (ptr = name; *ptr; ptr ++)
     if ((*ptr >= 0 && *ptr <= ' ') || *ptr == 127 || *ptr == '/' || *ptr == '#')
       break;
@@ -662,8 +751,7 @@ do_am_class(http_t *http,           /* I - HTTP connection */
   request = ippNewRequest(CUPS_ADD_CLASS);
 
   httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                   "localhost", 0, "/classes/%s",
-                  cgiGetVariable("PRINTER_NAME"));
+                   "localhost", 0, "/classes/%s", name);
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                NULL, uri);
 
@@ -881,7 +969,8 @@ do_am_printer(http_t *http,         /* I - HTTP connection */
          if (isalnum(*uriptr & 255) || *uriptr == '_' || *uriptr == '-' ||
              *uriptr == '.')
            *tptr++ = *uriptr;
-         else if ((*uriptr == ' ' || *uriptr == '/') && tptr[-1] != '_')
+         else if ((*uriptr == ' ' || *uriptr == '/') && tptr > template &&
+                  tptr[-1] != '_')
            *tptr++ = '_';
          else if (*uriptr == '?' || *uriptr == '(')
            break;
@@ -910,18 +999,29 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
     }
 
    /*
-    * Scan for devices for up to 30 seconds, updating the page as we find
-    * them...
+    * Scan for devices for up to 30 seconds...
     */
 
     fputs("DEBUG: Getting list of devices...\n", stderr);
 
-    last_device_time = 0;
-    current_device   = 0;
+    current_device = 0;
     if (cupsGetDevices(http, 30, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE,
                        (cups_device_cb_t)choose_device_cb,
                       (void *)title) == IPP_OK)
+    {
       fputs("DEBUG: Got device list!\n", stderr);
+
+      if (cgiSupportsMultipart())
+        cgiStartMultipart();
+
+      cgiSetVariable("CUPS_GET_DEVICES_DONE", "1");
+      cgiStartHTML(title);
+      cgiCopyTemplateLang("choose-device.tmpl");
+      cgiEndHTML();
+
+      if (cgiSupportsMultipart())
+        cgiEndMultipart();
+    }
     else
     {
       fprintf(stderr,
@@ -941,16 +1041,6 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
         return;
       }
     }
-
-   /*
-    * Show the final selection page...
-    */
-
-    cgiSetVariable("CUPS_GET_DEVICES_DONE", "1");
-    cgiStartHTML(title);
-    cgiCopyTemplateLang("choose-device.tmpl");
-    cgiEndHTML();
-    cgiEndMultipart();
   }
   else if (strchr(var, '/') == NULL)
   {
@@ -1016,6 +1106,11 @@ do_am_printer(http_t *http,              /* I - HTTP connection */
         if ((attr = ippFindAttribute(oldinfo, "printer-location",
                                     IPP_TAG_TEXT)) != NULL)
           cgiSetVariable("PRINTER_LOCATION", attr->values[0].string.text);
+
+       if ((attr = ippFindAttribute(oldinfo, "printer-is-shared",
+                                    IPP_TAG_BOOLEAN)) != NULL)
+         cgiSetVariable("PRINTER_IS_SHARED",
+                        attr->values[0].boolean ? "1" : "0");
       }
 
       cgiCopyTemplateLang("modify-printer.tmpl");
@@ -1043,9 +1138,10 @@ do_am_printer(http_t *http,              /* I - HTTP connection */
 
     return;
   }
-  else if (!file && !cgiGetVariable("PPD_NAME"))
+  else if (!file &&
+           (!cgiGetVariable("PPD_NAME") || cgiGetVariable("SELECT_MAKE")))
   {
-    if (modify)
+    if (modify && !cgiGetVariable("SELECT_MAKE"))
     {
      /*
       * Get the PPD file...
@@ -1069,6 +1165,8 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
 
       if (get_status != HTTP_OK)
       {
+        httpFlush(http);
+
         fprintf(stderr, "ERROR: Unable to get PPD file %s: %d - %s\n",
                uri, get_status, httpStatus(get_status));
       }
@@ -1122,7 +1220,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
 
     if ((var = cgiGetVariable("CURRENT_MAKE")) == NULL)
       var = cgiGetVariable("PPD_MAKE");
-    if (var)
+    if (var && !cgiGetVariable("SELECT_MAKE"))
     {
       const char *make_model;          /* Make and model */
 
@@ -1130,8 +1228,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
       ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
                    "ppd-make", NULL, var);
 
-      if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL &&
-          !cgiGetVariable("SELECT_MAKE"))
+      if ((make_model = cgiGetVariable("CURRENT_MAKE_AND_MODEL")) != NULL)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
                     "ppd-make-and-model", NULL, make_model);
     }
@@ -1149,7 +1246,7 @@ do_am_printer(http_t *http,               /* I - HTTP connection */
       * Got the list of PPDs, see if the user has selected a make...
       */
 
-      if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0)
+      if (cgiSetIPPVars(response, NULL, NULL, NULL, 0) == 0 && !modify)
       {
        /*
         * No PPD files with this make, try again with all makes...
@@ -1185,8 +1282,11 @@ do_am_printer(http_t *http,              /* I - HTTP connection */
        */
 
         cgiStartHTML(title);
-       cgiSetVariable("CURRENT_MAKE_AND_MODEL",
-                      cgiGetArray("PPD_MAKE_AND_MODEL", 0));
+       if (!cgiGetVariable("PPD_MAKE"))
+         cgiSetVariable("PPD_MAKE", cgiGetVariable("CURRENT_MAKE"));
+       if (!modify)
+         cgiSetVariable("CURRENT_MAKE_AND_MODEL",
+                        cgiGetArray("PPD_MAKE_AND_MODEL", 0));
        cgiCopyTemplateLang("choose-model.tmpl");
         cgiEndHTML();
       }
@@ -1360,7 +1460,7 @@ do_cancel_subscription(http_t *http)/* I - HTTP connection */
 
   if (id <= 0)
   {
-    cgiSetVariable("ERROR", cgiText(_("Bad subscription ID!")));
+    cgiSetVariable("ERROR", cgiText(_("Bad subscription ID")));
     cgiStartHTML(_("Cancel RSS Subscription"));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -1443,14 +1543,18 @@ do_config_server(http_t *http)          /* I - HTTP connection */
                        *share_printers,/* SHARE_PRINTERS value */
                        *user_cancel_any,
                                        /* USER_CANCEL_ANY value */
-                       *browse_web_if, /* BrowseWebIF value */
-                       *preserve_job_history,
+                       *browse_web_if = NULL,
+                                       /* BrowseWebIF value */
+                       *preserve_job_history = NULL,
                                        /* PreserveJobHistory value */
-                       *preserve_job_files,
+                       *preserve_job_files = NULL,
                                        /* PreserveJobFiles value */
-                       *max_clients,   /* MaxClients value */
-                       *max_jobs,      /* MaxJobs value */
-                       *max_log_size;  /* MaxLogSize value */
+                       *max_clients = NULL,
+                                       /* MaxClients value */
+                       *max_jobs = NULL,
+                                       /* MaxJobs value */
+                       *max_log_size = NULL;
+                                       /* MaxLogSize value */
     char               local_protocols[255],
                                        /* BrowseLocalProtocols */
                        remote_protocols[255];
@@ -1474,7 +1578,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
 #ifdef HAVE_GSSAPI
     char               default_auth_type[255];
                                        /* DefaultAuthType value */
-    const char         *val;           /* Setting value */ 
+    const char         *val;           /* Setting value */
 #endif /* HAVE_GSSAPI */
 
 
@@ -1546,7 +1650,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
          strcat(local_protocols, "slp");
       }
 #endif /* HAVE_SLP */
-      
+
       if (cgiGetVariable("BROWSE_REMOTE_CUPS"))
        strcpy(remote_protocols, "cups");
       else
@@ -1799,7 +1903,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
-      
+
       perror(tempfile);
       return;
     }
@@ -1811,7 +1915,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
       cgiSetVariable("ERROR", strerror(errno));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
-      
+
       perror(tempfile);
       close(tempfd);
       unlink(tempfile);
@@ -1920,7 +2024,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
                      cgiText(_("Unable to access cupsd.conf file:")));
       cgiSetVariable("ERROR",
                      cgiText(_("Unable to edit cupsd.conf files larger than "
-                              "1MB!")));
+                              "1MB")));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
 
@@ -2051,7 +2155,7 @@ do_delete_class(http_t *http)             /* I - HTTP connection */
   else
   {
     cgiStartHTML(cgiText(_("Delete Class")));
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
     return;
@@ -2136,7 +2240,7 @@ do_delete_printer(http_t *http)           /* I - HTTP connection */
   else
   {
     cgiStartHTML(cgiText(_("Delete Printer")));
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
     return;
@@ -2311,11 +2415,11 @@ do_export(http_t *http)                 /* I - HTTP connection */
   else if (username && !*username)
     cgiSetVariable("ERROR",
                    cgiText(_("A Samba username is required to export "
-                            "printer drivers!")));
+                            "printer drivers")));
   else if (username && (!password || !*password))
     cgiSetVariable("ERROR",
                    cgiText(_("A Samba password is required to export "
-                            "printer drivers!")));
+                            "printer drivers")));
 
  /*
   * Show form...
@@ -2587,7 +2691,9 @@ do_menu(http_t *http)                     /* I - HTTP connection */
   if ((val = cupsGetOption("DefaultAuthType", num_settings,
                            settings)) != NULL && !strcasecmp(val, "Negotiate"))
     cgiSetVariable("KERBEROS", "CHECKED");
+  else
 #endif /* HAVE_GSSAPI */
+  cgiSetVariable("KERBEROS", "");
 
 #ifdef HAVE_DNSSD
   cgiSetVariable("HAVE_DNSSD", "1");
@@ -2772,7 +2878,7 @@ do_set_allowed_users(http_t *http)        /* I - HTTP connection */
 
   if (!printer)
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(cgiText(_("Set Allowed Users")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3026,7 +3132,7 @@ do_set_default(http_t *http)              /* I - HTTP connection */
 
   if (!printer)
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(title);
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3137,7 +3243,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
                     printer);
   else
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(title);
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3199,11 +3305,16 @@ do_set_options(http_t *http,            /* I - HTTP connection */
     for (option = ppdFirstOption(ppd);
          option;
         option = ppdNextOption(ppd))
+    {
       if ((var = cgiGetVariable(option->keyword)) != NULL)
       {
        have_options = 1;
        ppdMarkOption(ppd, option->keyword, var);
+       fprintf(stderr, "DEBUG: Set %s to %s...\n", option->keyword, var);
       }
+      else
+        fprintf(stderr, "DEBUG: Didn't find %s...\n", option->keyword);
+    }
   }
 
   if (!have_options || ppdConflicts(ppd))
@@ -3224,7 +3335,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
           ((ppdattr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL &&
            ppdattr->value && strstr(ppdattr->value, "AutoConfigure")))
         cgiSetVariable("HAVE_AUTOCONFIGURE", "YES");
-      else 
+      else
       {
         for (i = 0; i < ppd->num_filters; i ++)
          if (!strncmp(ppd->filters[i], "application/vnd.cups-postscript", 31))
@@ -3310,6 +3421,16 @@ do_set_options(http_t *http,             /* I - HTTP connection */
            {
              cgiSetArray("ckeyword", k, option->keyword);
              cgiSetArray("ckeytext", k, option->text);
+
+             for (m = 0; m < option->num_choices; m ++)
+             {
+               if (option->choices[m].marked)
+               {
+                 cgiSetArray("cchoice", k, option->choices[m].text);
+                 break;
+               }
+              }
+
              k ++;
            }
 
@@ -3328,7 +3449,7 @@ do_set_options(http_t *http,              /* I - HTTP connection */
          cgiSetVariable("GROUP", group->text);
 
        cgiCopyTemplateLang("option-header.tmpl");
-       
+
        for (j = group->num_options, option = group->options;
             j > 0;
             j --, option ++)
@@ -3815,7 +3936,7 @@ do_set_sharing(http_t *http)              /* I - HTTP connection */
 
   if (!printer || !shared)
   {
-    cgiSetVariable("ERROR", cgiText(_("Missing form variable!")));
+    cgiSetVariable("ERROR", cgiText(_("Missing form variable")));
     cgiStartHTML(cgiText(_("Set Publishing")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
@@ -3972,7 +4093,7 @@ get_option_value(
 
     snprintf(buffer, bufsize, "Custom.%gx%g%s", width, length, uval);
   }
-  else if (cupsArrayCount(coption->params) == 1) 
+  else if (cupsArrayCount(coption->params) == 1)
   {
     cparam = ppdFirstCustomParam(coption);
     snprintf(keyword, sizeof(keyword), "%s.%s", coption->keyword, cparam->name);