]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http-support.c
Update copyright notices, addresses, etc.
[thirdparty/cups.git] / cups / http-support.c
1 /*
2 * "$Id$"
3 *
4 * HTTP support routines for the Common UNIX Printing System (CUPS) scheduler.
5 *
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * httpSeparate() - Separate a Universal Resource Identifier into its
29 * components.
30 * httpSeparate2() - Separate a Universal Resource Identifier into its
31 * components.
32 * httpStatus() - Return a short string describing a HTTP status code.
33 * cups_hstrerror() - hstrerror() emulation function for Solaris and others...
34 * http_copy_decode() - Copy and decode a URI.
35 */
36
37 /*
38 * Include necessary headers...
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <stdarg.h>
44 #include <ctype.h>
45 #include "string.h"
46
47 #include "http.h"
48 #include "ipp.h"
49
50
51 /*
52 * Local functions...
53 */
54
55 static const char *http_copy_decode(char *dst, const char *src,
56 int dstsize, const char *term);
57
58
59 /*
60 * 'httpSeparate()' - Separate a Universal Resource Identifier into its
61 * components.
62 */
63
64 void
65 httpSeparate(const char *uri, /* I - Universal Resource Identifier */
66 char *method, /* O - Method [32] (http, https, etc.) */
67 char *username, /* O - Username [1024] */
68 char *host, /* O - Hostname [1024] */
69 int *port, /* O - Port number to use */
70 char *resource) /* O - Resource/filename [1024] */
71 {
72 httpSeparate2(uri, method, 32, username, HTTP_MAX_URI, host, HTTP_MAX_URI,
73 port, resource, HTTP_MAX_URI);
74 }
75
76
77 /*
78 * 'httpSeparate2()' - Separate a Universal Resource Identifier into its
79 * components.
80 */
81
82 void
83 httpSeparate2(const char *uri, /* I - Universal Resource Identifier */
84 char *method, /* O - Method (http, https, etc.) */
85 int methodlen, /* I - Size of method buffer */
86 char *username, /* O - Username */
87 int usernamelen, /* I - Size of username buffer */
88 char *host, /* O - Hostname */
89 int hostlen, /* I - Size of hostname buffer */
90 int *port, /* O - Port number to use */
91 char *resource, /* O - Resource/filename */
92 int resourcelen) /* I - Size of resource buffer */
93 {
94 char *ptr; /* Pointer into string... */
95 const char *atsign, /* @ sign */
96 *slash; /* Separator */
97
98
99 /*
100 * Range check input...
101 */
102
103 if (uri == NULL || method == NULL || username == NULL || host == NULL ||
104 port == NULL || resource == NULL)
105 return;
106
107 /*
108 * Grab the method portion of the URI...
109 */
110
111 if (strncmp(uri, "//", 2) == 0)
112 {
113 /*
114 * Workaround for HP IPP client bug...
115 */
116
117 strlcpy(method, "ipp", methodlen);
118 }
119 else
120 {
121 /*
122 * Standard URI with method...
123 */
124
125 uri = http_copy_decode(host, uri, hostlen, ":");
126
127 if (*uri == ':')
128 uri ++;
129
130 /*
131 * If the method contains a period or slash, then it's probably
132 * hostname/filename...
133 */
134
135 if (strchr(host, '.') != NULL || strchr(host, '/') != NULL || *uri == '\0')
136 {
137 if ((ptr = strchr(host, '/')) != NULL)
138 {
139 strlcpy(resource, ptr, resourcelen);
140 *ptr = '\0';
141 }
142 else
143 resource[0] = '\0';
144
145 if (isdigit(*uri & 255))
146 {
147 /*
148 * OK, we have "hostname:port[/resource]"...
149 */
150
151 *port = strtol(uri, (char **)&uri, 10);
152
153 if (*uri == '/')
154 strlcpy(resource, uri, resourcelen);
155 }
156 else
157 *port = 631;
158
159 strlcpy(method, "http", methodlen);
160 username[0] = '\0';
161 return;
162 }
163 else
164 strlcpy(method, host, methodlen);
165 }
166
167 /*
168 * If the method starts with less than 2 slashes then it is a local resource...
169 */
170
171 if (strncmp(uri, "//", 2) != 0)
172 {
173 strlcpy(resource, uri, resourcelen);
174
175 username[0] = '\0';
176 host[0] = '\0';
177 *port = 0;
178 return;
179 }
180
181 /*
182 * Grab the username, if any...
183 */
184
185 uri += 2;
186
187 if ((slash = strchr(uri, '/')) == NULL)
188 slash = uri + strlen(uri);
189
190 if ((atsign = strchr(uri, '@')) != NULL && atsign < slash)
191 {
192 /*
193 * Got a username:password combo...
194 */
195
196 uri = http_copy_decode(username, uri, usernamelen, "@") + 1;
197 }
198 else
199 username[0] = '\0';
200
201 /*
202 * Grab the hostname...
203 */
204
205 uri = http_copy_decode(host, uri, hostlen, ":/");
206
207 if (*uri != ':')
208 {
209 if (strcasecmp(method, "http") == 0)
210 *port = 80;
211 else if (strcasecmp(method, "https") == 0)
212 *port = 443;
213 else if (strcasecmp(method, "ipp") == 0)
214 *port = 631;
215 else if (strcasecmp(method, "lpd") == 0)
216 *port = 515;
217 else if (strcasecmp(method, "socket") == 0) /* Not registered yet... */
218 *port = 9100;
219 else
220 *port = 0;
221 }
222 else
223 {
224 /*
225 * Parse port number...
226 */
227
228 *port = strtol(uri + 1, (char **)&uri, 10);
229 }
230
231 if (*uri == '\0')
232 {
233 /*
234 * Hostname but no port or path...
235 */
236
237 resource[0] = '/';
238 resource[1] = '\0';
239 return;
240 }
241
242 /*
243 * The remaining portion is the resource string...
244 */
245
246 http_copy_decode(resource, uri, resourcelen, "");
247 }
248
249
250 /*
251 * 'httpStatus()' - Return a short string describing a HTTP status code.
252 */
253
254 const char * /* O - String or NULL */
255 httpStatus(http_status_t status) /* I - HTTP status code */
256 {
257 switch (status)
258 {
259 case HTTP_CONTINUE :
260 return ("Continue");
261 case HTTP_SWITCHING_PROTOCOLS :
262 return ("Switching Protocols");
263 case HTTP_OK :
264 return ("OK");
265 case HTTP_CREATED :
266 return ("Created");
267 case HTTP_ACCEPTED :
268 return ("Accepted");
269 case HTTP_NO_CONTENT :
270 return ("No Content");
271 case HTTP_NOT_MODIFIED :
272 return ("Not Modified");
273 case HTTP_BAD_REQUEST :
274 return ("Bad Request");
275 case HTTP_UNAUTHORIZED :
276 return ("Unauthorized");
277 case HTTP_FORBIDDEN :
278 return ("Forbidden");
279 case HTTP_NOT_FOUND :
280 return ("Not Found");
281 case HTTP_REQUEST_TOO_LARGE :
282 return ("Request Entity Too Large");
283 case HTTP_URI_TOO_LONG :
284 return ("URI Too Long");
285 case HTTP_UPGRADE_REQUIRED :
286 return ("Upgrade Required");
287 case HTTP_NOT_IMPLEMENTED :
288 return ("Not Implemented");
289 case HTTP_NOT_SUPPORTED :
290 return ("Not Supported");
291 default :
292 return ("Unknown");
293 }
294 }
295
296
297 #ifndef HAVE_HSTRERROR
298 /*
299 * 'cups_hstrerror()' - hstrerror() emulation function for Solaris and others...
300 */
301
302 const char * /* O - Error string */
303 cups_hstrerror(int error) /* I - Error number */
304 {
305 static const char * const errors[] = /* Error strings */
306 {
307 "OK",
308 "Host not found.",
309 "Try again.",
310 "Unrecoverable lookup error.",
311 "No data associated with name."
312 };
313
314
315 if (error < 0 || error > 4)
316 return ("Unknown hostname lookup error.");
317 else
318 return (errors[error]);
319 }
320 #endif /* !HAVE_HSTRERROR */
321
322
323 /*
324 * 'http_copy_decode()' - Copy and decode a URI.
325 */
326
327 static const char * /* O - New source pointer */
328 http_copy_decode(char *dst, /* O - Destination buffer */
329 const char *src, /* I - Source pointer */
330 int dstsize, /* I - Destination size */
331 const char *term) /* I - Terminating characters */
332 {
333 char *ptr, /* Pointer into buffer */
334 *end; /* End of buffer */
335 int quoted; /* Quoted character */
336
337
338 /*
339 * Copy the src to the destination until we hit a terminating character
340 * or the end of the string.
341 */
342
343 for (ptr = dst, end = dst + dstsize - 1; *src && !strchr(term, *src); src ++)
344 if (ptr < end)
345 {
346 if (*src == '%' && isxdigit(src[1] & 255) && isxdigit(src[2] & 255))
347 {
348 /*
349 * Grab a hex-encoded character...
350 */
351
352 src ++;
353 if (isalpha(*src))
354 quoted = (tolower(*src) - 'a' + 10) << 4;
355 else
356 quoted = (*src - '0') << 4;
357
358 src ++;
359 if (isalpha(*src))
360 quoted |= tolower(*src) - 'a' + 10;
361 else
362 quoted |= *src - '0';
363
364 *ptr++ = quoted;
365 }
366 else
367 *ptr++ = *src;
368 }
369
370 *ptr = '\0';
371
372 return (src);
373 }
374
375
376 /*
377 * End of "$Id$".
378 */