1 /*
2 ** @(#) $Id$
3 **
4 ** W3C Web Commander can be found at "http://www.w3.org/WinCom/"
5 **
6 ** Copyright � 1995-1998 World Wide Web Consortium, (Massachusetts
7 ** Institute of Technology, Institut National de Recherche en
8 ** Informatique et en Automatique, Keio University). All Rights
9 ** Reserved. This program is distributed under the W3C's Software
10 ** Intellectual Property License. This program is distributed in the hope
11 ** that it will be useful, but WITHOUT ANY WARRANTY; without even the
12 ** implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
13 ** PURPOSE. See W3C License http://www.w3.org/Consortium/Legal/ for more
14 ** details.
15 **
16 ** Request.cpp: implementation of the CRequest class.
17 */
18
19 #include "stdafx.h"
20 #include "WinCom.h"
21 #include "Request.h"
22 #include "VersionConflict.h"
23
24 // From libwww
25 #include "WWWLib.h" /* Global Library Include file */
26 #include "WWWApp.h"
27 #include "WWWFile.h"
28
29 #ifdef _DEBUG
30 #undef THIS_FILE
31 static char THIS_FILE[]=__FILE__;
32 #define new DEBUG_NEW
33 #endif
34
35 #define DEF_LAST_SEGMENT "index"
36
37 /////////////////////////////////////////////////////////////////////////////
38 // Libwww filters
39
40 /*
41 ** Request termination handler
42 */
terminate_handler(HTRequest * request,HTResponse * response,void * param,int status)43 PRIVATE int terminate_handler (HTRequest * request, HTResponse * response,
44 void * param, int status)
45 {
46 CRequest * req = (CRequest *) HTRequest_context(request);
47
48 req->Cleanup();
49
50 delete req;
51
52 return HT_OK;
53 }
54
55 /*
56 ** 412 "Precondition failed" handler
57 */
precondition_handler(HTRequest * request,HTResponse * response,void * param,int status)58 PRIVATE int precondition_handler (HTRequest * request, HTResponse * response,
59 void * param, int status)
60 {
61 CRequest * req = (CRequest *) HTRequest_context(request);
62 CVersionConflict conflict;
63
64 req->Cleanup();
65
66 if (conflict.DoModal() == IDOK) {
67
68 if (conflict.m_versionResolution == 0) {
69 HTAnchor * source = req->Source();
70 HTAnchor * dest = req->Destination();
71 CRequest * new_req = new CRequest(req->m_pDoc);
72 delete req;
73
74 /* Start a new PUT request without preconditions */
75 new_req->PutDocument(source, dest, HT_NO_MATCH);
76
77 /* Stop here */
78 return HT_ERROR;
79
80 } else if (conflict.m_versionResolution == 1) {
81 HTAnchor * address = req->Source();
82 CRequest * new_req = new CRequest(req->m_pDoc);
83 delete req;
84
85 /* Start a new GET request */
86 new_req->GetDocument(address, 2);
87
88 /* Stop here */
89 return HT_ERROR;
90
91 } else
92 return HT_OK; /* Just finish the request */
93
94 }
95 return HT_OK;
96 }
97
98 /*
99 ** Request HEAD checker filter
100 */
check_handler(HTRequest * request,HTResponse * response,void * param,int status)101 PRIVATE int check_handler (HTRequest * request, HTResponse * response,
102 void * param, int status)
103 {
104 CRequest * req = (CRequest *) HTRequest_context(request);
105 CVersionConflict conflict;
106
107 req->Cleanup();
108
109 /*
110 ** If head request showed that the document doesn't exist
111 ** then just go ahead and PUT it. Otherwise ask for help
112 */
113 if (status==HT_ERROR || status==HT_INTERRUPTED || status==HT_TIMEOUT) {
114 delete req;
115 return HT_ERROR;
116 } else if (status==HT_NO_ACCESS || status==HT_NO_PROXY_ACCESS) {
117 delete req;
118 return HT_ERROR;
119 } else if (abs(status)/100!=2) {
120 HTAnchor * source = req->Source();
121 HTAnchor * dest = req->Destination();
122 CRequest * new_req = new CRequest(req->m_pDoc);
123 delete req;
124
125 /* Start a new PUT request with a "if-none-match *" precondition */
126 new_req->PutDocument(source, dest, HT_DONT_MATCH_ANY);
127
128 } else if (conflict.DoModal() == IDOK) {
129
130 if (conflict.m_versionResolution == 0) {
131 HTAnchor * source = req->Source();
132 HTAnchor * dest = req->Destination();
133 CRequest * new_req = new CRequest(req->m_pDoc);
134 delete req;
135
136 /* Start a new PUT request without preconditions */
137 new_req->PutDocument(source, dest, HT_NO_MATCH);
138
139 } else if (conflict.m_versionResolution == 1) {
140 HTAnchor * address = req->Source();
141 CRequest * new_req = new CRequest(req->m_pDoc);
142 delete req;
143
144 /* Start a new GET request */
145 new_req->GetDocument(address, 2);
146 }
147 }
148 return HT_ERROR;
149 }
150
151 //////////////////////////////////////////////////////////////////////
152 // Construction/Destruction
153 //////////////////////////////////////////////////////////////////////
154
IMPLEMENT_DYNCREATE(CRequest,CObject)155 IMPLEMENT_DYNCREATE(CRequest, CObject)
156
157 CRequest::CRequest(CWinComDoc * doc)
158 {
159 ASSERT(doc != NULL);
160 m_pDoc = doc;
161
162 m_pHTRequest = NULL;
163 m_pSource = NULL;
164 m_pDestination = NULL;
165 m_file = NULL;
166
167 // @@@ADD TO DOC LIST@@@
168 }
169
~CRequest()170 CRequest::~CRequest()
171 {
172 // @@@REMOVE FROM DOC LIST@@@
173 }
174
175 /////////////////////////////////////////////////////////////////////////////
176 // CWinComDoc commands
177
SetCacheValidation(int mode)178 BOOL CRequest::SetCacheValidation(int mode)
179 {
180 ASSERT(m_pHTRequest != NULL);
181 HTReload reload = HT_CACHE_OK;
182 switch (mode) {
183 case 0:
184 reload = HT_CACHE_OK;
185 break;
186 case 1:
187 reload = HT_CACHE_VALIDATE;
188 break;
189 case 2:
190 reload = HT_CACHE_END_VALIDATE;
191 break;
192 case 3:
193 reload = HT_CACHE_FLUSH;
194 break;
195 default:
196 reload = HT_CACHE_OK;
197 }
198
199 // Set the cache validation mode for this request
200 HTRequest_setReloadMode(m_pHTRequest, reload);
201
202 return TRUE;
203 }
204
GetDocument(HTAnchor * address,int cacheValidation)205 int CRequest::GetDocument (HTAnchor * address, int cacheValidation)
206 {
207 char filebuf[1024];
208 ASSERT(address != NULL);
209 char * uri = HTAnchor_address(address);
210
211 m_pSource = address;
212
213 CWinComApp * pApp = (CWinComApp *) AfxGetApp();
214 ASSERT(pApp != NULL);
215
216 CFileDialog fd(FALSE);
217
218 /* Find the start filename */
219 {
220 char * name = NULL;
221 char * suffix = HTBind_getSuffix(HTAnchor_parent(address));
222 char * uri_path = NULL;
223 if (uri && (uri_path = HTParse(uri, "", PARSE_PATH|PARSE_PUNCTUATION))) {
224 char * last_segment = strrchr(uri_path, '/');
225 if (last_segment && *(last_segment+1)) {
226 StrAllocMCopy(&name, ++last_segment, NULL);
227 } else {
228 StrAllocMCopy(&name, DEF_LAST_SEGMENT,
229 suffix ? suffix : "", NULL);
230 }
231 }
232
233 strcpy(filebuf, name);
234 fd.m_ofn.lpstrFile = filebuf;
235
236 HT_FREE(name);
237 HT_FREE(suffix);
238 }
239
240 /* Find the start folder */
241 fd.m_ofn.lpstrInitialDir = pApp->GetIniCWD();
242
243 if (fd.DoModal() == IDOK) {
244
245 m_saveAs = fd.GetPathName();
246
247 // Set the initial dir for next time
248 CString path = m_saveAs;
249 int idx = path.ReverseFind('\\');
250 if (idx != -1) path.GetBufferSetLength(idx+1);
251 pApp->SetIniCWD(path);
252
253 /* Create a new libwww request object */
254 m_pHTRequest = HTRequest_new();
255
256 /* Set the context so that we can find it again */
257 HTRequest_setContext(m_pHTRequest, this);
258
259 /* Terminating filters */
260 InitializeFilters();
261
262 /* Should we do cache validation? */
263 SetCacheValidation(cacheValidation);
264
265 /* Progress bar */
266 m_pProgress = new CProgress(this);
267 m_pProgress->Create(IDD_PROGRESS);
268 m_pProgress->ShowWindow(SW_SHOW);
269
270 /* Start the GET */
271 if (HTLoadToFile (uri, m_pHTRequest, m_saveAs) == NO) {
272 HT_FREE(uri);
273 return -1;
274 }
275
276 HT_FREE(uri);
277 return 0;
278 }
279
280 HT_FREE(uri);
281 return -1;
282 }
283
HeadDocument(HTAnchor * address,int cacheValidation)284 int CRequest::HeadDocument (HTAnchor * address, int cacheValidation)
285 {
286 ASSERT(address != NULL);
287
288 m_pSource = address;
289
290 /* Create a new libwww request object */
291 m_pHTRequest = HTRequest_new();
292
293 /* Set the context so that we can find it again */
294 HTRequest_setContext(m_pHTRequest, this);
295
296 /* Should we do cache validation? */
297 SetCacheValidation(cacheValidation);
298
299 /* Terminating filters */
300 InitializeFilters();
301
302 /* Progress bar */
303 m_pProgress = new CProgress(this);
304 m_pProgress->Create(IDD_PROGRESS);
305 m_pProgress->ShowWindow(SW_SHOW);
306
307 /* Start the HEAD */
308 if (HTHeadAnchor(address, m_pHTRequest) == NO) {
309 return -1;
310 }
311 return 0;
312 }
313
DeleteDocument(HTAnchor * address,HTPreconditions preconditions)314 int CRequest::DeleteDocument (HTAnchor * address, HTPreconditions preconditions)
315 {
316 ASSERT(address != NULL);
317
318 m_pSource = address;
319
320 /* Create a new libwww request object */
321 m_pHTRequest = HTRequest_new();
322
323 /* Set the context so that we can find it again */
324 HTRequest_setContext(m_pHTRequest, this);
325
326 /* Should we use preconditions? */
327 HTRequest_setPreconditions(m_pHTRequest, preconditions);
328
329 /* Terminating filters */
330 InitializeFilters();
331
332 /* Progress bar */
333 m_pProgress = new CProgress(this);
334 m_pProgress->Create(IDD_PROGRESS);
335 m_pProgress->ShowWindow(SW_SHOW);
336
337 /* Start the HEAD */
338 if (HTDeleteAnchor(address, m_pHTRequest) == NO) {
339 return -1;
340 }
341 return 0;
342 }
343
PutDocument(HTAnchor * source,HTAnchor * destination,HTPreconditions preconditions)344 int CRequest::PutDocument (HTAnchor * source,
345 HTAnchor * destination,
346 HTPreconditions preconditions)
347 {
348 ASSERT(source != NULL);
349 ASSERT(destination != NULL);
350
351 m_pSource = source;
352 m_pDestination = destination;
353
354 /* Create a new libwww request object */
355 m_pHTRequest = HTRequest_new();
356
357 /* Set the context so that we can find it again */
358 HTRequest_setContext(m_pHTRequest, this);
359
360 /* Should we use preconditions? */
361 HTRequest_setPreconditions(m_pHTRequest, preconditions);
362
363 /* Terminating filters */
364 InitializeFilters();
365
366 /* Progress bar */
367 m_pProgress = new CProgress(this);
368 m_pProgress->Create(IDD_PROGRESS);
369 m_pProgress->ShowWindow(SW_SHOW);
370
371 /* Start the PUT */
372 if (HTPutDocumentAnchor(HTAnchor_parent(source), destination, m_pHTRequest) != YES) {
373 return -1;
374 }
375 return 0;
376 }
377
PutDocumentWithPrecheck(HTAnchor * source,HTAnchor * destination)378 int CRequest::PutDocumentWithPrecheck (HTAnchor * source,
379 HTAnchor * destination)
380 {
381 ASSERT(source != NULL);
382 ASSERT(destination != NULL);
383
384 m_pSource = source;
385 m_pDestination = destination;
386
387 /* Create a new libwww request object */
388 m_pHTRequest = HTRequest_new();
389
390 /* Only use authentication and check AFTER filters */
391 HTRequest_addAfter(m_pHTRequest, HTAuthFilter, "http://*", NULL, HT_NO_ACCESS, HT_FILTER_MIDDLE, YES);
392 HTRequest_addAfter(m_pHTRequest, HTAuthFilter, "http://*", NULL, HT_REAUTH, HT_FILTER_MIDDLE, YES);
393 HTRequest_addAfter(m_pHTRequest, HTUseProxyFilter, "http://*", NULL, HT_USE_PROXY, HT_FILTER_MIDDLE, YES);
394 HTRequest_addAfter(m_pHTRequest, check_handler, NULL, NULL, HT_ALL, HT_FILTER_MIDDLE, YES);
395
396 /* Set the context so that we can find it again */
397 HTRequest_setContext(m_pHTRequest, this);
398
399 /* Set cache validation */
400 SetCacheValidation(2);
401
402 /* Progress bar */
403 m_pProgress = new CProgress(this);
404 m_pProgress->Create(IDD_PROGRESS);
405 m_pProgress->ShowWindow(SW_SHOW);
406
407 /* Start the HEAD */
408 if (HTHeadAnchor(destination, m_pHTRequest) == NO) {
409 return -1;
410 }
411 return 0;
412 }
413
Cancel()414 int CRequest::Cancel()
415 {
416 if (m_pHTRequest) HTRequest_kill(m_pHTRequest);
417 if (m_pProgress) m_pProgress = NULL;
418 return 0;
419 }
420
Cleanup()421 BOOL CRequest::Cleanup()
422 {
423 if (m_file) {
424 fclose(m_file);
425 m_file = NULL;
426 }
427 if (m_pProgress) {
428 m_pProgress->DestroyWindow();
429 m_pProgress = NULL;
430 }
431 return TRUE;
432 }
433
Source()434 HTAnchor * CRequest::Source()
435 {
436 return m_pSource;
437 }
438
Destination()439 HTAnchor * CRequest::Destination()
440 {
441 return m_pDestination;
442 }
443
InitializeFilters()444 BOOL CRequest::InitializeFilters()
445 {
446 static BOOL initialized = NO;
447 if (initialized == NO) {
448
449 /* Add our own after filter to handle 412 precondition failed */
450 HTNet_addAfter(precondition_handler, NULL, NULL, HT_PRECONDITION_FAILED, HT_FILTER_MIDDLE);
451
452 /* Add our own after filter to clecn up */
453 HTNet_addAfter(terminate_handler, NULL, NULL, HT_ALL, HT_FILTER_LAST);
454
455 initialized = YES;
456
457 return TRUE;
458 }
459 return FALSE;
460 }
461
GetProgressBar()462 CProgressCtrl * CRequest::GetProgressBar()
463 {
464 return &(m_pProgress->m_progress);
465 }
466
467