515 time_t result_lastmodified; |
515 time_t result_lastmodified; |
516 uint64_t result_contentlength; |
516 uint64_t result_contentlength; |
517 char *result_contenttype; |
517 char *result_contenttype; |
518 } DavPathOpResult; |
518 } DavPathOpResult; |
519 |
519 |
|
520 typedef struct DavRenameOp { |
|
521 UiObject *ui; |
|
522 DavBrowser *browser; |
|
523 |
|
524 // clone of the browser's DavSession |
|
525 DavSession *sn; |
|
526 char *path; |
|
527 char *newname; |
|
528 int result; |
|
529 char *errormsg; |
|
530 |
|
531 // browser->resources index |
|
532 size_t index; |
|
533 |
|
534 // browser->current ptr when the PathOp started |
|
535 // used in combination with collection_ctn to check if the browser list changed |
|
536 DavResource *collection; |
|
537 int64_t collection_ctn; |
|
538 } DavRenameOp; |
|
539 |
520 static int uithr_pathop_delete_error(void *data) { |
540 static int uithr_pathop_delete_error(void *data) { |
521 DavPathOpResult *result = data; |
541 DavPathOpResult *result = data; |
522 |
542 |
523 cxmutstr msg = cx_asprintf("Cannot delete resource %s", result->path); |
543 cxmutstr msg = cx_asprintf("Cannot delete resource %s", result->path); |
524 ui_dialog(result->ui, .title = "Error", .content = msg.ptr, .button1_label = "OK"); |
544 ui_dialog(result->ui, .title = "Error", .content = msg.ptr, .button1_label = "OK"); |
687 davbrowser_create_resource(ui, browser, name, TRUE); |
707 davbrowser_create_resource(ui, browser, name, TRUE); |
688 } |
708 } |
689 |
709 |
690 void davbrowser_newfile(UiObject *ui, DavBrowser *browser, const char *name) { |
710 void davbrowser_newfile(UiObject *ui, DavBrowser *browser, const char *name) { |
691 davbrowser_create_resource(ui, browser, name, FALSE); |
711 davbrowser_create_resource(ui, browser, name, FALSE); |
|
712 } |
|
713 |
|
714 |
|
715 |
|
716 |
|
717 static int jobthr_rename(void *data) { |
|
718 DavRenameOp *op = data; |
|
719 |
|
720 DavResource *res = dav_get(op->sn, op->path, NULL); |
|
721 if(!res) { |
|
722 fprintf(stderr, "Error: Cannot get resource %s\n", op->path); |
|
723 op->result = 1; |
|
724 return 0; |
|
725 } |
|
726 |
|
727 char *cryptoname = dav_get_string_property_ns(res, DAV_NS, "crypto-name"); |
|
728 char *cryptokey = dav_get_string_property_ns(res, DAV_NS, "crypto-key"); |
|
729 if(cryptoname && cryptokey) { |
|
730 // encrypted resource, the name is stored in the crypto-name property |
|
731 // these properties are only loaded if encryption is enabled for |
|
732 // this session |
|
733 DavKey *key = dav_context_get_key(op->sn->context, cryptokey); |
|
734 if(!key) { |
|
735 cxmutstr error = cx_asprintf_a(op->sn->mp->allocator, "Cannot rename resource: crypto key %s not found.", cryptokey); |
|
736 op->errormsg = error.ptr; |
|
737 op->result = 1; |
|
738 return 0; |
|
739 } |
|
740 |
|
741 // check if a resource with this name already exists |
|
742 char *parent = util_parent_path(res->path); |
|
743 char *newpath = util_concat_path(parent, op->newname); |
|
744 DavResource *testres = dav_resource_new(op->sn, newpath); |
|
745 if(dav_exists(testres)) { |
|
746 cxmutstr error = cx_asprintf_a(op->sn->mp->allocator, "A resource with the name %s already exists.", op->newname); |
|
747 op->errormsg = error.ptr; |
|
748 op->result = 1; |
|
749 } else { |
|
750 char *crname = aes_encrypt(op->newname, strlen(op->newname), key); |
|
751 dav_set_string_property_ns(res, DAV_NS, "crypto-name", crname); |
|
752 free(crname); |
|
753 if(dav_store(res)) { |
|
754 op->result = 1; |
|
755 } |
|
756 } |
|
757 free(parent); |
|
758 free(newpath); |
|
759 } else { |
|
760 // rename the resource by changing the url mapping with MOVE |
|
761 char *parent = util_parent_path(res->href); |
|
762 char *new_href = util_concat_path(parent, op->newname); |
|
763 char *dest = util_get_url(op->sn, new_href); |
|
764 free(parent); |
|
765 free(new_href); |
|
766 if(dav_moveto(res, dest, false)) { |
|
767 op->result = 1; |
|
768 } |
|
769 free(dest); |
|
770 } |
|
771 |
|
772 if(op->result && !op->errormsg) { |
|
773 cxmutstr error = cx_asprintf_a(op->sn->mp->allocator, "Error: %d", op->sn->error); |
|
774 op->errormsg = error.ptr; |
|
775 } |
|
776 |
|
777 return 0; |
|
778 } |
|
779 |
|
780 static void uithr_rename_finished(UiEvent *event, void *data) { |
|
781 DavRenameOp *op = data; |
|
782 |
|
783 if(!op->result) { |
|
784 // update name in the browser list |
|
785 if (op->browser->current == op->collection && op->browser->res_counter == op->collection_ctn) { |
|
786 DavResource *res = ui_list_get(op->browser->resources, op->index); |
|
787 |
|
788 char *parent = util_parent_path(res->path); |
|
789 char *newpath = util_concat_path(parent, op->newname); |
|
790 dav_session_free(res->session, res->path); |
|
791 dav_session_free(res->session, res->name); |
|
792 res->path = dav_session_strdup(res->session, newpath); |
|
793 res->name = dav_session_strdup(res->session, op->newname); |
|
794 op->browser->resources->update(op->browser->resources, 0); |
|
795 free(parent); |
|
796 free(newpath); |
|
797 } |
|
798 } else { |
|
799 // error |
|
800 ui_dialog(op->ui, .title = "Error", .content = op->errormsg, .closebutton_label = "OK"); |
|
801 } |
|
802 dav_session_destroy(op->sn); |
|
803 } |
|
804 |
|
805 static void action_resource_rename(UiEvent *event, void *data) { |
|
806 DavRenameOp *op = data; |
|
807 if(event->intval == 1) { |
|
808 char *newname = event->eventdata; |
|
809 if(!newname || strlen(newname) == 0) { |
|
810 ui_dialog(op->ui, .title = "Error", .content = "No name specified", .closebutton_label = "OK"); |
|
811 dav_session_destroy(op->sn); |
|
812 return; |
|
813 } |
|
814 |
|
815 char *s = strchr(newname, '/'); |
|
816 if(s) { |
|
817 ui_dialog(op->ui, .title = "Error", .content = "Character '/' is not allowed", .closebutton_label = "OK"); |
|
818 dav_session_destroy(op->sn); |
|
819 return; |
|
820 } |
|
821 |
|
822 op->newname = dav_session_strdup(op->sn, newname); |
|
823 |
|
824 ui_job(op->ui, jobthr_rename, op, uithr_rename_finished, op); |
|
825 return; |
|
826 } |
|
827 dav_session_destroy(op->sn); |
|
828 } |
|
829 |
|
830 void davbrowser_rename(UiObject *ui, DavBrowser *browser, UiListSelection selection) { |
|
831 DavSession *sn = dav_session_clone(browser->sn); |
|
832 |
|
833 DavResource *res = ui_list_get(browser->resources, selection.rows[0]); |
|
834 |
|
835 DavRenameOp *rename = dav_session_malloc(sn, sizeof(DavRenameOp)); |
|
836 memset(rename, 0, sizeof(DavRenameOp)); |
|
837 rename->browser = browser; |
|
838 rename->ui = ui; |
|
839 rename->sn = sn; |
|
840 rename->path = dav_session_strdup(sn, res->path); |
|
841 rename->index = selection.rows[0]; |
|
842 |
|
843 rename->collection = browser->current; |
|
844 rename->collection_ctn = browser->res_counter; |
|
845 |
|
846 ui_dialog(ui, |
|
847 .title = "Rename", |
|
848 .content = res->name, |
|
849 .input = TRUE, |
|
850 .input_value = res->name, |
|
851 .result = action_resource_rename, |
|
852 .resultdata = rename, |
|
853 .button1_label = "Rename", |
|
854 .closebutton_label = "Cancel"); |
692 } |
855 } |
693 |
856 |
694 |
857 |
695 |
858 |
696 DavResourceViewer* dav_resourceviewer_create(DavSession *sn, const char *path, DavResourceViewType type) { |
859 DavResourceViewer* dav_resourceviewer_create(DavSession *sn, const char *path, DavResourceViewType type) { |