]> git.ipfire.org Git - thirdparty/cups.git/blobdiff - test/ippserver.c
Remove all of the Subversion keywords from various source files.
[thirdparty/cups.git] / test / ippserver.c
index 99bc4707d6a34b41782bb85e94d378125183b357..8f58c9a712b3d5421ae7b4e42428c4fa4b1c067b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * "$Id$"
- *
  * Sample IPP Everywhere server for CUPS.
  *
  * Copyright 2010-2015 by Apple Inc.
@@ -108,6 +106,26 @@ enum _ipp_preason_e                        /* printer-state-reasons bit values */
   _IPP_PREASON_TONER_LOW = 0x8000      /* toner-low */
 };
 typedef unsigned int _ipp_preason_t;   /* Bitfield for printer-state-reasons */
+static const char * const _ipp_preason_strings[] =
+{                                      /* Strings for each bit */
+  /* "none" is implied for no bits set */
+  "other",
+  "cover-open",
+  "input-tray-missing",
+  "marker-supply-empty",
+  "marker-supply-low",
+  "marker-waste-almost-full",
+  "marker-waste-full",
+  "media-empty",
+  "media-jam",
+  "media-low",
+  "media-needed",
+  "moving-to-paused",
+  "paused",
+  "spool-area-full",
+  "toner-empty",
+  "toner-low"
+};
 
 typedef enum _ipp_media_class_e
 {
@@ -231,6 +249,16 @@ static const char * const printer_supplies[] =
   "Toner Waste"
 };
 
+/*
+ * URL scheme for web resources...
+ */
+
+#ifdef HAVE_SSL
+#  define WEB_SCHEME "https"
+#else
+#  define WEB_SCHEME "http"
+#endif /* HAVE_SSL */
+
 
 /*
  * Structures...
@@ -399,10 +427,12 @@ static void               ipp_send_uri(_ipp_client_t *client);
 static void            ipp_validate_job(_ipp_client_t *client);
 static void            load_attributes(const char *filename, ipp_t *attrs);
 static int             parse_options(_ipp_client_t *client, cups_option_t **options);
+static void            process_attr_message(_ipp_job_t *job, char *message);
 static void            *process_client(_ipp_client_t *client);
 static int             process_http(_ipp_client_t *client);
 static int             process_ipp(_ipp_client_t *client);
 static void            *process_job(_ipp_job_t *job);
+static void            process_state_message(_ipp_job_t *job, char *message);
 static int             register_printer(_ipp_printer_t *printer, const char *location, const char *make, const char *model, const char *formats, const char *adminurl, const char *uuid, int color, int duplex, const char *regtype);
 static int             respond_http(_ipp_client_t *client, http_status_t code,
                                     const char *content_coding,
@@ -648,7 +678,7 @@ main(int  argc,                             /* I - Number of command-line args */
 #ifdef WIN32
     if ((tmpdir = getenv("TEMP")) == NULL)
       tmpdir = "C:/TEMP";
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) && !TARGET_OS_IOS
     if ((tmpdir = getenv("TMPDIR")) == NULL)
       tmpdir = "/private/tmp";
 #else
@@ -1054,7 +1084,10 @@ create_job(_ipp_client_t *client)        /* I - Client */
   ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "job-id", job->id);
   ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uri", NULL, uri);
   ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL, uuid);
-  ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, client->printer->uri);
+  if ((attr = ippFindAttribute(client->request, "printer-uri", IPP_TAG_URI)) != NULL)
+    ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, ippGetString(attr, 0, NULL));
+  else
+    ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-printer-uri", NULL, client->printer->uri);
   ippAddInteger(job->attrs, IPP_TAG_JOB, IPP_TAG_INTEGER, "time-at-creation", (int)(job->created - client->printer->start_time));
 
   cupsArrayAdd(client->printer->jobs, job);
