Beispiel #1
0
static void 
_get_send (GtkCupsRequest *request)
{
  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  request->poll_state = GTK_CUPS_HTTP_WRITE;

  if (request->data_io == NULL)
    {
      gtk_cups_result_set_error (request->result,
                                 GTK_CUPS_ERROR_IO,
                                 G_IO_STATUS_ERROR,
                                 G_IO_CHANNEL_ERROR_FAILED, 
                                 "Get requires an open io channel");

      request->state = GTK_CUPS_GET_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;

      return;
    }

  httpClearFields (request->http);
#ifdef HAVE_HTTPGETAUTHSTRING
  httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
#else
#ifdef HAVE_HTTP_AUTHSTRING
  httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
#endif
#endif

  if (httpGet (request->http, request->resource))
    {
      if (httpReconnect (request->http))
        {
          request->state = GTK_CUPS_GET_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;
	 
          /* TODO: should add a status or error code for failed GET */ 
          gtk_cups_result_set_error (request->result, 
                                     GTK_CUPS_ERROR_GENERAL,
                                     0,
                                     0,
                                     "Failed Get");
        }

      request->attempts++;
      return;    
    }

  if (httpCheck (request->http))
    request->last_status = httpUpdate (request->http);
        
  request->attempts = 0;

  request->state = GTK_CUPS_GET_CHECK;
  request->poll_state = GTK_CUPS_HTTP_READ;
  
  ippSetState (request->ipp_request, IPP_IDLE);
}
Beispiel #2
0
gboolean 
gtk_cups_request_read_write (GtkCupsRequest *request)
{
  if (request->type == GTK_CUPS_POST)
    post_states[request->state] (request);
  else if (request->type == GTK_CUPS_GET)
    get_states[request->state] (request);

  if (request->attempts > _GTK_CUPS_MAX_ATTEMPTS && 
      request->state != GTK_CUPS_REQUEST_DONE)
    {
      /* TODO: should add a status or error code for too many failed attempts */
      gtk_cups_result_set_error (request->result, 
                                 GTK_CUPS_ERROR_GENERAL,
                                 0,
                                 0, 
                                 "Too many failed attempts");

      request->state = GTK_CUPS_REQUEST_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
    }
    
  if (request->state == GTK_CUPS_REQUEST_DONE)
    {
      request->poll_state = GTK_CUPS_HTTP_IDLE;
      return TRUE;
    }
  else
    return FALSE;
}
Beispiel #3
0
static void 
_get_read_data (GtkCupsRequest *request)
{
  char buffer[_GTK_CUPS_MAX_CHUNK_SIZE];
  gsize bytes;
  gsize bytes_written;
  GIOStatus io_status;
  GError *error;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  error = NULL;

  request->poll_state = GTK_CUPS_HTTP_READ;

#if HAVE_CUPS_API_1_2
  bytes = httpRead2 (request->http, buffer, sizeof (buffer));
#else
  bytes = httpRead (request->http, buffer, sizeof (buffer));
#endif /* HAVE_CUPS_API_1_2 */
  request->bytes_received += bytes;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %" G_GSIZE_FORMAT " bytes read\n", bytes));
  
  io_status =
    g_io_channel_write_chars (request->data_io, 
                              buffer, 
			      bytes, 
			      &bytes_written,
			      &error);

  if (io_status == G_IO_STATUS_ERROR)
    {
      request->state = GTK_CUPS_GET_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
    
      gtk_cups_result_set_error (request->result,
                                 GTK_CUPS_ERROR_IO,
                                 io_status,
                                 error->code, 
                                 error->message);
      g_error_free (error);
    }

  /* Stop if we do not expect any more data or EOF was received. */
#if HAVE_CUPS_API_1_2
  if (httpGetLength2 (request->http) <= request->bytes_received || bytes == 0)
#else
  if (httpGetLength (request->http) <= request->bytes_received || bytes == 0)
#endif /* HAVE_CUPS_API_1_2 */
    {
      request->state = GTK_CUPS_GET_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;

      return;
    }
}
Beispiel #4
0
static void 
_post_send (GtkCupsRequest *request)
{
  gchar length[255];
  struct stat data_info;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  request->poll_state = GTK_CUPS_HTTP_WRITE;

  if (request->data_io != NULL)
    {
      fstat (g_io_channel_unix_get_fd (request->data_io), &data_info);
      sprintf (length, "%lu", (unsigned long) (ippLength (request->ipp_request) + data_info.st_size));
    }
  else
    sprintf (length, "%lu", (unsigned long) ippLength (request->ipp_request));
	
  httpClearFields (request->http);
  httpSetField (request->http, HTTP_FIELD_CONTENT_LENGTH, length);
  httpSetField (request->http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
#ifdef HAVE_HTTPGETAUTHSTRING
  httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString (request->http));
#else
#ifdef HAVE_HTTP_AUTHSTRING
  httpSetField (request->http, HTTP_FIELD_AUTHORIZATION, request->http->authstring);
#endif
#endif

  if (httpPost (request->http, request->resource))
    {
      if (httpReconnect (request->http))
        {
          request->state = GTK_CUPS_POST_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;

          /* TODO: should add a status or error code for failed post */
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_GENERAL,
                                     0,
                                     0,
                                     "Failed Post");
        }

      request->attempts++;
      return;    
    }
        
    request->attempts = 0;

    request->state = GTK_CUPS_POST_WRITE_REQUEST;
    ippSetState (request->ipp_request, IPP_IDLE);
}
Beispiel #5
0
static void 
_get_read_data (GtkCupsRequest *request)
{
  char buffer[_GTK_CUPS_MAX_CHUNK_SIZE];
  gsize bytes;
  gsize bytes_written;
  GIOStatus io_status;
  GError *error;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  error = NULL;

  request->poll_state = GTK_CUPS_HTTP_READ;

#if HAVE_CUPS_API_1_2
  bytes = httpRead2 (request->http, buffer, sizeof (buffer));
#else
  bytes = httpRead (request->http, buffer, sizeof (buffer));
#endif /* HAVE_CUPS_API_1_2 */

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %i bytes read\n", bytes));
  
  if (bytes == 0)
    {
      request->state = GTK_CUPS_GET_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;

      return;
    }
  
  io_status =
    g_io_channel_write_chars (request->data_io, 
                              buffer, 
			      bytes, 
			      &bytes_written,
			      &error);

  if (io_status == G_IO_STATUS_ERROR)
    {
      request->state = GTK_CUPS_GET_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
    
      gtk_cups_result_set_error (request->result,
                                 GTK_CUPS_ERROR_IO,
                                 io_status,
                                 error->code, 
                                 error->message);
      g_error_free (error);
    }
}
Beispiel #6
0
gboolean 
gtk_cups_request_read_write (GtkCupsRequest *request, gboolean connect_only)
{
  if (connect_only && request->state != GTK_CUPS_REQUEST_START)
    return FALSE;

  do
    {
      if (request->type == GTK_CUPS_POST)
        post_states[request->state] (request);
      else if (request->type == GTK_CUPS_GET)
        get_states[request->state] (request);

      if (gtk_cups_result_is_error (request->result))
        request->state = GTK_CUPS_REQUEST_DONE;

      if (request->attempts > _GTK_CUPS_MAX_ATTEMPTS &&
          request->state != GTK_CUPS_REQUEST_DONE)
        {
          /* TODO: should add a status or error code for too many failed attempts */
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_GENERAL,
                                     0,
                                     0,
                                     "Too many failed attempts");

          request->state = GTK_CUPS_REQUEST_DONE;
        }

      if (request->state == GTK_CUPS_REQUEST_DONE)
        {
          request->poll_state = GTK_CUPS_HTTP_IDLE;
          return TRUE;
        }
    }
  /* We need to recheck using httpCheck if the poll_state is read, because
   * Cups has an internal read buffer. And if this buffer is filled, we may
   * never get a poll event again. */
  while (request->poll_state == GTK_CUPS_HTTP_READ && request->http && httpCheck(request->http));

  return FALSE;
}
Beispiel #7
0
static void
_get_auth (GtkCupsRequest *request)
{
  if (request->password_state == GTK_CUPS_PASSWORD_HAS)
    {
      if (request->password == NULL)
        {
          request->state = GTK_CUPS_GET_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;

          gtk_cups_result_set_error (request->result, 
                                     GTK_CUPS_ERROR_AUTH,
                                     0,
                                     1,
                                     "Canceled by user");
        }
      else
        request->state = GTK_CUPS_GET_CHECK;
    }
}
Beispiel #8
0
static void 
_post_write_request (GtkCupsRequest *request)
{
  ipp_state_t ipp_status;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  request->poll_state = GTK_CUPS_HTTP_WRITE;
  
  ipp_status = ippWrite (request->http, request->ipp_request);

  if (ipp_status == IPP_ERROR)
    {
      int cups_error = cupsLastError ();
      request->state = GTK_CUPS_POST_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
 
      gtk_cups_result_set_error (request->result, 
                                 GTK_CUPS_ERROR_IPP,
                                 ipp_status,
                                 cups_error,
                                 "%s", 
                                 ippErrorString (cups_error));
      return;
    }

  if (ipp_status == IPP_DATA)
    {
      if (request->data_io != NULL)
        request->state = GTK_CUPS_POST_WRITE_DATA;
      else
        {
          request->state = GTK_CUPS_POST_CHECK;
          request->poll_state = GTK_CUPS_HTTP_READ;
	}
    }
}
Beispiel #9
0
static void 
_post_read_response (GtkCupsRequest *request)
{
  ipp_state_t ipp_status;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  request->poll_state = GTK_CUPS_HTTP_READ;

  if (request->result->ipp_response == NULL)
    request->result->ipp_response = ippNew();

  ipp_status = ippRead (request->http, 
                        request->result->ipp_response);

  if (ipp_status == IPP_ERROR)
    {
      int ipp_error = cupsLastError ();
      gtk_cups_result_set_error (request->result,  
                                 GTK_CUPS_ERROR_IPP,
                                 ipp_status,
                                 ipp_error,
                                 "%s",
                                 ippErrorString (ipp_error));
      
      ippDelete (request->result->ipp_response);
      request->result->ipp_response = NULL;

      request->state = GTK_CUPS_POST_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
    }
  else if (ipp_status == IPP_DATA)
    {
      request->state = GTK_CUPS_POST_DONE;
      request->poll_state = GTK_CUPS_HTTP_IDLE;
    }
}
Beispiel #10
0
static void 
_post_check (GtkCupsRequest *request)
{
  http_status_t http_status;

  http_status = request->last_status;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s - status %i\n", G_STRFUNC, http_status));

  request->poll_state = GTK_CUPS_HTTP_READ;

  if (http_status == HTTP_CONTINUE)
    {
      goto again; 
    }
  else if (http_status == HTTP_UNAUTHORIZED)
    {
      int auth_result = -1;
      httpFlush (request->http);

      if (request->password_state == GTK_CUPS_PASSWORD_APPLIED)
        {
          request->poll_state = GTK_CUPS_HTTP_IDLE;
          request->password_state = GTK_CUPS_PASSWORD_NOT_VALID;
          request->state = GTK_CUPS_POST_AUTH;
          request->need_password = TRUE;

          return;
        }

      /* Negotiate */
      if (strncmp (httpGetField (request->http, HTTP_FIELD_WWW_AUTHENTICATE), "Negotiate", 9) == 0)
        {
          auth_result = cupsDoAuthentication (request->http, "POST", request->resource);
        }
      /* Basic, BasicDigest, Digest and PeerCred */
      else
        {
          if (request->password_state == GTK_CUPS_PASSWORD_NONE)
            {
              cups_username = request->username;
              cupsSetPasswordCB (passwordCB);

              /* This call success for PeerCred authentication */
              auth_result = cupsDoAuthentication (request->http, "POST", request->resource);

              if (auth_result != 0)
                {
                  /* move to AUTH state to let the backend 
                   * ask for a password
                   */ 
                  request->poll_state = GTK_CUPS_HTTP_IDLE;
                  request->state = GTK_CUPS_POST_AUTH;
                  request->need_password = TRUE;

                  return;
                }
            }
          else
            {
              cups_password = request->password;
              cups_username = request->username;

              auth_result = cupsDoAuthentication (request->http, "POST", request->resource);

              if (cups_password != NULL)
                return;

              if (request->password != NULL)
                {
                  memset (request->password, 0, strlen (request->password));
                  g_free (request->password);
                  request->password = NULL;
                }

              request->password_state = GTK_CUPS_PASSWORD_APPLIED;
            }
        }

      if (auth_result ||
          httpReconnect (request->http))
        {
          /* if the password has been used, reset password_state
           * so that we ask for a new one next time around
           */ 
          if (cups_password == NULL)
            request->password_state = GTK_CUPS_PASSWORD_NONE;

          request->state = GTK_CUPS_POST_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;
          gtk_cups_result_set_error (request->result, 
                                     GTK_CUPS_ERROR_AUTH,
                                     0,
                                     0,
                                     "Not authorized");
          return;
        }
      
      if (request->data_io != NULL)
        g_io_channel_seek_position (request->data_io, 0, G_SEEK_SET, NULL);

      request->state = GTK_CUPS_POST_CONNECT;
      request->poll_state = GTK_CUPS_HTTP_WRITE;
    }
  else if (http_status == HTTP_ERROR)
    {
      int error = httpError (request->http);
#ifdef G_OS_WIN32
      if (error != WSAENETDOWN && error != WSAENETUNREACH)
#else
      if (error != ENETDOWN && error != ENETUNREACH)	  
#endif /* G_OS_WIN32 */
        {
          request->attempts++;
          goto again;
        }
      else
        {
          request->state = GTK_CUPS_POST_DONE;
          request->poll_state = GTK_CUPS_HTTP_IDLE;
     
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_HTTP,
                                     http_status,
                                     error, 
                                     "Unknown HTTP error");

          return;
        }
    }
  else if (http_status == HTTP_UPGRADE_REQUIRED)
    {
      /* Flush any error message... */
      httpFlush (request->http);

      cupsSetEncryption (HTTP_ENCRYPT_REQUIRED);
      request->state = GTK_CUPS_POST_CONNECT;

      /* Reconnect... */
      httpReconnect (request->http);

      /* Upgrade with encryption... */
      httpEncryption (request->http, HTTP_ENCRYPT_REQUIRED);
 
      request->attempts++;
      goto again;
    }
  else if (http_status != HTTP_OK)
    {
      int http_errno;

      http_errno = httpError (request->http);

      if (http_errno == EPIPE)
        request->state = GTK_CUPS_POST_CONNECT;
      else
        {
          request->state = GTK_CUPS_POST_DONE;
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_HTTP,
                                     http_status,
                                     http_errno, 
                                     "HTTP Error in POST %s", 
                                     g_strerror (http_errno));
          request->poll_state = GTK_CUPS_HTTP_IDLE;
 
          httpFlush (request->http); 
          return;
        }

      request->poll_state = GTK_CUPS_HTTP_IDLE;
      request->last_status = HTTP_CONTINUE;

      httpFlush (request->http);
      if (request->own_http)
        httpClose (request->http);
      request->http = NULL;

      return;
    }
  else
    {
      request->state = GTK_CUPS_POST_READ_RESPONSE;
      return;
    }

 again:
  http_status = HTTP_CONTINUE;

  if (httpCheck (request->http))
    http_status = httpUpdate (request->http);

  request->last_status = http_status;
}
Beispiel #11
0
static void 
_post_write_data (GtkCupsRequest *request)
{
  gsize bytes;
  char buffer[_GTK_CUPS_MAX_CHUNK_SIZE];
  http_status_t http_status;

  GTK_NOTE (PRINTING,
            g_print ("CUPS Backend: %s\n", G_STRFUNC));

  request->poll_state = GTK_CUPS_HTTP_WRITE;
  
  if (httpCheck (request->http))
    http_status = httpUpdate (request->http);
  else
    http_status = request->last_status;

  request->last_status = http_status;


  if (http_status == HTTP_CONTINUE || http_status == HTTP_OK)
    {
      GIOStatus io_status;
      GError *error;

      error = NULL;

      /* send data */
      io_status =
        g_io_channel_read_chars (request->data_io, 
	                         buffer, 
				 _GTK_CUPS_MAX_CHUNK_SIZE,
				 &bytes,
				 &error);

      if (io_status == G_IO_STATUS_ERROR)
        {
          request->state = GTK_CUPS_POST_DONE;
	  request->poll_state = GTK_CUPS_HTTP_IDLE;
     
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_IO,
                                     io_status,
                                     error->code, 
                                     "Error reading from cache file: %s",
                                     error->message);

	  g_error_free (error);
          return;
	}
      else if (bytes == 0 && io_status == G_IO_STATUS_EOF)
        {
          request->state = GTK_CUPS_POST_CHECK;
	  request->poll_state = GTK_CUPS_HTTP_READ;

          request->attempts = 0;
          return;
        }


      if (httpWrite2 (request->http, buffer, bytes) < bytes)
        {
          int http_errno;

          http_errno = httpError (request->http);

          request->state = GTK_CUPS_POST_DONE;
	  request->poll_state = GTK_CUPS_HTTP_IDLE;
     
          gtk_cups_result_set_error (request->result,
                                     GTK_CUPS_ERROR_HTTP,
                                     http_status,
                                     http_errno, 
                                     "Error writing to socket in Post %s", 
                                     g_strerror (http_errno));
          return;
        }
    }
  else if (http_status == HTTP_UNAUTHORIZED)
    {
      request->state = GTK_CUPS_POST_CHECK;
      request->poll_state = GTK_CUPS_HTTP_READ;

      request->attempts = 0;
      return;
    }
  else
    {
      request->attempts++;
    }
}