#include "globals.h"
#include "cups.h"
#include "language.h"
#include "debug.h"
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#if defined(WIN32) || defined(__EMX__)
# include <io.h>
#else
# include <unistd.h>
#endif
http_status_t
cupsGetFd(http_t *http,
const char *resource,
int fd)
{
int bytes;
char buffer[8192];
http_status_t status;
char if_modified_since[HTTP_MAX_VALUE];
DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http,
resource, fd));
if (!resource || fd < 0)
{
if (http)
http->error = EINVAL;
return (HTTP_ERROR);
}
if (!http)
if ((http = _cupsConnect()) == NULL)
return (HTTP_SERVICE_UNAVAILABLE);
strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
sizeof(if_modified_since));
do
{
httpClearFields(http);
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
if (httpGet(http, resource))
{
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
else
{
status = HTTP_UNAUTHORIZED;
continue;
}
}
while ((status = httpUpdate(http)) == HTTP_CONTINUE);
if (status == HTTP_UNAUTHORIZED)
{
httpFlush(http);
if (cupsDoAuthentication(http, "GET", resource))
{
status = HTTP_AUTHORIZATION_CANCELED;
break;
}
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
continue;
}
#ifdef HAVE_SSL
else if (status == HTTP_UPGRADE_REQUIRED)
{
httpFlush(http);
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
continue;
}
#endif
}
while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
if (status == HTTP_OK)
{
while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
write(fd, buffer, bytes);
}
else
{
_cupsSetHTTPError(status);
httpFlush(http);
}
DEBUG_printf(("1cupsGetFd: Returning %d...", status));
return (status);
}
http_status_t
cupsGetFile(http_t *http,
const char *resource,
const char *filename)
{
int fd;
http_status_t status;
if (!http || !resource || !filename)
{
if (http)
http->error = EINVAL;
return (HTTP_ERROR);
}
if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
{
http->error = errno;
return (HTTP_ERROR);
}
status = cupsGetFd(http, resource, fd);
close(fd);
if (status != HTTP_OK)
unlink(filename);
return (status);
}
http_status_t
cupsPutFd(http_t *http,
const char *resource,
int fd)
{
int bytes,
retries;
char buffer[8192];
http_status_t status;
DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http,
resource, fd));
if (!resource || fd < 0)
{
if (http)
http->error = EINVAL;
return (HTTP_ERROR);
}
if (!http)
if ((http = _cupsConnect()) == NULL)
return (HTTP_SERVICE_UNAVAILABLE);
retries = 0;
do
{
DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
http->authstring));
httpClearFields(http);
httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
httpSetExpect(http, HTTP_CONTINUE);
if (httpPut(http, resource))
{
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
else
{
status = HTTP_UNAUTHORIZED;
continue;
}
}
if (httpWait(http, 1000))
status = httpUpdate(http);
else
status = HTTP_CONTINUE;
if (status == HTTP_CONTINUE)
{
lseek(fd, 0, SEEK_SET);
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
if (httpCheck(http))
{
if ((status = httpUpdate(http)) != HTTP_CONTINUE)
break;
}
else
httpWrite2(http, buffer, bytes);
}
if (status == HTTP_CONTINUE)
{
httpWrite2(http, buffer, 0);
while ((status = httpUpdate(http)) == HTTP_CONTINUE);
}
if (status == HTTP_ERROR && !retries)
{
DEBUG_printf(("2cupsPutFd: retry on status %d", status));
retries ++;
httpFlush(http);
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
continue;
}
DEBUG_printf(("2cupsPutFd: status=%d", status));
if (status == HTTP_UNAUTHORIZED)
{
httpFlush(http);
if (cupsDoAuthentication(http, "PUT", resource))
{
status = HTTP_AUTHORIZATION_CANCELED;
break;
}
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
continue;
}
#ifdef HAVE_SSL
else if (status == HTTP_UPGRADE_REQUIRED)
{
httpFlush(http);
if (httpReconnect(http))
{
status = HTTP_ERROR;
break;
}
httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
continue;
}
#endif
}
while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
(status == HTTP_ERROR && retries < 2));
if (status != HTTP_CREATED)
{
_cupsSetHTTPError(status);
httpFlush(http);
}
DEBUG_printf(("1cupsPutFd: Returning %d...", status));
return (status);
}
http_status_t
cupsPutFile(http_t *http,
const char *resource,
const char *filename)
{
int fd;
http_status_t status;
if (!http || !resource || !filename)
{
if (http)
http->error = EINVAL;
return (HTTP_ERROR);
}
if ((fd = open(filename, O_RDONLY)) < 0)
{
http->error = errno;
return (HTTP_ERROR);
}
status = cupsPutFd(http, resource, fd);
close(fd);
return (status);
}