@@ -1555,12 +1588,6 @@ create_printer(const char *servername,   /* I - Server hostname (NULL for default)
   * Prepare values for the printer attributes...
   */
 
-#ifdef HAVE_SSL
-#  define WEB_SCHEME "https"
-#else
-#  define WEB_SCHEME "http"
-#endif /* HAVE_SSL */
-
   httpAssembleURI(HTTP_URI_CODING_ALL, icons, sizeof(icons), WEB_SCHEME, NULL, printer->hostname, printer->port, "/icon.png");
   httpAssembleURI(HTTP_URI_CODING_ALL, adminurl, sizeof(adminurl), WEB_SCHEME, NULL, printer->hostname, printer->port, "/");
   httpAssembleURI(HTTP_URI_CODING_ALL, supplyurl, sizeof(supplyurl), WEB_SCHEME, NULL, printer->hostname, printer->port, "/supplies");
@@ -1744,9 +1771,6 @@ create_printer(const char *servername,    /* I - Server hostname (NULL for default)
   if (!ippFindAttribute(printer->attrs, "job-password-supported", IPP_TAG_ZERO))
     ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-password-supported", 4);
 
-  /* job-preferred-attributes-supported */
-  ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-preferred-attributes-supported", 0);
-
   /* job-priority-default */
   if (!ippFindAttribute(printer->attrs, "job-priority-default", IPP_TAG_ZERO))
     ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-default", 50);
@@ -1954,6 +1978,9 @@ create_printer(const char *servername,    /* I - Server hostname (NULL for default)
   if (!ippFindAttribute(printer->attrs, "pdl-override-supported", IPP_TAG_ZERO))
     ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "pdl-override-supported", NULL, "attempted");
 
+  /* preferred-attributes-supported */
+  ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "preferred-attributes-supported", 0);
+
   /* print-color-mode-default */
   if (!ippFindAttribute(printer->attrs, "print-color-mode-default", IPP_TAG_ZERO))
     ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_CONST_TAG(IPP_TAG_KEYWORD), "print-color-mode-default", NULL, "auto");
@@ -3646,45 +3673,22 @@ ipp_get_printer_attributes(
                    "printer-state-reasons", NULL, "none");
     else
     {
-      int                      num_reasons = 0;/* Number of reasons */
-      const char               *reasons[32];   /* Reason strings */
-
-      if (printer->state_reasons & _IPP_PREASON_OTHER)
-       reasons[num_reasons ++] = "other";
-      if (printer->state_reasons & _IPP_PREASON_COVER_OPEN)
-       reasons[num_reasons ++] = "cover-open";
-      if (printer->state_reasons & _IPP_PREASON_INPUT_TRAY_MISSING)
-       reasons[num_reasons ++] = "input-tray-missing";
-      if (printer->state_reasons & _IPP_PREASON_MARKER_SUPPLY_EMPTY)
-       reasons[num_reasons ++] = "marker-supply-empty-warning";
-      if (printer->state_reasons & _IPP_PREASON_MARKER_SUPPLY_LOW)
-       reasons[num_reasons ++] = "marker-supply-low-report";
-      if (printer->state_reasons & _IPP_PREASON_MARKER_WASTE_ALMOST_FULL)
-       reasons[num_reasons ++] = "marker-waste-almost-full-report";
-      if (printer->state_reasons & _IPP_PREASON_MARKER_WASTE_FULL)
-       reasons[num_reasons ++] = "marker-waste-full-warning";
-      if (printer->state_reasons & _IPP_PREASON_MEDIA_EMPTY)
-       reasons[num_reasons ++] = "media-empty-warning";
-      if (printer->state_reasons & _IPP_PREASON_MEDIA_JAM)
-       reasons[num_reasons ++] = "media-jam-warning";
-      if (printer->state_reasons & _IPP_PREASON_MEDIA_LOW)
-       reasons[num_reasons ++] = "media-low-report";
-      if (printer->state_reasons & _IPP_PREASON_MEDIA_NEEDED)
-       reasons[num_reasons ++] = "media-needed-report";
-      if (printer->state_reasons & _IPP_PREASON_MOVING_TO_PAUSED)
-       reasons[num_reasons ++] = "moving-to-paused";
-      if (printer->state_reasons & _IPP_PREASON_PAUSED)
-       reasons[num_reasons ++] = "paused";
-      if (printer->state_reasons & _IPP_PREASON_SPOOL_AREA_FULL)
-       reasons[num_reasons ++] = "spool-area-full";
-      if (printer->state_reasons & _IPP_PREASON_TONER_EMPTY)
-       reasons[num_reasons ++] = "toner-empty-warning";
-      if (printer->state_reasons & _IPP_PREASON_TONER_LOW)
-       reasons[num_reasons ++] = "toner-low-report";
-
-      ippAddStrings(client->response, IPP_TAG_PRINTER,
-                    IPP_CONST_TAG(IPP_TAG_KEYWORD),
-                    "printer-state-reasons", num_reasons, NULL, reasons);
+      ipp_attribute_t  *attr = NULL;           /* printer-state-reasons */
+      _ipp_preason_t   bit;                    /* Reason bit */
+      int              i;                      /* Looping var */
+      char             reason[32];             /* Reason string */
+
+      for (i = 0, bit = 1; i < (int)(sizeof(_ipp_preason_strings) / sizeof(_ipp_preason_strings[0])); i ++, bit *= 2)
+      {
+        if (printer->state_reasons & bit)
+       {
+         snprintf(reason, sizeof(reason), "%s-%s", _ipp_preason_strings[i], printer->state == IPP_PSTATE_IDLE ? "report" : printer->state == IPP_PSTATE_PROCESSING ? "warning" : "error");
+         if (attr)
+           ippSetString(client->response, &attr, ippGetCount(attr), reason);
+         else
+           attr = ippAddString(client->response, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "printer-state-reasons", NULL, reason);
+       }
+      }
     }
   }
 
