#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <ctype.h>
#include "string.h"
#include "http.h"
#include "ipp.h"
static const char *http_copy_decode(char *dst, const char *src,
int dstsize, const char *term, int decode);
void
httpSeparate(const char *uri,
char *method,
char *username,
char *host,
int *port,
char *resource)
{
httpSeparateApple(uri, method, 32, username, HTTP_MAX_URI, host, HTTP_MAX_URI,
port, resource, HTTP_MAX_URI, 1);
}
void
httpSeparate2(const char *uri,
char *method,
int methodlen,
char *username,
int usernamelen,
char *host,
int hostlen,
int *port,
char *resource,
int resourcelen)
{
httpSeparateApple(uri, method, 32, username, HTTP_MAX_URI, host, HTTP_MAX_URI,
port, resource, HTTP_MAX_URI, 1);
}
void
httpSeparateApple(const char *uri,
char *method,
int methodlen,
char *username,
int usernamelen,
char *host,
int hostlen,
int *port,
char *resource,
int resourcelen,
int decode)
{
char *ptr;
const char *atsign,
*slash;
if (uri == NULL || method == NULL || username == NULL || host == NULL ||
port == NULL || resource == NULL)
return;
if (strncmp(uri, "//", 2) == 0)
{
strlcpy(method, "ipp", methodlen);
}
else
{
uri = http_copy_decode(host, uri, hostlen, ":", decode);
if (*uri == ':')
uri ++;
if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0')
{
if ((ptr = strchr(host, '/')) != NULL)
{
strlcpy(resource, ptr, resourcelen);
*ptr = '\0';
}
else
resource[0] = '\0';
if (isdigit(*uri & 255))
{
*port = strtol(uri, (char **)&uri, 10);
if (*uri == '/')
strlcpy(resource, uri, resourcelen);
}
else
*port = 631;
strlcpy(method, "http", methodlen);
username[0] = '\0';
return;
}
else
strlcpy(method, host, methodlen);
}
if (strncmp(uri, "//", 2) != 0)
{
strlcpy(resource, uri, resourcelen);
username[0] = '\0';
host[0] = '\0';
*port = 0;
return;
}
uri += 2;
if ((slash = strchr(uri, '/')) == NULL)
slash = uri + strlen(uri);
if ((atsign = strchr(uri, '@')) != NULL && atsign < slash)
{
uri = http_copy_decode(username, uri, usernamelen, "@", decode) + 1;
}
else
username[0] = '\0';
uri = http_copy_decode(host, uri, hostlen, ":/", decode);
if (*uri == ':' && isdigit(*(uri+1) & 255))
{
*port = strtol(uri + 1, (char **)&uri, 10);
}
else
{
if (strcasecmp(method, "http") == 0)
*port = 80;
else if (strcasecmp(method, "https") == 0)
*port = 443;
else if (strcasecmp(method, "ipp") == 0)
*port = 631;
else if (strcasecmp(method, "lpd") == 0)
*port = 515;
else if (strcasecmp(method, "socket") == 0)
*port = 9100;
else
*port = 0;
}
if (*uri == '\0')
{
resource[0] = '/';
resource[1] = '\0';
return;
}
http_copy_decode(resource, uri, resourcelen, "", decode);
}
const char *
httpStatus(http_status_t status)
{
switch (status)
{
case HTTP_CONTINUE :
return ("Continue");
case HTTP_SWITCHING_PROTOCOLS :
return ("Switching Protocols");
case HTTP_OK :
return ("OK");
case HTTP_CREATED :
return ("Created");
case HTTP_ACCEPTED :
return ("Accepted");
case HTTP_NO_CONTENT :
return ("No Content");
case HTTP_NOT_MODIFIED :
return ("Not Modified");
case HTTP_BAD_REQUEST :
return ("Bad Request");
case HTTP_UNAUTHORIZED :
return ("Unauthorized");
case HTTP_FORBIDDEN :
return ("Forbidden");
case HTTP_NOT_FOUND :
return ("Not Found");
case HTTP_REQUEST_TOO_LARGE :
return ("Request Entity Too Large");
case HTTP_URI_TOO_LONG :
return ("URI Too Long");
case HTTP_UPGRADE_REQUIRED :
return ("Upgrade Required");
case HTTP_NOT_IMPLEMENTED :
return ("Not Implemented");
case HTTP_NOT_SUPPORTED :
return ("Not Supported");
default :
return ("Unknown");
}
}
#ifndef HAVE_HSTRERROR
const char *
cups_hstrerror(int error)
{
static const char * const errors[] =
{
"OK",
"Host not found.",
"Try again.",
"Unrecoverable lookup error.",
"No data associated with name."
};
if (error < 0 || error > 4)
return ("Unknown hostname lookup error.");
else
return (errors[error]);
}
#endif
static const char *
http_copy_decode(char *dst,
const char *src,
int dstsize,
const char *term,
int decode)
{
char *ptr,
*end;
int quoted;
for (ptr = dst, end = dst + dstsize - 1; *src && !strchr(term, *src); src ++)
if (ptr < end)
{
if (decode && *src == '%' && isxdigit(src[1] & 255) && isxdigit(src[2] & 255))
{
src ++;
if (isalpha(*src))
quoted = (tolower(*src) - 'a' + 10) << 4;
else
quoted = (*src - '0') << 4;
src ++;
if (isalpha(*src))
quoted |= tolower(*src) - 'a' + 10;
else
quoted |= *src - '0';
*ptr++ = quoted;
}
else
*ptr++ = *src;
}
*ptr = '\0';
return (src);
}