1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker * Get/put file functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker *
4*5e7646d2SAndroid Build Coastguard Worker * Copyright 2007-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker * Copyright 1997-2006 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker *
7*5e7646d2SAndroid Build Coastguard Worker * Licensed under Apache License v2.0. See the file "LICENSE" for more
8*5e7646d2SAndroid Build Coastguard Worker * information.
9*5e7646d2SAndroid Build Coastguard Worker */
10*5e7646d2SAndroid Build Coastguard Worker
11*5e7646d2SAndroid Build Coastguard Worker /*
12*5e7646d2SAndroid Build Coastguard Worker * Include necessary headers...
13*5e7646d2SAndroid Build Coastguard Worker */
14*5e7646d2SAndroid Build Coastguard Worker
15*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
16*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
17*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
19*5e7646d2SAndroid Build Coastguard Worker #if defined(_WIN32) || defined(__EMX__)
20*5e7646d2SAndroid Build Coastguard Worker # include <io.h>
21*5e7646d2SAndroid Build Coastguard Worker #else
22*5e7646d2SAndroid Build Coastguard Worker # include <unistd.h>
23*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 || __EMX__ */
24*5e7646d2SAndroid Build Coastguard Worker
25*5e7646d2SAndroid Build Coastguard Worker
26*5e7646d2SAndroid Build Coastguard Worker /*
27*5e7646d2SAndroid Build Coastguard Worker * 'cupsGetFd()' - Get a file from the server.
28*5e7646d2SAndroid Build Coastguard Worker *
29*5e7646d2SAndroid Build Coastguard Worker * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
30*5e7646d2SAndroid Build Coastguard Worker *
31*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.20/macOS 10.4@
32*5e7646d2SAndroid Build Coastguard Worker */
33*5e7646d2SAndroid Build Coastguard Worker
34*5e7646d2SAndroid Build Coastguard Worker http_status_t /* O - HTTP status */
cupsGetFd(http_t * http,const char * resource,int fd)35*5e7646d2SAndroid Build Coastguard Worker cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
36*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource name */
37*5e7646d2SAndroid Build Coastguard Worker int fd) /* I - File descriptor */
38*5e7646d2SAndroid Build Coastguard Worker {
39*5e7646d2SAndroid Build Coastguard Worker ssize_t bytes; /* Number of bytes read */
40*5e7646d2SAndroid Build Coastguard Worker char buffer[8192]; /* Buffer for file */
41*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* HTTP status from server */
42*5e7646d2SAndroid Build Coastguard Worker char if_modified_since[HTTP_MAX_VALUE];
43*5e7646d2SAndroid Build Coastguard Worker /* If-Modified-Since header */
44*5e7646d2SAndroid Build Coastguard Worker int new_auth = 0; /* Using new auth information? */
45*5e7646d2SAndroid Build Coastguard Worker int digest; /* Are we using Digest authentication? */
46*5e7646d2SAndroid Build Coastguard Worker
47*5e7646d2SAndroid Build Coastguard Worker
48*5e7646d2SAndroid Build Coastguard Worker /*
49*5e7646d2SAndroid Build Coastguard Worker * Range check input...
50*5e7646d2SAndroid Build Coastguard Worker */
51*5e7646d2SAndroid Build Coastguard Worker
52*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));
53*5e7646d2SAndroid Build Coastguard Worker
54*5e7646d2SAndroid Build Coastguard Worker if (!resource || fd < 0)
55*5e7646d2SAndroid Build Coastguard Worker {
56*5e7646d2SAndroid Build Coastguard Worker if (http)
57*5e7646d2SAndroid Build Coastguard Worker http->error = EINVAL;
58*5e7646d2SAndroid Build Coastguard Worker
59*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
60*5e7646d2SAndroid Build Coastguard Worker }
61*5e7646d2SAndroid Build Coastguard Worker
62*5e7646d2SAndroid Build Coastguard Worker if (!http)
63*5e7646d2SAndroid Build Coastguard Worker if ((http = _cupsConnect()) == NULL)
64*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_SERVICE_UNAVAILABLE);
65*5e7646d2SAndroid Build Coastguard Worker
66*5e7646d2SAndroid Build Coastguard Worker /*
67*5e7646d2SAndroid Build Coastguard Worker * Then send GET requests to the HTTP server...
68*5e7646d2SAndroid Build Coastguard Worker */
69*5e7646d2SAndroid Build Coastguard Worker
70*5e7646d2SAndroid Build Coastguard Worker strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
71*5e7646d2SAndroid Build Coastguard Worker sizeof(if_modified_since));
72*5e7646d2SAndroid Build Coastguard Worker
73*5e7646d2SAndroid Build Coastguard Worker do
74*5e7646d2SAndroid Build Coastguard Worker {
75*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
76*5e7646d2SAndroid Build Coastguard Worker {
77*5e7646d2SAndroid Build Coastguard Worker httpClearFields(http);
78*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
79*5e7646d2SAndroid Build Coastguard Worker {
80*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
81*5e7646d2SAndroid Build Coastguard Worker break;
82*5e7646d2SAndroid Build Coastguard Worker }
83*5e7646d2SAndroid Build Coastguard Worker }
84*5e7646d2SAndroid Build Coastguard Worker
85*5e7646d2SAndroid Build Coastguard Worker httpClearFields(http);
86*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
87*5e7646d2SAndroid Build Coastguard Worker
88*5e7646d2SAndroid Build Coastguard Worker digest = http->authstring && !strncmp(http->authstring, "Digest ", 7);
89*5e7646d2SAndroid Build Coastguard Worker
90*5e7646d2SAndroid Build Coastguard Worker if (digest && !new_auth)
91*5e7646d2SAndroid Build Coastguard Worker {
92*5e7646d2SAndroid Build Coastguard Worker /*
93*5e7646d2SAndroid Build Coastguard Worker * Update the Digest authentication string...
94*5e7646d2SAndroid Build Coastguard Worker */
95*5e7646d2SAndroid Build Coastguard Worker
96*5e7646d2SAndroid Build Coastguard Worker _httpSetDigestAuthString(http, http->nextnonce, "GET", resource);
97*5e7646d2SAndroid Build Coastguard Worker }
98*5e7646d2SAndroid Build Coastguard Worker
99*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
100*5e7646d2SAndroid Build Coastguard Worker if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth)
101*5e7646d2SAndroid Build Coastguard Worker {
102*5e7646d2SAndroid Build Coastguard Worker /*
103*5e7646d2SAndroid Build Coastguard Worker * Do not use cached Kerberos credentials since they will look like a
104*5e7646d2SAndroid Build Coastguard Worker * "replay" attack...
105*5e7646d2SAndroid Build Coastguard Worker */
106*5e7646d2SAndroid Build Coastguard Worker
107*5e7646d2SAndroid Build Coastguard Worker _cupsSetNegotiateAuthString(http, "GET", resource);
108*5e7646d2SAndroid Build Coastguard Worker }
109*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
110*5e7646d2SAndroid Build Coastguard Worker
111*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
112*5e7646d2SAndroid Build Coastguard Worker
113*5e7646d2SAndroid Build Coastguard Worker if (httpGet(http, resource))
114*5e7646d2SAndroid Build Coastguard Worker {
115*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
116*5e7646d2SAndroid Build Coastguard Worker {
117*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
118*5e7646d2SAndroid Build Coastguard Worker break;
119*5e7646d2SAndroid Build Coastguard Worker }
120*5e7646d2SAndroid Build Coastguard Worker else
121*5e7646d2SAndroid Build Coastguard Worker {
122*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_UNAUTHORIZED;
123*5e7646d2SAndroid Build Coastguard Worker continue;
124*5e7646d2SAndroid Build Coastguard Worker }
125*5e7646d2SAndroid Build Coastguard Worker }
126*5e7646d2SAndroid Build Coastguard Worker
127*5e7646d2SAndroid Build Coastguard Worker new_auth = 0;
128*5e7646d2SAndroid Build Coastguard Worker
129*5e7646d2SAndroid Build Coastguard Worker while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
130*5e7646d2SAndroid Build Coastguard Worker
131*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_UNAUTHORIZED)
132*5e7646d2SAndroid Build Coastguard Worker {
133*5e7646d2SAndroid Build Coastguard Worker /*
134*5e7646d2SAndroid Build Coastguard Worker * Flush any error message...
135*5e7646d2SAndroid Build Coastguard Worker */
136*5e7646d2SAndroid Build Coastguard Worker
137*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
138*5e7646d2SAndroid Build Coastguard Worker
139*5e7646d2SAndroid Build Coastguard Worker /*
140*5e7646d2SAndroid Build Coastguard Worker * See if we can do authentication...
141*5e7646d2SAndroid Build Coastguard Worker */
142*5e7646d2SAndroid Build Coastguard Worker
143*5e7646d2SAndroid Build Coastguard Worker new_auth = 1;
144*5e7646d2SAndroid Build Coastguard Worker
145*5e7646d2SAndroid Build Coastguard Worker if (cupsDoAuthentication(http, "GET", resource))
146*5e7646d2SAndroid Build Coastguard Worker {
147*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
148*5e7646d2SAndroid Build Coastguard Worker break;
149*5e7646d2SAndroid Build Coastguard Worker }
150*5e7646d2SAndroid Build Coastguard Worker
151*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
152*5e7646d2SAndroid Build Coastguard Worker {
153*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
154*5e7646d2SAndroid Build Coastguard Worker break;
155*5e7646d2SAndroid Build Coastguard Worker }
156*5e7646d2SAndroid Build Coastguard Worker
157*5e7646d2SAndroid Build Coastguard Worker continue;
158*5e7646d2SAndroid Build Coastguard Worker }
159*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
160*5e7646d2SAndroid Build Coastguard Worker else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
161*5e7646d2SAndroid Build Coastguard Worker {
162*5e7646d2SAndroid Build Coastguard Worker /* Flush any error message... */
163*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
164*5e7646d2SAndroid Build Coastguard Worker
165*5e7646d2SAndroid Build Coastguard Worker /* Reconnect... */
166*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
167*5e7646d2SAndroid Build Coastguard Worker {
168*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
169*5e7646d2SAndroid Build Coastguard Worker break;
170*5e7646d2SAndroid Build Coastguard Worker }
171*5e7646d2SAndroid Build Coastguard Worker
172*5e7646d2SAndroid Build Coastguard Worker /* Upgrade with encryption... */
173*5e7646d2SAndroid Build Coastguard Worker httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
174*5e7646d2SAndroid Build Coastguard Worker
175*5e7646d2SAndroid Build Coastguard Worker /* Try again, this time with encryption enabled... */
176*5e7646d2SAndroid Build Coastguard Worker continue;
177*5e7646d2SAndroid Build Coastguard Worker }
178*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
179*5e7646d2SAndroid Build Coastguard Worker }
180*5e7646d2SAndroid Build Coastguard Worker while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);
181*5e7646d2SAndroid Build Coastguard Worker
182*5e7646d2SAndroid Build Coastguard Worker /*
183*5e7646d2SAndroid Build Coastguard Worker * See if we actually got the file or an error...
184*5e7646d2SAndroid Build Coastguard Worker */
185*5e7646d2SAndroid Build Coastguard Worker
186*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_OK)
187*5e7646d2SAndroid Build Coastguard Worker {
188*5e7646d2SAndroid Build Coastguard Worker /*
189*5e7646d2SAndroid Build Coastguard Worker * Yes, copy the file...
190*5e7646d2SAndroid Build Coastguard Worker */
191*5e7646d2SAndroid Build Coastguard Worker
192*5e7646d2SAndroid Build Coastguard Worker while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
193*5e7646d2SAndroid Build Coastguard Worker write(fd, buffer, (size_t)bytes);
194*5e7646d2SAndroid Build Coastguard Worker }
195*5e7646d2SAndroid Build Coastguard Worker else
196*5e7646d2SAndroid Build Coastguard Worker {
197*5e7646d2SAndroid Build Coastguard Worker _cupsSetHTTPError(status);
198*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
199*5e7646d2SAndroid Build Coastguard Worker }
200*5e7646d2SAndroid Build Coastguard Worker
201*5e7646d2SAndroid Build Coastguard Worker /*
202*5e7646d2SAndroid Build Coastguard Worker * Return the request status...
203*5e7646d2SAndroid Build Coastguard Worker */
204*5e7646d2SAndroid Build Coastguard Worker
205*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1cupsGetFd: Returning %d...", status));
206*5e7646d2SAndroid Build Coastguard Worker
207*5e7646d2SAndroid Build Coastguard Worker return (status);
208*5e7646d2SAndroid Build Coastguard Worker }
209*5e7646d2SAndroid Build Coastguard Worker
210*5e7646d2SAndroid Build Coastguard Worker
211*5e7646d2SAndroid Build Coastguard Worker /*
212*5e7646d2SAndroid Build Coastguard Worker * 'cupsGetFile()' - Get a file from the server.
213*5e7646d2SAndroid Build Coastguard Worker *
214*5e7646d2SAndroid Build Coastguard Worker * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
215*5e7646d2SAndroid Build Coastguard Worker *
216*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.20/macOS 10.4@
217*5e7646d2SAndroid Build Coastguard Worker */
218*5e7646d2SAndroid Build Coastguard Worker
219*5e7646d2SAndroid Build Coastguard Worker http_status_t /* O - HTTP status */
cupsGetFile(http_t * http,const char * resource,const char * filename)220*5e7646d2SAndroid Build Coastguard Worker cupsGetFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
221*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource name */
222*5e7646d2SAndroid Build Coastguard Worker const char *filename) /* I - Filename */
223*5e7646d2SAndroid Build Coastguard Worker {
224*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
225*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Status */
226*5e7646d2SAndroid Build Coastguard Worker
227*5e7646d2SAndroid Build Coastguard Worker
228*5e7646d2SAndroid Build Coastguard Worker /*
229*5e7646d2SAndroid Build Coastguard Worker * Range check input...
230*5e7646d2SAndroid Build Coastguard Worker */
231*5e7646d2SAndroid Build Coastguard Worker
232*5e7646d2SAndroid Build Coastguard Worker if (!http || !resource || !filename)
233*5e7646d2SAndroid Build Coastguard Worker {
234*5e7646d2SAndroid Build Coastguard Worker if (http)
235*5e7646d2SAndroid Build Coastguard Worker http->error = EINVAL;
236*5e7646d2SAndroid Build Coastguard Worker
237*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
238*5e7646d2SAndroid Build Coastguard Worker }
239*5e7646d2SAndroid Build Coastguard Worker
240*5e7646d2SAndroid Build Coastguard Worker /*
241*5e7646d2SAndroid Build Coastguard Worker * Create the file...
242*5e7646d2SAndroid Build Coastguard Worker */
243*5e7646d2SAndroid Build Coastguard Worker
244*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
245*5e7646d2SAndroid Build Coastguard Worker {
246*5e7646d2SAndroid Build Coastguard Worker /*
247*5e7646d2SAndroid Build Coastguard Worker * Couldn't open the file!
248*5e7646d2SAndroid Build Coastguard Worker */
249*5e7646d2SAndroid Build Coastguard Worker
250*5e7646d2SAndroid Build Coastguard Worker http->error = errno;
251*5e7646d2SAndroid Build Coastguard Worker
252*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
253*5e7646d2SAndroid Build Coastguard Worker }
254*5e7646d2SAndroid Build Coastguard Worker
255*5e7646d2SAndroid Build Coastguard Worker /*
256*5e7646d2SAndroid Build Coastguard Worker * Get the file...
257*5e7646d2SAndroid Build Coastguard Worker */
258*5e7646d2SAndroid Build Coastguard Worker
259*5e7646d2SAndroid Build Coastguard Worker status = cupsGetFd(http, resource, fd);
260*5e7646d2SAndroid Build Coastguard Worker
261*5e7646d2SAndroid Build Coastguard Worker /*
262*5e7646d2SAndroid Build Coastguard Worker * If the file couldn't be gotten, then remove the file...
263*5e7646d2SAndroid Build Coastguard Worker */
264*5e7646d2SAndroid Build Coastguard Worker
265*5e7646d2SAndroid Build Coastguard Worker close(fd);
266*5e7646d2SAndroid Build Coastguard Worker
267*5e7646d2SAndroid Build Coastguard Worker if (status != HTTP_STATUS_OK)
268*5e7646d2SAndroid Build Coastguard Worker unlink(filename);
269*5e7646d2SAndroid Build Coastguard Worker
270*5e7646d2SAndroid Build Coastguard Worker /*
271*5e7646d2SAndroid Build Coastguard Worker * Return the HTTP status code...
272*5e7646d2SAndroid Build Coastguard Worker */
273*5e7646d2SAndroid Build Coastguard Worker
274*5e7646d2SAndroid Build Coastguard Worker return (status);
275*5e7646d2SAndroid Build Coastguard Worker }
276*5e7646d2SAndroid Build Coastguard Worker
277*5e7646d2SAndroid Build Coastguard Worker
278*5e7646d2SAndroid Build Coastguard Worker /*
279*5e7646d2SAndroid Build Coastguard Worker * 'cupsPutFd()' - Put a file on the server.
280*5e7646d2SAndroid Build Coastguard Worker *
281*5e7646d2SAndroid Build Coastguard Worker * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
282*5e7646d2SAndroid Build Coastguard Worker * successfully.
283*5e7646d2SAndroid Build Coastguard Worker *
284*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.20/macOS 10.4@
285*5e7646d2SAndroid Build Coastguard Worker */
286*5e7646d2SAndroid Build Coastguard Worker
287*5e7646d2SAndroid Build Coastguard Worker http_status_t /* O - HTTP status */
cupsPutFd(http_t * http,const char * resource,int fd)288*5e7646d2SAndroid Build Coastguard Worker cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
289*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource name */
290*5e7646d2SAndroid Build Coastguard Worker int fd) /* I - File descriptor */
291*5e7646d2SAndroid Build Coastguard Worker {
292*5e7646d2SAndroid Build Coastguard Worker ssize_t bytes; /* Number of bytes read */
293*5e7646d2SAndroid Build Coastguard Worker int retries; /* Number of retries */
294*5e7646d2SAndroid Build Coastguard Worker char buffer[8192]; /* Buffer for file */
295*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* HTTP status from server */
296*5e7646d2SAndroid Build Coastguard Worker int new_auth = 0; /* Using new auth information? */
297*5e7646d2SAndroid Build Coastguard Worker int digest; /* Are we using Digest authentication? */
298*5e7646d2SAndroid Build Coastguard Worker
299*5e7646d2SAndroid Build Coastguard Worker
300*5e7646d2SAndroid Build Coastguard Worker /*
301*5e7646d2SAndroid Build Coastguard Worker * Range check input...
302*5e7646d2SAndroid Build Coastguard Worker */
303*5e7646d2SAndroid Build Coastguard Worker
304*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http, resource, fd));
305*5e7646d2SAndroid Build Coastguard Worker
306*5e7646d2SAndroid Build Coastguard Worker if (!resource || fd < 0)
307*5e7646d2SAndroid Build Coastguard Worker {
308*5e7646d2SAndroid Build Coastguard Worker if (http)
309*5e7646d2SAndroid Build Coastguard Worker http->error = EINVAL;
310*5e7646d2SAndroid Build Coastguard Worker
311*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
312*5e7646d2SAndroid Build Coastguard Worker }
313*5e7646d2SAndroid Build Coastguard Worker
314*5e7646d2SAndroid Build Coastguard Worker if (!http)
315*5e7646d2SAndroid Build Coastguard Worker if ((http = _cupsConnect()) == NULL)
316*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_SERVICE_UNAVAILABLE);
317*5e7646d2SAndroid Build Coastguard Worker
318*5e7646d2SAndroid Build Coastguard Worker /*
319*5e7646d2SAndroid Build Coastguard Worker * Then send PUT requests to the HTTP server...
320*5e7646d2SAndroid Build Coastguard Worker */
321*5e7646d2SAndroid Build Coastguard Worker
322*5e7646d2SAndroid Build Coastguard Worker retries = 0;
323*5e7646d2SAndroid Build Coastguard Worker
324*5e7646d2SAndroid Build Coastguard Worker do
325*5e7646d2SAndroid Build Coastguard Worker {
326*5e7646d2SAndroid Build Coastguard Worker if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
327*5e7646d2SAndroid Build Coastguard Worker {
328*5e7646d2SAndroid Build Coastguard Worker httpClearFields(http);
329*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
330*5e7646d2SAndroid Build Coastguard Worker {
331*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
332*5e7646d2SAndroid Build Coastguard Worker break;
333*5e7646d2SAndroid Build Coastguard Worker }
334*5e7646d2SAndroid Build Coastguard Worker }
335*5e7646d2SAndroid Build Coastguard Worker
336*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
337*5e7646d2SAndroid Build Coastguard Worker http->authstring));
338*5e7646d2SAndroid Build Coastguard Worker
339*5e7646d2SAndroid Build Coastguard Worker httpClearFields(http);
340*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
341*5e7646d2SAndroid Build Coastguard Worker httpSetExpect(http, HTTP_STATUS_CONTINUE);
342*5e7646d2SAndroid Build Coastguard Worker
343*5e7646d2SAndroid Build Coastguard Worker digest = http->authstring && !strncmp(http->authstring, "Digest ", 7);
344*5e7646d2SAndroid Build Coastguard Worker
345*5e7646d2SAndroid Build Coastguard Worker if (digest && !new_auth)
346*5e7646d2SAndroid Build Coastguard Worker {
347*5e7646d2SAndroid Build Coastguard Worker /*
348*5e7646d2SAndroid Build Coastguard Worker * Update the Digest authentication string...
349*5e7646d2SAndroid Build Coastguard Worker */
350*5e7646d2SAndroid Build Coastguard Worker
351*5e7646d2SAndroid Build Coastguard Worker _httpSetDigestAuthString(http, http->nextnonce, "PUT", resource);
352*5e7646d2SAndroid Build Coastguard Worker }
353*5e7646d2SAndroid Build Coastguard Worker
354*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_GSSAPI
355*5e7646d2SAndroid Build Coastguard Worker if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth)
356*5e7646d2SAndroid Build Coastguard Worker {
357*5e7646d2SAndroid Build Coastguard Worker /*
358*5e7646d2SAndroid Build Coastguard Worker * Do not use cached Kerberos credentials since they will look like a
359*5e7646d2SAndroid Build Coastguard Worker * "replay" attack...
360*5e7646d2SAndroid Build Coastguard Worker */
361*5e7646d2SAndroid Build Coastguard Worker
362*5e7646d2SAndroid Build Coastguard Worker _cupsSetNegotiateAuthString(http, "PUT", resource);
363*5e7646d2SAndroid Build Coastguard Worker }
364*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_GSSAPI */
365*5e7646d2SAndroid Build Coastguard Worker
366*5e7646d2SAndroid Build Coastguard Worker httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
367*5e7646d2SAndroid Build Coastguard Worker
368*5e7646d2SAndroid Build Coastguard Worker if (httpPut(http, resource))
369*5e7646d2SAndroid Build Coastguard Worker {
370*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
371*5e7646d2SAndroid Build Coastguard Worker {
372*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
373*5e7646d2SAndroid Build Coastguard Worker break;
374*5e7646d2SAndroid Build Coastguard Worker }
375*5e7646d2SAndroid Build Coastguard Worker else
376*5e7646d2SAndroid Build Coastguard Worker {
377*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_UNAUTHORIZED;
378*5e7646d2SAndroid Build Coastguard Worker continue;
379*5e7646d2SAndroid Build Coastguard Worker }
380*5e7646d2SAndroid Build Coastguard Worker }
381*5e7646d2SAndroid Build Coastguard Worker
382*5e7646d2SAndroid Build Coastguard Worker /*
383*5e7646d2SAndroid Build Coastguard Worker * Wait up to 1 second for a 100-continue response...
384*5e7646d2SAndroid Build Coastguard Worker */
385*5e7646d2SAndroid Build Coastguard Worker
386*5e7646d2SAndroid Build Coastguard Worker if (httpWait(http, 1000))
387*5e7646d2SAndroid Build Coastguard Worker status = httpUpdate(http);
388*5e7646d2SAndroid Build Coastguard Worker else
389*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_CONTINUE;
390*5e7646d2SAndroid Build Coastguard Worker
391*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_CONTINUE)
392*5e7646d2SAndroid Build Coastguard Worker {
393*5e7646d2SAndroid Build Coastguard Worker /*
394*5e7646d2SAndroid Build Coastguard Worker * Copy the file...
395*5e7646d2SAndroid Build Coastguard Worker */
396*5e7646d2SAndroid Build Coastguard Worker
397*5e7646d2SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
398*5e7646d2SAndroid Build Coastguard Worker
399*5e7646d2SAndroid Build Coastguard Worker while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
400*5e7646d2SAndroid Build Coastguard Worker if (httpCheck(http))
401*5e7646d2SAndroid Build Coastguard Worker {
402*5e7646d2SAndroid Build Coastguard Worker if ((status = httpUpdate(http)) != HTTP_STATUS_CONTINUE)
403*5e7646d2SAndroid Build Coastguard Worker break;
404*5e7646d2SAndroid Build Coastguard Worker }
405*5e7646d2SAndroid Build Coastguard Worker else
406*5e7646d2SAndroid Build Coastguard Worker httpWrite2(http, buffer, (size_t)bytes);
407*5e7646d2SAndroid Build Coastguard Worker }
408*5e7646d2SAndroid Build Coastguard Worker
409*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_CONTINUE)
410*5e7646d2SAndroid Build Coastguard Worker {
411*5e7646d2SAndroid Build Coastguard Worker httpWrite2(http, buffer, 0);
412*5e7646d2SAndroid Build Coastguard Worker
413*5e7646d2SAndroid Build Coastguard Worker while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
414*5e7646d2SAndroid Build Coastguard Worker }
415*5e7646d2SAndroid Build Coastguard Worker
416*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_ERROR && !retries)
417*5e7646d2SAndroid Build Coastguard Worker {
418*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsPutFd: retry on status %d", status));
419*5e7646d2SAndroid Build Coastguard Worker
420*5e7646d2SAndroid Build Coastguard Worker retries ++;
421*5e7646d2SAndroid Build Coastguard Worker
422*5e7646d2SAndroid Build Coastguard Worker /* Flush any error message... */
423*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
424*5e7646d2SAndroid Build Coastguard Worker
425*5e7646d2SAndroid Build Coastguard Worker /* Reconnect... */
426*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
427*5e7646d2SAndroid Build Coastguard Worker {
428*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
429*5e7646d2SAndroid Build Coastguard Worker break;
430*5e7646d2SAndroid Build Coastguard Worker }
431*5e7646d2SAndroid Build Coastguard Worker
432*5e7646d2SAndroid Build Coastguard Worker /* Try again... */
433*5e7646d2SAndroid Build Coastguard Worker continue;
434*5e7646d2SAndroid Build Coastguard Worker }
435*5e7646d2SAndroid Build Coastguard Worker
436*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("2cupsPutFd: status=%d", status));
437*5e7646d2SAndroid Build Coastguard Worker
438*5e7646d2SAndroid Build Coastguard Worker new_auth = 0;
439*5e7646d2SAndroid Build Coastguard Worker
440*5e7646d2SAndroid Build Coastguard Worker if (status == HTTP_STATUS_UNAUTHORIZED)
441*5e7646d2SAndroid Build Coastguard Worker {
442*5e7646d2SAndroid Build Coastguard Worker /*
443*5e7646d2SAndroid Build Coastguard Worker * Flush any error message...
444*5e7646d2SAndroid Build Coastguard Worker */
445*5e7646d2SAndroid Build Coastguard Worker
446*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
447*5e7646d2SAndroid Build Coastguard Worker
448*5e7646d2SAndroid Build Coastguard Worker /*
449*5e7646d2SAndroid Build Coastguard Worker * See if we can do authentication...
450*5e7646d2SAndroid Build Coastguard Worker */
451*5e7646d2SAndroid Build Coastguard Worker
452*5e7646d2SAndroid Build Coastguard Worker new_auth = 1;
453*5e7646d2SAndroid Build Coastguard Worker
454*5e7646d2SAndroid Build Coastguard Worker if (cupsDoAuthentication(http, "PUT", resource))
455*5e7646d2SAndroid Build Coastguard Worker {
456*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
457*5e7646d2SAndroid Build Coastguard Worker break;
458*5e7646d2SAndroid Build Coastguard Worker }
459*5e7646d2SAndroid Build Coastguard Worker
460*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
461*5e7646d2SAndroid Build Coastguard Worker {
462*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
463*5e7646d2SAndroid Build Coastguard Worker break;
464*5e7646d2SAndroid Build Coastguard Worker }
465*5e7646d2SAndroid Build Coastguard Worker
466*5e7646d2SAndroid Build Coastguard Worker continue;
467*5e7646d2SAndroid Build Coastguard Worker }
468*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SSL
469*5e7646d2SAndroid Build Coastguard Worker else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
470*5e7646d2SAndroid Build Coastguard Worker {
471*5e7646d2SAndroid Build Coastguard Worker /* Flush any error message... */
472*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
473*5e7646d2SAndroid Build Coastguard Worker
474*5e7646d2SAndroid Build Coastguard Worker /* Reconnect... */
475*5e7646d2SAndroid Build Coastguard Worker if (httpReconnect2(http, 30000, NULL))
476*5e7646d2SAndroid Build Coastguard Worker {
477*5e7646d2SAndroid Build Coastguard Worker status = HTTP_STATUS_ERROR;
478*5e7646d2SAndroid Build Coastguard Worker break;
479*5e7646d2SAndroid Build Coastguard Worker }
480*5e7646d2SAndroid Build Coastguard Worker
481*5e7646d2SAndroid Build Coastguard Worker /* Upgrade with encryption... */
482*5e7646d2SAndroid Build Coastguard Worker httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);
483*5e7646d2SAndroid Build Coastguard Worker
484*5e7646d2SAndroid Build Coastguard Worker /* Try again, this time with encryption enabled... */
485*5e7646d2SAndroid Build Coastguard Worker continue;
486*5e7646d2SAndroid Build Coastguard Worker }
487*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SSL */
488*5e7646d2SAndroid Build Coastguard Worker }
489*5e7646d2SAndroid Build Coastguard Worker while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED ||
490*5e7646d2SAndroid Build Coastguard Worker (status == HTTP_STATUS_ERROR && retries < 2));
491*5e7646d2SAndroid Build Coastguard Worker
492*5e7646d2SAndroid Build Coastguard Worker /*
493*5e7646d2SAndroid Build Coastguard Worker * See if we actually put the file or an error...
494*5e7646d2SAndroid Build Coastguard Worker */
495*5e7646d2SAndroid Build Coastguard Worker
496*5e7646d2SAndroid Build Coastguard Worker if (status != HTTP_STATUS_CREATED)
497*5e7646d2SAndroid Build Coastguard Worker {
498*5e7646d2SAndroid Build Coastguard Worker _cupsSetHTTPError(status);
499*5e7646d2SAndroid Build Coastguard Worker httpFlush(http);
500*5e7646d2SAndroid Build Coastguard Worker }
501*5e7646d2SAndroid Build Coastguard Worker
502*5e7646d2SAndroid Build Coastguard Worker DEBUG_printf(("1cupsPutFd: Returning %d...", status));
503*5e7646d2SAndroid Build Coastguard Worker
504*5e7646d2SAndroid Build Coastguard Worker return (status);
505*5e7646d2SAndroid Build Coastguard Worker }
506*5e7646d2SAndroid Build Coastguard Worker
507*5e7646d2SAndroid Build Coastguard Worker
508*5e7646d2SAndroid Build Coastguard Worker /*
509*5e7646d2SAndroid Build Coastguard Worker * 'cupsPutFile()' - Put a file on the server.
510*5e7646d2SAndroid Build Coastguard Worker *
511*5e7646d2SAndroid Build Coastguard Worker * This function returns @code HTTP_CREATED@ when the file is stored
512*5e7646d2SAndroid Build Coastguard Worker * successfully.
513*5e7646d2SAndroid Build Coastguard Worker *
514*5e7646d2SAndroid Build Coastguard Worker * @since CUPS 1.1.20/macOS 10.4@
515*5e7646d2SAndroid Build Coastguard Worker */
516*5e7646d2SAndroid Build Coastguard Worker
517*5e7646d2SAndroid Build Coastguard Worker http_status_t /* O - HTTP status */
cupsPutFile(http_t * http,const char * resource,const char * filename)518*5e7646d2SAndroid Build Coastguard Worker cupsPutFile(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
519*5e7646d2SAndroid Build Coastguard Worker const char *resource, /* I - Resource name */
520*5e7646d2SAndroid Build Coastguard Worker const char *filename) /* I - Filename */
521*5e7646d2SAndroid Build Coastguard Worker {
522*5e7646d2SAndroid Build Coastguard Worker int fd; /* File descriptor */
523*5e7646d2SAndroid Build Coastguard Worker http_status_t status; /* Status */
524*5e7646d2SAndroid Build Coastguard Worker
525*5e7646d2SAndroid Build Coastguard Worker
526*5e7646d2SAndroid Build Coastguard Worker /*
527*5e7646d2SAndroid Build Coastguard Worker * Range check input...
528*5e7646d2SAndroid Build Coastguard Worker */
529*5e7646d2SAndroid Build Coastguard Worker
530*5e7646d2SAndroid Build Coastguard Worker if (!http || !resource || !filename)
531*5e7646d2SAndroid Build Coastguard Worker {
532*5e7646d2SAndroid Build Coastguard Worker if (http)
533*5e7646d2SAndroid Build Coastguard Worker http->error = EINVAL;
534*5e7646d2SAndroid Build Coastguard Worker
535*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
536*5e7646d2SAndroid Build Coastguard Worker }
537*5e7646d2SAndroid Build Coastguard Worker
538*5e7646d2SAndroid Build Coastguard Worker /*
539*5e7646d2SAndroid Build Coastguard Worker * Open the local file...
540*5e7646d2SAndroid Build Coastguard Worker */
541*5e7646d2SAndroid Build Coastguard Worker
542*5e7646d2SAndroid Build Coastguard Worker if ((fd = open(filename, O_RDONLY)) < 0)
543*5e7646d2SAndroid Build Coastguard Worker {
544*5e7646d2SAndroid Build Coastguard Worker /*
545*5e7646d2SAndroid Build Coastguard Worker * Couldn't open the file!
546*5e7646d2SAndroid Build Coastguard Worker */
547*5e7646d2SAndroid Build Coastguard Worker
548*5e7646d2SAndroid Build Coastguard Worker http->error = errno;
549*5e7646d2SAndroid Build Coastguard Worker
550*5e7646d2SAndroid Build Coastguard Worker return (HTTP_STATUS_ERROR);
551*5e7646d2SAndroid Build Coastguard Worker }
552*5e7646d2SAndroid Build Coastguard Worker
553*5e7646d2SAndroid Build Coastguard Worker /*
554*5e7646d2SAndroid Build Coastguard Worker * Put the file...
555*5e7646d2SAndroid Build Coastguard Worker */
556*5e7646d2SAndroid Build Coastguard Worker
557*5e7646d2SAndroid Build Coastguard Worker status = cupsPutFd(http, resource, fd);
558*5e7646d2SAndroid Build Coastguard Worker
559*5e7646d2SAndroid Build Coastguard Worker close(fd);
560*5e7646d2SAndroid Build Coastguard Worker
561*5e7646d2SAndroid Build Coastguard Worker return (status);
562*5e7646d2SAndroid Build Coastguard Worker }
563