@@ -3727,7 +3731,21 @@ static void
 ipp_identify_printer(
     _ipp_client_t *client)             /* I - Client */
 {
-  /* TODO: Do something */
+  ipp_attribute_t      *actions,       /* identify-actions */
+                       *message;       /* message */
+
+
+  actions = ippFindAttribute(client->request, "identify-actions", IPP_TAG_KEYWORD);
+  message = ippFindAttribute(client->request, "message", IPP_TAG_TEXT);
+
+  if (!actions || ippContainsString(actions, "sound"))
+  {
+    putchar(0x07);
+    fflush(stdout);
+  }
+
+  if (ippContainsString(actions, "display"))
+    printf("IDENTIFY from %s: %s\n", client->hostname, message ? ippGetString(message, 0, NULL) : "No message supplied");
 
   respond_ipp(client, IPP_STATUS_OK, NULL);
 }
@@ -5098,6 +5116,20 @@ parse_options(_ipp_client_t *client,     /* I - Client */
 }
 
 
+/*
+ * 'process_attr_message()' - Process an ATTR: message from a command.
+ */
+
+static void
+process_attr_message(
+    _ipp_job_t *job,                   /* I - Job */
+    char       *message)               /* I - Message */
+{
+  (void)job;
+  (void)message;
+}
+
+
 /*
  * 'process_client()' - Process client requests on a thread.
  */
@@ -6024,6 +6056,13 @@ process_job(_ipp_job_t *job)             /* I - Job */
     ipp_attribute_t *attr;             /* Job attribute */
     char       val[1280],              /* IPP_NAME=value */
                *valptr;                /* Pointer into string */
+#ifndef WIN32
+    int                mypipe[2];              /* Pipe for stderr */
+    char       line[2048],             /* Line from stderr */
+               *ptr,                   /* Pointer into line */
+               *endptr;                /* End of line */
+    ssize_t    bytes;                  /* Bytes read */
+#endif /* !WIN32 */
 
     fprintf(stderr, "Running command \"%s %s\".\n", job->printer->command,
             job->filename);
@@ -6083,13 +6122,25 @@ process_job(_ipp_job_t *job)            /* I - Job */
 
 #ifdef WIN32
     status = _spawnvpe(_P_WAIT, job->printer->command, myargv, myenvp);
+
 #else
+    if (pipe(mypipe))
+    {
+      perror("Unable to create pipe for stderr");
+      mypipe[0] = mypipe[1] = -1;
+    }
+
     if ((pid = fork()) == 0)
     {
      /*
       * Child comes here...
       */
 
+      close(2);
+      dup2(mypipe[1], 2);
+      close(mypipe[0]);
+      close(mypipe[1]);
+
       execve(job->printer->command, myargv, myenvp);
       exit(errno);
     }
@@ -6102,6 +6153,9 @@ process_job(_ipp_job_t *job)              /* I - Job */
       perror("Unable to start job processing command");
       status = -1;
 
+      close(mypipe[0]);
+      close(mypipe[1]);
+
      /*
       * Free memory used for environment...
       */
@@ -6117,6 +6171,55 @@ process_job(_ipp_job_t *job)             /* I - Job */
 
       while (myenvc > 0)
        free(myenvp[-- myenvc]);
