244 UiObject *ui; |
244 UiObject *ui; |
245 DavBrowser *browser; |
245 DavBrowser *browser; |
246 DavSession *sn; |
246 DavSession *sn; |
247 UiFileList files; |
247 UiFileList files; |
248 char *base_path; |
248 char *base_path; |
|
249 UiThreadpool *queue; |
|
250 |
|
251 size_t total_bytes; |
|
252 size_t total_files; |
|
253 size_t total_directories; |
|
254 size_t uploaded_bytes; |
|
255 size_t uploaded_files; |
|
256 size_t uploaded_directories; |
249 |
257 |
250 UiObject *dialog; |
258 UiObject *dialog; |
251 UiDouble *progress; |
259 UiDouble *progress; |
252 UiString *file_label; |
260 UiString *file_label; |
253 UiString *speed_label; |
261 UiString *speed_label; |
254 } DavFileUpload; |
262 } DavFileUpload; |
255 |
263 |
256 typedef struct DUFile { |
264 typedef struct DUFile { |
257 char *path; |
265 char *path; |
258 char *upload_path; |
266 char *upload_path; |
|
267 size_t bytes; |
|
268 DavBool isdirectory; |
|
269 DavFileUpload *upload; |
|
270 DavError error; |
259 } DUFile; |
271 } DUFile; |
260 |
272 |
261 static int jobthr_file_upload(void *data) { |
273 static double upload_progress(DavFileUpload *upload) { |
|
274 return ((double)upload->uploaded_bytes / (double)upload->total_bytes) * 100; |
|
275 } |
|
276 |
|
277 static int qthr_file_upload(void *data) { |
|
278 DUFile *f = data; |
|
279 DavFileUpload *upload = f->upload; |
|
280 DavSession *sn = upload->sn; |
|
281 |
|
282 FILE *in = sys_fopen(f->path, "rb"); |
|
283 if (!in) { |
|
284 // TODO: error msg |
|
285 return 0; |
|
286 } |
|
287 |
|
288 DavResource *res = dav_resource_new(sn, f->upload_path); |
|
289 dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); |
|
290 if (dav_store(res)) { |
|
291 f->error = sn->error; |
|
292 } |
|
293 dav_resource_free(res); |
|
294 |
|
295 fclose(in); |
|
296 |
|
297 return 0; |
|
298 } |
|
299 |
|
300 static void uithr_file_uploaded(UiEvent *event, void *data) { |
|
301 DUFile *file = data; |
|
302 DavFileUpload *upload = file->upload; |
|
303 |
|
304 upload->uploaded_files++; |
|
305 upload->uploaded_bytes += file->bytes; |
|
306 |
|
307 double progress = upload_progress(upload); |
|
308 ui_set(upload->progress, upload_progress(upload)); |
|
309 |
|
310 free(file->path); |
|
311 free(file->upload_path); |
|
312 } |
|
313 |
|
314 static int qthr_dir_upload(void *data) { |
|
315 DUFile *f = data; |
|
316 DavFileUpload *upload = f->upload; |
|
317 DavSession *sn = upload->sn; |
|
318 |
|
319 DavResource *res = dav_resource_new(sn, f->upload_path); |
|
320 res->iscollection = TRUE; |
|
321 |
|
322 if (dav_create(res)) { |
|
323 f->error = sn->error; |
|
324 } |
|
325 |
|
326 dav_resource_free(res); |
|
327 |
|
328 return 0; |
|
329 } |
|
330 |
|
331 static void uithr_dir_uploaded(UiEvent *event, void *data) { |
|
332 DUFile *file = data; |
|
333 DavFileUpload *upload = file->upload; |
|
334 |
|
335 upload->uploaded_directories++; |
|
336 |
|
337 free(file->path); |
|
338 free(file->upload_path); |
|
339 } |
|
340 |
|
341 static int qthr_upload_finished(void *data) { |
|
342 return 0; |
|
343 } |
|
344 |
|
345 static void uithr_upload_finished(UiEvent *event, void *data) { |
262 DavFileUpload *upload = data; |
346 DavFileUpload *upload = data; |
263 |
347 ui_threadpool_destroy(upload->queue); |
264 CxList *stack = cxLinkedListCreateSimple(sizeof(DUFile)); |
348 |
|
349 free(upload->base_path); |
|
350 dav_session_destroy(upload->sn); |
|
351 } |
|
352 |
|
353 static int jobthr_upload_scan(void *data) { |
|
354 DavFileUpload *upload = data; |
|
355 |
|
356 CxList *stack = cxLinkedListCreateSimple(CX_STORE_POINTERS); |
265 for (int i = 0; i < upload->files.nfiles; i++) { |
357 for (int i = 0; i < upload->files.nfiles; i++) { |
266 DUFile f; |
358 DUFile *f = malloc(sizeof(DUFile)); |
267 f.path = upload->files.files[i]; |
359 f->path = strdup(upload->files.files[i]); |
268 f.upload_path = util_path_file_name(f.path); |
360 f->upload_path = util_concat_path(upload->base_path, util_path_file_name(f->path)); |
269 cxListInsert(stack, 0, &f); |
361 f->isdirectory = FALSE; |
|
362 f->bytes = 0; |
|
363 f->upload = upload; |
|
364 f->error = 0; |
|
365 cxListInsert(stack, 0, f); |
270 } |
366 } |
271 |
367 |
272 while (stack->size > 0) { |
368 while (stack->size > 0) { |
273 DUFile *f = cxListAt(stack, 0); |
369 DUFile *f = cxListAt(stack, 0); |
274 |
370 |
275 char *path = util_concat_path(upload->base_path, f->upload_path); |
371 char *path = util_concat_path(upload->base_path, f->upload_path); |
276 DavResource *res = dav_resource_new(upload->sn, path); |
372 cxListRemove(stack, 0); |
277 |
373 |
278 SYS_STAT s; |
374 SYS_STAT s; |
279 if (!stat(f->path, &s)) { |
375 if (!stat(f->path, &s)) { |
280 if (S_ISDIR(s.st_mode)) { |
376 if (S_ISDIR(s.st_mode)) { |
281 res->iscollection = 1; |
377 f->isdirectory = TRUE; |
282 dav_create(res); |
378 upload->total_directories++; |
|
379 ui_threadpool_job(upload->queue, upload->ui, qthr_dir_upload, f, uithr_dir_uploaded, f); |
283 |
380 |
284 SYS_DIR dir = sys_opendir(f->path); |
381 SYS_DIR dir = sys_opendir(f->path); |
285 if (dir) { |
382 if (dir) { |
286 SysDirEnt *entry; |
383 SysDirEnt *entry; |
287 int nument = 0; |
384 int nument = 0; |
288 while((entry = sys_readdir(dir)) != NULL) { |
385 while((entry = sys_readdir(dir)) != NULL) { |
289 if(!strcmp(entry->name, ".") || !strcmp(entry->name, "..")) { |
386 if(!strcmp(entry->name, ".") || !strcmp(entry->name, "..")) { |
290 continue; |
387 continue; |
291 } |
388 } |
292 |
389 |
293 cxmutstr newpath = util_concat_sys_path(cx_str(f->path), cx_str(entry->name)); |
390 cxmutstr newpath = util_concat_sys_path(cx_str(f->path), cx_str(entry->name)); |
294 char *new_upload_path = util_concat_path(f->upload_path, entry->name); |
391 char *new_upload_path = util_concat_path(f->upload_path, entry->name); |
295 |
392 |
296 DUFile child; |
393 DUFile *child = malloc(sizeof(DUFile)); |
297 child.path = newpath.ptr; |
394 child->path = newpath.ptr; |
298 child.upload_path = new_upload_path; |
395 child->upload_path = new_upload_path; |
299 cxListAdd(stack, &child); |
396 child->isdirectory = FALSE; |
|
397 child->bytes = 0; |
|
398 child->upload = upload; |
|
399 child->error = 0; |
|
400 cxListAdd(stack, child); |
300 } |
401 } |
301 |
402 |
302 sys_closedir(dir); |
403 sys_closedir(dir); |
303 } |
404 } |
304 } else if (S_ISREG(s.st_mode)) { |
405 } else if (S_ISREG(s.st_mode)) { |
305 FILE *in = sys_fopen(f->path, "rb"); |
406 f->isdirectory = FALSE; |
306 if (in) { |
407 f->bytes = s.st_size; |
307 dav_set_content(res, in, (dav_read_func)fread, (dav_seek_func)fseek); |
408 upload->total_files++; |
308 //dav_set_content_length(res, s.st_size); |
409 upload->total_bytes += s.st_size; |
309 int err = dav_store(res); |
410 ui_threadpool_job(upload->queue, upload->ui, qthr_file_upload, f, uithr_file_uploaded, f); |
310 if (err) { |
|
311 // TODO: error |
|
312 |
|
313 } |
|
314 fclose(in); |
|
315 } |
|
316 } |
411 } |
317 } // TODO: else error msg |
412 } |
318 |
413 } // TODO: else error msg |
319 dav_resource_free(res); |
414 |
320 free(path); |
415 ui_threadpool_job(upload->queue, upload->ui, qthr_upload_finished, upload, uithr_upload_finished, upload); |
321 |
416 |
322 cxListRemove(stack, 0); |
417 ui_filelist_free(upload->files); |
323 } |
|
324 |
418 |
325 return 0; |
419 return 0; |
326 } |
420 } |
327 |
421 |
328 static void uithr_file_upload_finished(UiEvent *event, void *data) { |
422 static void uithr_upload_scan_finished(UiEvent *event, void *data) { |
329 DavFileUpload *upload = data; |
423 DavFileUpload *upload = data; |
330 } |
424 } |
331 |
425 |
332 |
426 |
333 void davbrowser_upload_files(UiObject *ui, DavBrowser *browser, UiFileList files) { |
427 void davbrowser_upload_files(UiObject *ui, DavBrowser *browser, UiFileList files) { |
339 // is done in a separate thread |
433 // is done in a separate thread |
340 DavSession *upload_session = dav_session_clone(browser->sn); |
434 DavSession *upload_session = dav_session_clone(browser->sn); |
341 |
435 |
342 // create upload obj, that contains all relevant data for the upload |
436 // create upload obj, that contains all relevant data for the upload |
343 DavFileUpload *upload = malloc(sizeof(DavFileUpload)); |
437 DavFileUpload *upload = malloc(sizeof(DavFileUpload)); |
|
438 memset(upload, 0, sizeof(DavFileUpload)); |
|
439 |
344 upload->ui = ui; |
440 upload->ui = ui; |
345 upload->browser = browser; |
441 upload->browser = browser; |
346 upload->sn = upload_session; |
442 upload->sn = upload_session; |
347 upload->files = files; |
443 upload->files = files; |
348 upload->base_path = strdup(browser->current->path); |
444 upload->base_path = strdup(browser->current->path); |
|
445 upload->queue = ui_threadpool_create(1); |
349 |
446 |
350 // create upload progress window |
447 // create upload progress window |
351 UiObject *dialog = ui_simple_window("Upload", upload); |
448 UiObject *dialog = ui_simple_window("Upload", upload); |
352 upload->dialog = dialog; |
449 upload->dialog = dialog; |
353 ui_window_size(dialog, 450, 120); |
450 ui_window_size(dialog, 450, 120); |