]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/getputfile.c
Load cups into easysw/current.
[thirdparty/cups.git] / cups / getputfile.c
1 /*
2 * "$Id: getputfile.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * Get/put file functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * cupsGetFd() - Get a file from the server.
20 * cupsGetFile() - Get a file from the server.
21 * cupsPutFd() - Put a file on the server.
22 * cupsPutFile() - Put a file on the server.
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include "http-private.h"
30 #include "cups.h"
31 #include "language.h"
32 #include "string.h"
33 #include "debug.h"
34 #include <stdlib.h>
35 #include <ctype.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #if defined(WIN32) || defined(__EMX__)
40 # include <io.h>
41 #else
42 # include <unistd.h>
43 #endif /* WIN32 || __EMX__ */
44
45
46 /*
47 * 'cupsGetFd()' - Get a file from the server.
48 *
49 * This function returns HTTP_OK when the file is successfully retrieved.
50 *
51 * @since CUPS 1.1.20@
52 */
53
54 http_status_t /* O - HTTP status */
55 cupsGetFd(http_t *http, /* I - HTTP connection to server */
56 const char *resource, /* I - Resource name */
57 int fd) /* I - File descriptor */
58 {
59 int bytes; /* Number of bytes read */
60 char buffer[8192]; /* Buffer for file */
61 http_status_t status; /* HTTP status from server */
62 char if_modified_since[HTTP_MAX_VALUE];
63 /* If-Modified-Since header */
64
65
66 /*
67 * Range check input...
68 */
69
70 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http,
71 resource, fd));
72
73 if (!http || !resource || fd < 0)
74 {
75 if (http)
76 http->error = EINVAL;
77
78 return (HTTP_ERROR);
79 }
80
81 /*
82 * Then send GET requests to the HTTP server...
83 */
84
85 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
86 sizeof(if_modified_since));
87
88 do
89 {
90 httpClearFields(http);
91 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
92 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
93
94 if (httpGet(http, resource))
95 {
96 if (httpReconnect(http))
97 {
98 status = HTTP_ERROR;
99 break;
100 }
101 else
102 {
103 status = HTTP_UNAUTHORIZED;
104 continue;
105 }
106 }
107
108 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
109
110 if (status == HTTP_UNAUTHORIZED)
111 {
112 /*
113 * Flush any error message...
114 */
115
116 httpFlush(http);
117
118 /*
119 * See if we can do authentication...
120 */
121
122 if (cupsDoAuthentication(http, "GET", resource))
123 break;
124
125 if (httpReconnect(http))
126 {
127 status = HTTP_ERROR;
128 break;
129 }
130
131 continue;
132 }
133 #ifdef HAVE_SSL
134 else if (status == HTTP_UPGRADE_REQUIRED)
135 {
136 /* Flush any error message... */
137 httpFlush(http);
138
139 /* Reconnect... */
140 if (httpReconnect(http))
141 {
142 status = HTTP_ERROR;
143 break;
144 }
145
146 /* Upgrade with encryption... */
147 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
148
149 /* Try again, this time with encryption enabled... */
150 continue;
151 }
152 #endif /* HAVE_SSL */
153 }
154 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
155
156 /*
157 * See if we actually got the file or an error...
158 */
159
160 if (status == HTTP_OK)
161 {
162 /*
163 * Yes, copy the file...
164 */
165
166 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
167 write(fd, buffer, bytes);
168 }
169 else
170 httpFlush(http);
171
172 /*
173 * Return the request status...
174 */
175
176 return (status);
177 }
178
179
180 /*
181 * 'cupsGetFile()' - Get a file from the server.
182 *
183 * This function returns HTTP_OK when the file is successfully retrieved.
184 *
185 * @since CUPS 1.1.20@
186 */
187
188 http_status_t /* O - HTTP status */
189 cupsGetFile(http_t *http, /* I - HTTP connection to server */
190 const char *resource, /* I - Resource name */
191 const char *filename) /* I - Filename */
192 {
193 int fd; /* File descriptor */
194 http_status_t status; /* Status */
195
196
197 /*
198 * Range check input...
199 */
200
201 if (!http || !resource || !filename)
202 {
203 if (http)
204 http->error = EINVAL;
205
206 return (HTTP_ERROR);
207 }
208
209 /*
210 * Create the file...
211 */
212
213 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
214 {
215 /*
216 * Couldn't open the file!
217 */
218
219 http->error = errno;
220
221 return (HTTP_ERROR);
222 }
223
224 /*
225 * Get the file...
226 */
227
228 status = cupsGetFd(http, resource, fd);
229
230 /*
231 * If the file couldn't be gotten, then remove the file...
232 */
233
234 close(fd);
235
236 if (status != HTTP_OK)
237 unlink(filename);
238
239 /*
240 * Return the HTTP status code...
241 */
242
243 return (status);
244 }
245
246
247 /*
248 * 'cupsPutFd()' - Put a file on the server.
249 *
250 * This function returns HTTP_CREATED when the file is stored successfully.
251 *
252 * @since CUPS 1.1.20@
253 */
254
255 http_status_t /* O - HTTP status */
256 cupsPutFd(http_t *http, /* I - HTTP connection to server */
257 const char *resource, /* I - Resource name */
258 int fd) /* I - File descriptor */
259 {
260 int bytes, /* Number of bytes read */
261 retries; /* Number of retries */
262 char buffer[8192]; /* Buffer for file */
263 http_status_t status; /* HTTP status from server */
264
265
266 /*
267 * Range check input...
268 */
269
270 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)\n", http,
271 resource, fd));
272
273 if (!http || !resource || fd < 0)
274 {
275 if (http)
276 http->error = EINVAL;
277
278 return (HTTP_ERROR);
279 }
280
281 /*
282 * Then send PUT requests to the HTTP server...
283 */
284
285 retries = 0;
286
287 do
288 {
289 DEBUG_printf(("cupsPutFd: starting attempt, authstring=\"%s\"...\n",
290 http->authstring));
291
292 httpClearFields(http);
293 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
294 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
295 httpSetExpect(http, HTTP_CONTINUE);
296
297 if (httpPut(http, resource))
298 {
299 if (httpReconnect(http))
300 {
301 status = HTTP_ERROR;
302 break;
303 }
304 else
305 {
306 status = HTTP_UNAUTHORIZED;
307 continue;
308 }
309 }
310
311 /*
312 * Wait up to 1 second for a 100-continue response...
313 */
314
315 if (httpWait(http, 1000))
316 status = httpUpdate(http);
317 else
318 status = HTTP_CONTINUE;
319
320 if (status == HTTP_CONTINUE)
321 {
322 /*
323 * Copy the file...
324 */
325
326 lseek(fd, 0, SEEK_SET);
327
328 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
329 if (httpCheck(http))
330 {
331 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
332 break;
333 }
334 else
335 httpWrite2(http, buffer, bytes);
336 }
337
338 if (status == HTTP_CONTINUE)
339 {
340 httpWrite2(http, buffer, 0);
341
342 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
343 }
344
345 if (status == HTTP_ERROR && !retries)
346 {
347 DEBUG_printf(("cupsPutFd: retry on status %d\n", status));
348
349 retries ++;
350
351 /* Flush any error message... */
352 httpFlush(http);
353
354 /* Reconnect... */
355 if (httpReconnect(http))
356 {
357 status = HTTP_ERROR;
358 break;
359 }
360
361 /* Try again... */
362 continue;
363 }
364
365 DEBUG_printf(("cupsPutFd: status=%d\n", status));
366
367 if (status == HTTP_UNAUTHORIZED)
368 {
369 /*
370 * Flush any error message...
371 */
372
373 httpFlush(http);
374
375 /*
376 * See if we can do authentication...
377 */
378
379 if (cupsDoAuthentication(http, "PUT", resource))
380 break;
381
382 if (httpReconnect(http))
383 {
384 status = HTTP_ERROR;
385 break;
386 }
387
388 continue;
389 }
390 #ifdef HAVE_SSL
391 else if (status == HTTP_UPGRADE_REQUIRED)
392 {
393 /* Flush any error message... */
394 httpFlush(http);
395
396 /* Reconnect... */
397 if (httpReconnect(http))
398 {
399 status = HTTP_ERROR;
400 break;
401 }
402
403 /* Upgrade with encryption... */
404 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
405
406 /* Try again, this time with encryption enabled... */
407 continue;
408 }
409 #endif /* HAVE_SSL */
410 }
411 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
412 (status == HTTP_ERROR && retries < 2));
413
414 /*
415 * See if we actually put the file or an error...
416 */
417
418 if (status != HTTP_CREATED)
419 httpFlush(http);
420
421 return (status);
422 }
423
424
425 /*
426 * 'cupsPutFile()' - Put a file on the server.
427 *
428 * This function returns HTTP_CREATED when the file is stored successfully.
429 *
430 * @since CUPS 1.1.20@
431 */
432
433 http_status_t /* O - HTTP status */
434 cupsPutFile(http_t *http, /* I - HTTP connection to server */
435 const char *resource, /* I - Resource name */
436 const char *filename) /* I - Filename */
437 {
438 int fd; /* File descriptor */
439 http_status_t status; /* Status */
440
441
442 /*
443 * Range check input...
444 */
445
446 if (!http || !resource || !filename)
447 {
448 if (http)
449 http->error = EINVAL;
450
451 return (HTTP_ERROR);
452 }
453
454 /*
455 * Open the local file...
456 */
457
458 if ((fd = open(filename, O_RDONLY)) < 0)
459 {
460 /*
461 * Couldn't open the file!
462 */
463
464 http->error = errno;
465
466 return (HTTP_ERROR);
467 }
468
469 /*
470 * Put the file...
471 */
472
473 status = cupsPutFd(http, resource, fd);
474
475 close(fd);
476
477 return (status);
478 }
479
480
481 /*
482 * End of "$Id: getputfile.c 6649 2007-07-11 21:46:42Z mike $".
483 */