+
+     /*
+      * If the pipe exists, read from it until EOF...
+      */
+
+      if (mypipe[0] >= 0)
+      {
+       close(mypipe[1]);
+
+       endptr = line;
+       while ((bytes = read(mypipe[0], endptr, sizeof(line) - (size_t)(endptr - line) - 1)) > 0)
+       {
+         endptr += bytes;
+         *endptr = '\0';
+
+          while ((ptr = strchr(line, '\n')) != NULL)
+         {
+           *ptr++ = '\0';
+
+           if (!strncmp(line, "STATE:", 6))
+           {
+            /*
+             * Process printer-state-reasons keywords.
+             */
+
+             process_state_message(job, line);
+           }
+           else if (!strncmp(line, "ATTR:", 5))
+           {
+            /*
+             * Process printer attribute update.
+             */
+
+             process_attr_message(job, line);
+           }
+           else if (Verbosity > 1)
+             fprintf(stderr, "%s: %s\n", job->printer->command, line);
+
+           bytes = ptr - line;
+            if (ptr < endptr)
+             memmove(line, ptr, (size_t)(endptr - ptr));
+           endptr -= bytes;
+           *endptr = '\0';
+         }
+       }
+
+       close(mypipe[0]);
+      }
+
      /*
       * Wait for child to complete...
       */
@@ -6179,6 +6282,95 @@ process_job(_ipp_job_t *job)             /* I - Job */
 }
 
 
+/*
+ * 'process_state_message()' - Process a STATE: message from a command.
+ */
+
+static void
+process_state_message(
+    _ipp_job_t *job,                   /* I - Job */
+    char       *message)               /* I - Message */
+{
+  int          i;                      /* Looping var */
+  _ipp_preason_t state_reasons,                /* printer-state-reasons values */
+               bit;                    /* Current reason bit */
+  char         *ptr,                   /* Pointer into message */
+               *next;                  /* Next keyword in message */
+  int          remove;                 /* Non-zero if we are removing keywords */
+
+
+ /*
+  * Skip leading "STATE:" and any whitespace...
+  */
+
+  for (message += 6; *message; message ++)
+    if (*message != ' ' && *message != '\t')
+      break;
+
+ /*
+  * Support the following forms of message:
+  *
+  * "keyword[,keyword,...]" to set the printer-state-reasons value(s).
+  *
+  * "-keyword[,keyword,...]" to remove keywords.
+  *
+  * "+keyword[,keyword,...]" to add keywords.
+  *
+  * Keywords may or may not have a suffix (-report, -warning, -error) per
+  * RFC 2911.
+  */
+
+  if (*message == '-')
+  {
+    remove        = 1;
+    state_reasons = job->printer->state_reasons;
+    message ++;
+  }
+  else if (*message == '+')
+  {
+    remove        = 0;
+    state_reasons = job->printer->state_reasons;
+    message ++;
+  }
+  else
+  {
+    remove        = 0;
+    state_reasons = _IPP_PREASON_NONE;
+  }
+
+  while (*message)
+  {
+    if ((next = strchr(message, ',')) != NULL)
+      *next++ = '\0';
+
+    if ((ptr = strstr(message, "-error")) != NULL)
+      *ptr = '\0';
+    else if ((ptr = strstr(message, "-report")) != NULL)
+      *ptr = '\0';
+    else if ((ptr = strstr(message, "-warning")) != NULL)
+      *ptr = '\0';
+
+    for (i = 0, bit = 1; i < (int)(sizeof(_ipp_preason_strings) / sizeof(_ipp_preason_strings[0])); i ++, bit *= 2)
+    {
+      if (!strcmp(message, _ipp_preason_strings[i]))
+      {
+        if (remove)
+         state_reasons &= ~bit;
+       else
+         state_reasons |= bit;
+      }
+    }
+
+    if (next)
+      message = next;
+    else
+      break;
+  }
+
+  job->printer->state_reasons = state_reasons;
+}
+
+
 /*
  * 'register_printer()' - Register a printer object via Bonjour.
  */
@@ -6887,6 +7079,7 @@ valid_job_attributes(
     _ipp_client_t *client)             /* I - Client */
 {
   int                  i,              /* Looping var */
+                       count,          /* Number of values */
                        valid = 1;      /* Valid attributes? */
   ipp_attribute_t      *attr,          /* Current attribute */
                        *supported;     /* xxx-supported attribute */
@@ -6993,13 +7186,9 @@ valid_job_attributes(
     }
     else
     {
-      for (i = 0;
-           i < (int)(sizeof(media_supported) / sizeof(media_supported[0]));
-          i ++)
-        if (!strcmp(ippGetString(attr, 0, NULL), media_supported[i]))
-         break;
+      supported = ippFindAttribute(client->printer->attrs, "media-supported", IPP_TAG_KEYWORD);
 
-      if (i >= (int)(sizeof(media_supported) / sizeof(media_supported[0])))
+      if (!ippContainsString(supported, ippGetString(attr, 0, NULL)))
       {
        respond_unsupported(client, attr);
        valid = 0;
@@ -7009,13 +7198,86 @@ valid_job_attributes(
 
   if ((attr = ippFindAttribute(client->request, "media-col", IPP_TAG_ZERO)) != NULL)
   {
+    ipp_t              *col,           /* media-col collection */
+                       *size;          /* media-size collection */
+    ipp_attribute_t    *member,        /* Member attribute */
+                       *x_dim,         /* x-dimension */
+                       *y_dim;         /* y-dimension */
+    int                        x_value,        /* y-dimension value */
+                       y_value;        /* x-dimension value */
+
     if (ippGetCount(attr) != 1 ||
         ippGetValueTag(attr) != IPP_TAG_BEGIN_COLLECTION)
     {
       respond_unsupported(client, attr);
       valid = 0;
     }
-    /* TODO: check for valid media-col */
+
+    col = ippGetCollection(attr, 0);
+
+    if ((member = ippFindAttribute(col, "media-size-name", IPP_TAG_ZERO)) != NULL)
+    {
+      if (ippGetCount(member) != 1 ||
+         (ippGetValueTag(member) != IPP_TAG_NAME &&
+          ippGetValueTag(member) != IPP_TAG_NAMELANG &&
+          ippGetValueTag(member) != IPP_TAG_KEYWORD))
+      {
+       respond_unsupported(client, attr);
+       valid = 0;
+      }
+      else
+      {
+       supported = ippFindAttribute(client->printer->attrs, "media-supported", IPP_TAG_KEYWORD);
+
+       if (!ippContainsString(supported, ippGetString(member, 0, NULL)))
+       {
+         respond_unsupported(client, attr);
+         valid = 0;
+       }
+      }
+    }
+    else if ((member = ippFindAttribute(col, "media-size", IPP_TAG_BEGIN_COLLECTION)) != NULL)
+    {
+      if (ippGetCount(member) != 1)
+      {
+       respond_unsupported(client, attr);
+       valid = 0;
+      }
+      else
+      {
+       size = ippGetCollection(member, 0);
+
+       if ((x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(x_dim) != 1 ||
+           (y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_INTEGER)) == NULL || ippGetCount(y_dim) != 1)
+       {
+         respond_unsupported(client, attr);
+         valid = 0;
+       }
+       else
+       {
+         x_value   = ippGetInteger(x_dim, 0);
+         y_value   = ippGetInteger(y_dim, 0);
+         supported = ippFindAttribute(client->printer->attrs, "media-size-supported", IPP_TAG_BEGIN_COLLECTION);
+         count     = ippGetCount(supported);
+
+         for (i = 0; i < count ; i ++)
+         {
+           size  = ippGetCollection(supported, i);
+           x_dim = ippFindAttribute(size, "x-dimension", IPP_TAG_ZERO);
+           y_dim = ippFindAttribute(size, "y-dimension", IPP_TAG_ZERO);
+
+           if (ippContainsInteger(x_dim, x_value) && ippContainsInteger(y_dim, y_value))
+             break;
+         }
+
+         if (i >= count)
+         {
+           respond_unsupported(client, attr);
+           valid = 0;
+         }
+       }
+      }
+    }
   }
 
   if ((attr = ippFindAttribute(client->request, "multiple-document-handling", IPP_TAG_ZERO)) != NULL)
@@ -7074,8 +7336,7 @@ valid_job_attributes(
     }
     else
     {
-      int      count,                  /* Number of supported values */
-               xdpi,                   /* Horizontal resolution for job template attribute */
+      int      xdpi,                   /* Horizontal resolution for job template attribute */
                ydpi,                   /* Vertical resolution for job template attribute */
                sydpi;                  /* Vertical resolution for supported value */
       ipp_res_t        units,                  /* Units for job template attribute */
@@ -7125,8 +7386,3 @@ valid_job_attributes(
 
   return (valid);
 }
-
-
-/*
- * End of "$Id$".
- */