@sync-in/server 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +3 -3
- package/package.json +14 -14
- package/server/applications/files/services/files-manager.service.js +11 -2
- package/server/applications/files/services/files-manager.service.js.map +1 -1
- package/server/applications/files/utils/send-file.js +1 -1
- package/server/applications/files/utils/send-file.js.map +1 -1
- package/server/applications/sync/services/sync-manager.service.js +1 -1
- package/server/applications/sync/services/sync-manager.service.js.map +1 -1
- package/server/applications/webdav/services/webdav-methods.service.js +28 -28
- package/server/applications/webdav/services/webdav-methods.service.js.map +1 -1
- package/static/3rdpartylicenses.txt +85 -85
- package/static/assets/codemirror/mode/gas/gas.js +2 -0
- package/static/chunk-2OSA27SE.js +1 -0
- package/static/chunk-2PQGH3LQ.js +1 -0
- package/static/chunk-2QNFUN7G.js +1 -0
- package/static/chunk-3UFSZ24R.js +1 -0
- package/static/chunk-3XDVB3TW.js +1 -0
- package/static/chunk-4RF354LU.js +1 -0
- package/static/chunk-55WOZ7P6.js +4 -0
- package/static/chunk-5SYLS7WR.js +1 -0
- package/static/chunk-6HV65OKG.js +1 -0
- package/static/chunk-7XBZXSHI.js +1 -0
- package/static/chunk-AS7H5UIO.js +1 -0
- package/static/chunk-BOIXDTUT.js +4 -0
- package/static/chunk-ESSY62VJ.js +1 -0
- package/static/chunk-GLAK4VQT.js +1 -0
- package/static/chunk-GW5AVRYT.js +1 -0
- package/static/chunk-HPRC4PXX.js +1 -0
- package/static/chunk-J6YSVODR.js +1 -0
- package/static/chunk-JQOMI5VI.js +560 -0
- package/static/chunk-MLLPT7BU.js +1 -0
- package/static/chunk-MTBJHA2L.js +1 -0
- package/static/chunk-OWYD7F64.js +1 -0
- package/static/chunk-Q35EEVWP.js +1 -0
- package/static/chunk-Q7LN54AP.js +1 -0
- package/static/chunk-QKELW3MH.js +1 -0
- package/static/chunk-RTRJ3KFH.js +1 -0
- package/static/chunk-SOYI5P5A.js +7 -0
- package/static/{chunk-E27KCFP6.js → chunk-VCXIQZT4.js} +3 -3
- package/static/chunk-W4LKCEBR.js +1 -0
- package/static/chunk-WWKXW4MM.js +24 -0
- package/static/chunk-X2BMM3NY.js +1 -0
- package/static/chunk-X4CIBLP6.js +1 -0
- package/static/chunk-XQFA4DLU.js +1 -0
- package/static/chunk-YQGJX5R7.js +1 -0
- package/static/chunk-ZEZVOO4G.js +1 -0
- package/static/chunk-ZJDBESQA.js +1 -0
- package/static/index.html +2 -2
- package/static/main-2GG5BCQL.js +10 -0
- package/static/{scripts-MQMRSPYD.js → scripts-263WP5VB.js} +2 -2
- package/static/{styles-TJJDSCD4.css → styles-3DONJ2Z4.css} +1 -1
- package/sync-in-server.js +12 -5
- package/static/assets/mimes/7zip.svg +0 -14
- package/static/assets/mimes/application-7zip.svg +0 -14
- package/static/assets/mimes/application-atom+xml.svg +0 -15
- package/static/assets/mimes/application-gzip.svg +0 -16
- package/static/assets/mimes/application-mathml+xml.svg +0 -188
- package/static/assets/mimes/application-mp4.svg +0 -18
- package/static/assets/mimes/application-msexcel.svg +0 -1
- package/static/assets/mimes/application-msword-template.svg +0 -1
- package/static/assets/mimes/application-pgp-encrypted.svg +0 -16
- package/static/assets/mimes/application-pgp-keys.svg +0 -16
- package/static/assets/mimes/application-pgp-signature.svg +0 -16
- package/static/assets/mimes/application-powerpoint.svg +0 -1
- package/static/assets/mimes/application-rdf+xml.svg +0 -14
- package/static/assets/mimes/application-rss+xml.svg +0 -15
- package/static/assets/mimes/application-rtf.svg +0 -14
- package/static/assets/mimes/application-text.svg +0 -14
- package/static/assets/mimes/application-vnd.ms-excel.sheet.binary.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-excel.sheet.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-excel.template.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-powerpoint.presentation.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-powerpoint.template.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-word.document.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-word.svg +0 -1
- package/static/assets/mimes/application-vnd.ms-word.template.macroenabled.12.svg +0 -1
- package/static/assets/mimes/application-vnd.mspowerpoint.svg +0 -1
- package/static/assets/mimes/application-vnd.oasis.opendocument.chart.svg +0 -1
- package/static/assets/mimes/application-vnd.oasis.opendocument.text-master.svg +0 -92
- package/static/assets/mimes/application-vnd.oasis.opendocument.text-web.svg +0 -18
- package/static/assets/mimes/application-vnd.openofficeorg.extension.svg +0 -59
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.presentationml.presentation.svg +0 -1
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.presentationml.slideshow.svg +0 -1
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.spreadsheetml.sheet.svg +0 -1
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.spreadsheetml.template.svg +0 -1
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.wordprocessingml.document.svg +0 -1
- package/static/assets/mimes/application-vnd.openxmlformats-officedocument.wordprocessingml.template.svg +0 -1
- package/static/assets/mimes/application-vnd.rn-realmedia.svg +0 -18
- package/static/assets/mimes/application-vnd.sun.xml.calc.svg +0 -1
- package/static/assets/mimes/application-vnd.sun.xml.writer-global.svg +0 -1
- package/static/assets/mimes/application-vnd.sun.xml.writer-template.svg +0 -1
- package/static/assets/mimes/application-vnd.sun.xml.writer.svg +0 -1
- package/static/assets/mimes/application-vnd.sun.xml.writer.template.svg +0 -14
- package/static/assets/mimes/application-wps-office.doc.svg +0 -1
- package/static/assets/mimes/application-wps-office.docx.svg +0 -1
- package/static/assets/mimes/application-wps-office.ppt.svg +0 -1
- package/static/assets/mimes/application-wps-office.pptx.svg +0 -1
- package/static/assets/mimes/application-wps-office.xls.svg +0 -1
- package/static/assets/mimes/application-wps-office.xlsx.svg +0 -1
- package/static/assets/mimes/application-x-7zip.svg +0 -14
- package/static/assets/mimes/application-x-ace.svg +0 -14
- package/static/assets/mimes/application-x-addon.svg +0 -59
- package/static/assets/mimes/application-x-ar.svg +0 -16
- package/static/assets/mimes/application-x-arc.svg +0 -14
- package/static/assets/mimes/application-x-archive.svg +0 -16
- package/static/assets/mimes/application-x-arj.svg +0 -14
- package/static/assets/mimes/application-x-audacity-project.svg +0 -24
- package/static/assets/mimes/application-x-bzdvi.svg +0 -14
- package/static/assets/mimes/application-x-bzip-compressed-tar.svg +0 -14
- package/static/assets/mimes/application-x-class-file.svg +0 -37
- package/static/assets/mimes/application-x-compress-tar.svg +0 -16
- package/static/assets/mimes/application-x-compress.svg +0 -16
- package/static/assets/mimes/application-x-compressed-tar.svg +0 -14
- package/static/assets/mimes/application-x-core.svg +0 -20
- package/static/assets/mimes/application-x-cpio.svg +0 -16
- package/static/assets/mimes/application-x-deb.svg +0 -14
- package/static/assets/mimes/application-x-designer.svg +0 -48
- package/static/assets/mimes/application-x-egon.svg +0 -12
- package/static/assets/mimes/application-x-extension-html.svg +0 -18
- package/static/assets/mimes/application-x-font-afm.svg +0 -14
- package/static/assets/mimes/application-x-font-snf.svg +0 -14
- package/static/assets/mimes/application-x-font-speedo.svg +0 -14
- package/static/assets/mimes/application-x-font-type1.svg +0 -14
- package/static/assets/mimes/application-x-gettext-translation.svg +0 -14
- package/static/assets/mimes/application-x-gnome-theme-package.svg +0 -109
- package/static/assets/mimes/application-x-gzdvi.svg +0 -16
- package/static/assets/mimes/application-x-gzip.svg +0 -16
- package/static/assets/mimes/application-x-httpd-php.svg +0 -18
- package/static/assets/mimes/application-x-iso9660-image.svg +0 -292
- package/static/assets/mimes/application-x-java-archive.svg +0 -16
- package/static/assets/mimes/application-x-jokosher.svg +0 -24
- package/static/assets/mimes/application-x-kcachegrind.svg +0 -273
- package/static/assets/mimes/application-x-kcsrc.svg +0 -109
- package/static/assets/mimes/application-x-keepass2.svg +0 -2
- package/static/assets/mimes/application-x-kgetlist.svg +0 -53
- package/static/assets/mimes/application-x-lha.svg +0 -14
- package/static/assets/mimes/application-x-lzma-compressed-tar.svg +0 -16
- package/static/assets/mimes/application-x-lzop.svg +0 -16
- package/static/assets/mimes/application-x-m4.svg +0 -14
- package/static/assets/mimes/application-x-matroska.svg +0 -18
- package/static/assets/mimes/application-x-mplayer2.svg +0 -18
- package/static/assets/mimes/application-x-ms-application.svg +0 -306
- package/static/assets/mimes/application-x-msdos-program.svg +0 -306
- package/static/assets/mimes/application-x-msdownload.svg +0 -306
- package/static/assets/mimes/application-x-msi.svg +0 -306
- package/static/assets/mimes/application-x-mswinurl.svg +0 -18
- package/static/assets/mimes/application-x-mswrite.svg +0 -1
- package/static/assets/mimes/application-x-object.svg +0 -273
- package/static/assets/mimes/application-x-ole-storage.svg +0 -273
- package/static/assets/mimes/application-x-pak.svg +0 -16
- package/static/assets/mimes/application-x-perl.svg +0 -15
- package/static/assets/mimes/application-x-php.svg +0 -18
- package/static/assets/mimes/application-x-python-bytecode.svg +0 -16
- package/static/assets/mimes/application-x-rar.svg +0 -14
- package/static/assets/mimes/application-x-rpm.svg +0 -14
- package/static/assets/mimes/application-x-ruby.svg +0 -22
- package/static/assets/mimes/application-x-sh.svg +0 -17
- package/static/assets/mimes/application-x-shared-library-la.svg +0 -62
- package/static/assets/mimes/application-x-shellscript.svg +0 -17
- package/static/assets/mimes/application-x-shockwave-flash.svg +0 -18
- package/static/assets/mimes/application-x-srt.svg +0 -210
- package/static/assets/mimes/application-x-tar.svg +0 -16
- package/static/assets/mimes/application-x-tarz.svg +0 -14
- package/static/assets/mimes/application-x-trash.svg +0 -14
- package/static/assets/mimes/application-x-tzo.svg +0 -14
- package/static/assets/mimes/application-x-wine-extension-pdd.svg +0 -14
- package/static/assets/mimes/application-x-zip.svg +0 -14
- package/static/assets/mimes/application-x-zoo.svg +0 -14
- package/static/assets/mimes/application-xhtml+xml.svg +0 -18
- package/static/assets/mimes/application-xml.svg +0 -18
- package/static/assets/mimes/application-xsd.svg +0 -18
- package/static/assets/mimes/application-xslt+xml.svg +0 -18
- package/static/assets/mimes/application-zip.svg +0 -14
- package/static/assets/mimes/applications-java.svg +0 -14
- package/static/assets/mimes/archive.svg +0 -16
- package/static/assets/mimes/ascii.svg +0 -14
- package/static/assets/mimes/audio-ac3.svg +0 -24
- package/static/assets/mimes/audio-flac.svg +0 -24
- package/static/assets/mimes/audio-mpeg.svg +0 -24
- package/static/assets/mimes/audio-vn.rn-realmedia.svg +0 -18
- package/static/assets/mimes/audio-vnd.rn-realvideo.svg +0 -18
- package/static/assets/mimes/audio-x-adpcm.svg +0 -24
- package/static/assets/mimes/audio-x-aiff.svg +0 -24
- package/static/assets/mimes/audio-x-flac+ogg.svg +0 -24
- package/static/assets/mimes/audio-x-flac.svg +0 -24
- package/static/assets/mimes/audio-x-it.svg +0 -24
- package/static/assets/mimes/audio-x-monkey.svg +0 -24
- package/static/assets/mimes/audio-x-mpegurl.svg +0 -24
- package/static/assets/mimes/audio-x-wav.svg +0 -24
- package/static/assets/mimes/audio-x-xi.svg +0 -24
- package/static/assets/mimes/audio-x-xm.svg +0 -24
- package/static/assets/mimes/binary.svg +0 -40
- package/static/assets/mimes/deb.svg +0 -14
- package/static/assets/mimes/divx.svg +0 -18
- package/static/assets/mimes/document.svg +0 -14
- package/static/assets/mimes/emblem-package.svg +0 -16
- package/static/assets/mimes/eps.svg +0 -24
- package/static/assets/mimes/exec.svg +0 -40
- package/static/assets/mimes/folder-tar.svg +0 -16
- package/static/assets/mimes/folder_tar.svg +0 -16
- package/static/assets/mimes/font-otf.svg +0 -14
- package/static/assets/mimes/font.svg +0 -14
- package/static/assets/mimes/font_bitmap.svg +0 -14
- package/static/assets/mimes/font_truetype.svg +0 -14
- package/static/assets/mimes/font_type1.svg +0 -14
- package/static/assets/mimes/fonts-package.svg +0 -16
- package/static/assets/mimes/gedit-plugin.svg +0 -59
- package/static/assets/mimes/gnome-exe-thumbnailer-generic-x.svg +0 -306
- package/static/assets/mimes/gnome-exe-thumbnailer-generic.svg +0 -306
- package/static/assets/mimes/gnome-exe-thumbnailer-template.svg +0 -306
- package/static/assets/mimes/gnome-fs-executable.svg +0 -40
- package/static/assets/mimes/gnome-mime-application-atom+xml.svg +0 -15
- package/static/assets/mimes/gnome-mime-application-msexcel.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-msword.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-ogg.svg +0 -24
- package/static/assets/mimes/gnome-mime-application-pdf.svg +0 -13
- package/static/assets/mimes/gnome-mime-application-postscript.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-powerpoint.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-rss+xml.svg +0 -15
- package/static/assets/mimes/gnome-mime-application-rtf.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-vnd.ms-excel.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.ms-powerpoint.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.ms-word.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.mspowerpoint.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.oasis.opendocument.formula.svg +0 -188
- package/static/assets/mimes/gnome-mime-application-vnd.oasis.opendocument.text-web.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-vnd.openxmlformats-officedocument.presentationml.presentation.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.openxmlformats-officedocument.presentationml.slideshow.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.openxmlformats-officedocument.spreadsheetml.sheet.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.openxmlformats-officedocument.wordprocessingml.document.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-vnd.rn-realmedia-secure.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-vnd.rn-realmedia-vbr.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-vnd.rn-realmedia.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-wps-office.doc.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-wps-office.docx.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-wps-office.ppt.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-wps-office.pptx.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-wps-office.xls.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-wps-office.xlsx.svg +0 -1
- package/static/assets/mimes/gnome-mime-application-x-7z-compressed.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-7zip.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-archive.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-arj.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-bittorrent.svg +0 -53
- package/static/assets/mimes/gnome-mime-application-x-bzip-compressed-tar.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-bzip-compressed.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-bzip.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-class-file.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-compress.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-compressed-tar.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-cpio-compressed.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-cpio.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-deb.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-designer.svg +0 -48
- package/static/assets/mimes/gnome-mime-application-x-executable.svg +0 -40
- package/static/assets/mimes/gnome-mime-application-x-font-afm.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-font-bdf.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-font-linux-psf.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-font-pcf.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-font-sunos-news.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-font-ttf.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-glade.svg +0 -48
- package/static/assets/mimes/gnome-mime-application-x-gnome-app-info.svg +0 -109
- package/static/assets/mimes/gnome-mime-application-x-gnome-theme-package.svg +0 -109
- package/static/assets/mimes/gnome-mime-application-x-gzip.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-gzpostscript.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-jar.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-java.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-killustrator.svg +0 -12
- package/static/assets/mimes/gnome-mime-application-x-lha.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-lhz.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-lzma-compressed-tar.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-lzma.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-ms-dos-executable.svg +0 -306
- package/static/assets/mimes/gnome-mime-application-x-perl.svg +0 -15
- package/static/assets/mimes/gnome-mime-application-x-php.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-x-python-bytecode.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-rar.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-rpm.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-x-ruby.svg +0 -22
- package/static/assets/mimes/gnome-mime-application-x-shellscript.svg +0 -17
- package/static/assets/mimes/gnome-mime-application-x-shockwave-flash.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-x-stuffit.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-tar.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-tarz.svg +0 -16
- package/static/assets/mimes/gnome-mime-application-x-tex.svg +0 -79
- package/static/assets/mimes/gnome-mime-application-x-theme.svg +0 -109
- package/static/assets/mimes/gnome-mime-application-x-zip.svg +0 -14
- package/static/assets/mimes/gnome-mime-application-xhtml+xml.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-xml.svg +0 -18
- package/static/assets/mimes/gnome-mime-application-zip.svg +0 -14
- package/static/assets/mimes/gnome-mime-application.svg +0 -40
- package/static/assets/mimes/gnome-mime-audio.svg +0 -24
- package/static/assets/mimes/gnome-mime-image-vnd.adobe.photoshop.svg +0 -14
- package/static/assets/mimes/gnome-mime-image-x-cmu-raster.svg +0 -12
- package/static/assets/mimes/gnome-mime-image-x-killustrator.svg +0 -12
- package/static/assets/mimes/gnome-mime-image-x-psd.svg +0 -14
- package/static/assets/mimes/gnome-mime-image-x-xpixmap.svg +0 -12
- package/static/assets/mimes/gnome-mime-image.svg +0 -12
- package/static/assets/mimes/gnome-mime-text-html.svg +0 -18
- package/static/assets/mimes/gnome-mime-text-install.svg +0 -20
- package/static/assets/mimes/gnome-mime-text-plain.svg +0 -14
- package/static/assets/mimes/gnome-mime-text-vnd.wap.wml.svg +0 -18
- package/static/assets/mimes/gnome-mime-text-x-changelog.svg +0 -208
- package/static/assets/mimes/gnome-mime-text-x-copying.svg +0 -17
- package/static/assets/mimes/gnome-mime-text-x-csh.svg +0 -17
- package/static/assets/mimes/gnome-mime-text-x-gtkrc.svg +0 -109
- package/static/assets/mimes/gnome-mime-text-x-install.svg +0 -17
- package/static/assets/mimes/gnome-mime-text-x-java-source.svg +0 -14
- package/static/assets/mimes/gnome-mime-text-x-java.svg +0 -14
- package/static/assets/mimes/gnome-mime-text-x-makefile.svg +0 -176
- package/static/assets/mimes/gnome-mime-text-x-opml+xml.svg +0 -15
- package/static/assets/mimes/gnome-mime-text-x-opml.svg +0 -15
- package/static/assets/mimes/gnome-mime-text-x-python.svg +0 -16
- package/static/assets/mimes/gnome-mime-text-x-readme.svg +0 -15
- package/static/assets/mimes/gnome-mime-text-x-sh.svg +0 -17
- package/static/assets/mimes/gnome-mime-text-x-zsh.svg +0 -17
- package/static/assets/mimes/gnome-mime-text.svg +0 -14
- package/static/assets/mimes/gnome-mime-video-x-ms-asf.svg +0 -18
- package/static/assets/mimes/gnome-mime-video-x-ms-wmv.svg +0 -18
- package/static/assets/mimes/gnome-mime-video.svg +0 -18
- package/static/assets/mimes/gnome-mime-x-font-afm.svg +0 -14
- package/static/assets/mimes/gnome-mime-x-install.svg +0 -20
- package/static/assets/mimes/gnome-package.svg +0 -16
- package/static/assets/mimes/html.svg +0 -18
- package/static/assets/mimes/image-gif.svg +0 -12
- package/static/assets/mimes/image-jpeg.svg +0 -12
- package/static/assets/mimes/image-png.svg +0 -12
- package/static/assets/mimes/image-svg+xml-compressed.svg +0 -12
- package/static/assets/mimes/image-svg+xml.svg +0 -12
- package/static/assets/mimes/image-vnd.adobe.photoshop.svg +0 -14
- package/static/assets/mimes/image-vnd.microsoft.icon.svg +0 -12
- package/static/assets/mimes/image-x-psdimage-x-psd.svg +0 -14
- package/static/assets/mimes/image-x-xfig.svg +0 -12
- package/static/assets/mimes/image.svg +0 -12
- package/static/assets/mimes/internet-feed.svg +0 -15
- package/static/assets/mimes/libpeas-plugin.svg +0 -59
- package/static/assets/mimes/libreoffice-database.svg +0 -155
- package/static/assets/mimes/libreoffice-extension.svg +0 -59
- package/static/assets/mimes/libreoffice-extensionn.svg +0 -59
- package/static/assets/mimes/libreoffice-formula.svg +0 -188
- package/static/assets/mimes/libreoffice-oasis-formula.svg +0 -188
- package/static/assets/mimes/libreoffice34-extension.svg +0 -59
- package/static/assets/mimes/media-audio.svg +0 -24
- package/static/assets/mimes/media-video.svg +0 -18
- package/static/assets/mimes/mime-ascii.svg +0 -14
- package/static/assets/mimes/mime_ascii.svg +0 -14
- package/static/assets/mimes/misc.svg +0 -14
- package/static/assets/mimes/multipart-encrypted.svg +0 -273
- package/static/assets/mimes/music.svg +0 -24
- package/static/assets/mimes/none.svg +0 -110
- package/static/assets/mimes/openofficeorg3-extension.svg +0 -59
- package/static/assets/mimes/package.svg +0 -16
- package/static/assets/mimes/package_editors.svg +0 -14
- package/static/assets/mimes/pdf.svg +0 -13
- package/static/assets/mimes/preferences-certificate.svg +0 -28
- package/static/assets/mimes/preferences-plugin.svg +0 -59
- package/static/assets/mimes/rar.svg +0 -14
- package/static/assets/mimes/raw.svg +0 -12
- package/static/assets/mimes/scii.svg +0 -14
- package/static/assets/mimes/shellscript.svg +0 -17
- package/static/assets/mimes/sound.svg +0 -24
- package/static/assets/mimes/stock_certificate.svg +0 -28
- package/static/assets/mimes/stock_new-formula.svg +0 -188
- package/static/assets/mimes/stock_new-html.svg +0 -18
- package/static/assets/mimes/stock_script.svg +0 -17
- package/static/assets/mimes/stock_scripts.svg +0 -17
- package/static/assets/mimes/tar.svg +0 -16
- package/static/assets/mimes/text-css.svg +0 -18
- package/static/assets/mimes/text-enriched.svg +0 -14
- package/static/assets/mimes/text-htmlh.svg +0 -18
- package/static/assets/mimes/text-javascript.svg +0 -6
- package/static/assets/mimes/text-mht.svg +0 -18
- package/static/assets/mimes/text-plain.svg +0 -14
- package/static/assets/mimes/text-x-bibtex.svg +0 -79
- package/static/assets/mimes/text-x-gtkrc.svg +0 -109
- package/static/assets/mimes/text-x-java-source.svg +0 -14
- package/static/assets/mimes/text-x-lua.svg +0 -14
- package/static/assets/mimes/text-x-nfo.svg +0 -14
- package/static/assets/mimes/text-x-opml+xml.svg +0 -15
- package/static/assets/mimes/text-x-opml.svg +0 -15
- package/static/assets/mimes/text-x-tex.svg +0 -79
- package/static/assets/mimes/text-x-vala.svg +0 -14
- package/static/assets/mimes/text-x.svg +0 -14
- package/static/assets/mimes/text-xmcd.svg +0 -358
- package/static/assets/mimes/text.svg +0 -14
- package/static/assets/mimes/text2.svg +0 -14
- package/static/assets/mimes/tgz.svg +0 -16
- package/static/assets/mimes/txt.svg +0 -14
- package/static/assets/mimes/txt2.svg +0 -14
- package/static/assets/mimes/uri-mms.svg +0 -18
- package/static/assets/mimes/uri-mmst.svg +0 -18
- package/static/assets/mimes/uri-mmsu.svg +0 -18
- package/static/assets/mimes/uri-pnm.svg +0 -18
- package/static/assets/mimes/uri-rtspt.svg +0 -18
- package/static/assets/mimes/uri-rtspu.svg +0 -18
- package/static/assets/mimes/video-quicktime.svg +0 -18
- package/static/assets/mimes/video-vivo.svg +0 -18
- package/static/assets/mimes/video-wavelet.svg +0 -18
- package/static/assets/mimes/video-webm.svg +0 -18
- package/static/assets/mimes/video-x-anim.svg +0 -18
- package/static/assets/mimes/video-x-flic.svg +0 -18
- package/static/assets/mimes/video-x-google-vlc-plugin.svg +0 -18
- package/static/assets/mimes/video-x-javafx.svg +0 -18
- package/static/assets/mimes/video-x-matroska.svg +0 -18
- package/static/assets/mimes/video-x-mng.svg +0 -18
- package/static/assets/mimes/video-x-ms-asf-plugin.svg +0 -18
- package/static/assets/mimes/video-x-ms-asf.svg +0 -18
- package/static/assets/mimes/video-x-ms-wmp.svg +0 -18
- package/static/assets/mimes/video-x-ms-wmv.svg +0 -18
- package/static/assets/mimes/video-x-nsv.svg +0 -18
- package/static/assets/mimes/video-x-sgi-movie.svg +0 -18
- package/static/assets/mimes/video-x-theora+ogg.svg +0 -18
- package/static/assets/mimes/video-x-wmv.svg +0 -18
- package/static/assets/mimes/video.svg +0 -18
- package/static/assets/mimes/www.svg +0 -18
- package/static/assets/mimes/x-kde-nsplugin-generated.svg +0 -59
- package/static/assets/mimes/zip.svg +0 -14
- package/static/chunk-2LIE3SKB.js +0 -7
- package/static/chunk-3BKYCF53.js +0 -1
- package/static/chunk-6CFIZHYI.js +0 -1
- package/static/chunk-7FVU676A.js +0 -4
- package/static/chunk-7RNZNYVF.js +0 -1
- package/static/chunk-7SJOQRBE.js +0 -1
- package/static/chunk-BS5LXHXU.js +0 -1
- package/static/chunk-CPHC7U34.js +0 -1
- package/static/chunk-DVHXFWN7.js +0 -1
- package/static/chunk-DYRV5R67.js +0 -1
- package/static/chunk-EWJD5G76.js +0 -1
- package/static/chunk-EYXC4W63.js +0 -24
- package/static/chunk-FPEGN42P.js +0 -564
- package/static/chunk-GAL4ENT6.js +0 -1
- package/static/chunk-GSVMWC5N.js +0 -1
- package/static/chunk-HNWPHW2W.js +0 -1
- package/static/chunk-IPGNGPWY.js +0 -1
- package/static/chunk-J5O3CY2H.js +0 -1
- package/static/chunk-JRVJIJB5.js +0 -1
- package/static/chunk-MAWDGVNC.js +0 -1
- package/static/chunk-N3QPDPBV.js +0 -1
- package/static/chunk-NSXFB3SX.js +0 -1
- package/static/chunk-OVO4W2GF.js +0 -1
- package/static/chunk-SOLCSMU7.js +0 -1
- package/static/chunk-SY5HMUMM.js +0 -1
- package/static/chunk-SZKZH4MJ.js +0 -1
- package/static/chunk-UGSGMP2I.js +0 -1
- package/static/chunk-ULTPIQL3.js +0 -1
- package/static/chunk-VBWPPICY.js +0 -1
- package/static/chunk-VFSSL4TI.js +0 -1
- package/static/chunk-WGSPBZVN.js +0 -1
- package/static/chunk-X6UFHF4Q.js +0 -1
- package/static/chunk-XBHT4AH5.js +0 -1
- package/static/chunk-ZYB4TLJM.js +0 -4
- package/static/main-EDITZWHO.js +0 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
|
|
2
|
+
## [1.3.4](https://github.com/Sync-in/server/compare/v1.3.3...v1.3.4) (2025-08-19)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Chores
|
|
6
|
+
|
|
7
|
+
* **ci:** remove husky prepare ([8e911ab](https://github.com/Sync-in/server/commit/8e911abf11e5a3265ea6afe30e26879452766a20))
|
|
8
|
+
|
|
9
|
+
## [1.3.3](https://github.com/Sync-in/server/compare/v1.3.2...v1.3.3) (2025-08-19)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* **backend:files:** correct archive name when downloading a folder ([1474949](https://github.com/Sync-in/server/commit/147494906e7a04f520195dfb747eb791daabfbc3))
|
|
15
|
+
* **backend:sync:** avoid "parent must exist" error when files are moved before destination folder creation during sync ([8c92535](https://github.com/Sync-in/server/commit/8c9253551aa1d90c7fe340b81e5f9b48c82b6fdf))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Chores
|
|
19
|
+
|
|
20
|
+
* **docker:** allow http2 in nginx directives ([4ad2ffb](https://github.com/Sync-in/server/commit/4ad2ffbfe12720af75aeac1d7ee7e383d73ad981))
|
|
21
|
+
* **frontend:** add missing video-mp4 mime type ([d210268](https://github.com/Sync-in/server/commit/d210268bc8cb5a5e61e0bbc24f431915b509b32d))
|
|
22
|
+
* **frontend:** bump to angular 20 ([363671a](https://github.com/Sync-in/server/commit/363671ac5e6ad6299477bf07f0bcffe1cff3e3f4))
|
|
23
|
+
* **npm-sync-in-server.js:** more verbose createUser function ([1ea155a](https://github.com/Sync-in/server/commit/1ea155a23f092312cb234758c59002bbe01458b2))
|
|
24
|
+
* **frontend:** update-angular-19-to-20 ([14f0397](https://github.com/Sync-in/server/commit/14f03973a77370f531bd1ed4c6c2052b76c15ea2))
|
|
25
|
+
* add Husky pre-commit hook for lint and test ([281e32d](https://github.com/Sync-in/server/commit/281e32df28e092b6ea0a57d94b6f8279ca67c4c1))
|
|
26
|
+
|
|
2
27
|
## [1.3.2](https://github.com/Sync-in/server/compare/v1.3.1...v1.3.2) (2025-08-08)
|
|
3
28
|
|
|
29
|
+
### Features
|
|
30
|
+
|
|
31
|
+
* **cli** add create-user command to manage user creation
|
|
32
|
+
|
|
33
|
+
|
|
4
34
|
## [1.3.1](https://github.com/Sync-in/server/compare/v1.3.0...v1.3.1) (2025-08-08)
|
|
5
35
|
|
|
6
36
|
|
package/README.md
CHANGED
|
@@ -14,9 +14,9 @@ _Welcome to the official Sync-in server repository!_
|
|
|
14
14
|
- 📦 [Deploy with NPM](https://sync-in.com/docs/setup-guide/npm)
|
|
15
15
|
|
|
16
16
|
<a href="#-license"><img src="https://img.shields.io/badge/Licence-AGPL%20v3.0-green.svg" alt="License"/></a>
|
|
17
|
-
<a href="https://discord.gg/qhJyzwaymT" target="_blank"><img src="https://img.shields.io/
|
|
18
|
-
<a href="https://www.npmjs.com/package/@sync-in/server" target="_blank"><img src="https://img.shields.io/
|
|
19
|
-
<a href="https://hub.docker.com/r/syncin/server" target="_blank"><img src="https://img.shields.io/docker/pulls/syncin/server
|
|
17
|
+
<a href="https://discord.gg/qhJyzwaymT" target="_blank"><img src="https://img.shields.io/discord/1391081837849346088?logo=discord&label=Discord" alt="Discord"/></a>
|
|
18
|
+
<a href="https://www.npmjs.com/package/@sync-in/server" target="_blank"><img src="https://img.shields.io/npm/d18m/@sync-in/server.svg?logo=npm&label=NPM%20Downloads&color=cb3837" alt="NPM"/></a>
|
|
19
|
+
<a href="https://hub.docker.com/r/syncin/server" target="_blank"><img src="https://img.shields.io/docker/pulls/syncin/server?logo=docker&label=Docker%20Hub%20Pulls" alt="Docker pulls"/></a>
|
|
20
20
|
|
|
21
21
|
The **Sync-in Server** is designed to run on your own infrastructure, it gives you **full control over your data** while offering a modern,
|
|
22
22
|
intuitive interface for both internal and external users.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sync-in/server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "The secure, open-source platform for file storage, sharing, collaboration, and sync",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Johan Legrand",
|
|
@@ -36,41 +36,41 @@
|
|
|
36
36
|
"@fastify/static": "8.2.0",
|
|
37
37
|
"@knaadh/nestjs-drizzle-mysql2": "1.2.0",
|
|
38
38
|
"@lukeed/ms": "2.0.2",
|
|
39
|
-
"@nestjs/axios": "4.0.
|
|
40
|
-
"@nestjs/common": "11.1.
|
|
39
|
+
"@nestjs/axios": "4.0.1",
|
|
40
|
+
"@nestjs/common": "11.1.6",
|
|
41
41
|
"@nestjs/config": "4.0.2",
|
|
42
|
-
"@nestjs/core": "11.1.
|
|
42
|
+
"@nestjs/core": "11.1.6",
|
|
43
43
|
"@nestjs/jwt": "11.0.0",
|
|
44
44
|
"@nestjs/passport": "11.0.5",
|
|
45
|
-
"@nestjs/platform-fastify": "11.1.
|
|
46
|
-
"@nestjs/platform-socket.io": "11.1.
|
|
45
|
+
"@nestjs/platform-fastify": "11.1.6",
|
|
46
|
+
"@nestjs/platform-socket.io": "11.1.6",
|
|
47
47
|
"@nestjs/schedule": "6.0.0",
|
|
48
|
-
"@nestjs/websockets": "11.1.
|
|
48
|
+
"@nestjs/websockets": "11.1.6",
|
|
49
49
|
"@socket.io/cluster-adapter": "0.2.2",
|
|
50
50
|
"@socket.io/redis-adapter": "8.3.0",
|
|
51
51
|
"archiver": "7.0.1",
|
|
52
52
|
"bcryptjs": "3.0.2",
|
|
53
|
-
"canvas": "3.
|
|
53
|
+
"canvas": "3.2.0",
|
|
54
54
|
"class-transformer": "0.5.1",
|
|
55
55
|
"class-validator": "0.14.2",
|
|
56
56
|
"deepmerge": "4.3.1",
|
|
57
57
|
"drizzle-kit": "0.31.4",
|
|
58
|
-
"drizzle-orm": "0.44.
|
|
58
|
+
"drizzle-orm": "0.44.4",
|
|
59
59
|
"fast-xml-parser": "5.2.5",
|
|
60
|
-
"fs-extra": "11.3.
|
|
60
|
+
"fs-extra": "11.3.1",
|
|
61
61
|
"html-to-text": "9.0.5",
|
|
62
62
|
"js-yaml": "4.1.0",
|
|
63
|
-
"ldapts": "8.0.
|
|
63
|
+
"ldapts": "8.0.9",
|
|
64
64
|
"mime-types": "3.0.1",
|
|
65
|
-
"mysql2": "3.14.
|
|
65
|
+
"mysql2": "3.14.3",
|
|
66
66
|
"nestjs-pino": "4.4.0",
|
|
67
67
|
"nodemailer": "7.0.5",
|
|
68
68
|
"passport-http": "0.3.0",
|
|
69
69
|
"passport-jwt": "4.0.1",
|
|
70
70
|
"passport-local": "1.0.0",
|
|
71
71
|
"passport": "0.7.0",
|
|
72
|
-
"pdfjs-dist": "5.
|
|
73
|
-
"pino-pretty": "13.
|
|
72
|
+
"pdfjs-dist": "5.4.54",
|
|
73
|
+
"pino-pretty": "13.1.1",
|
|
74
74
|
"redis": "4.7.1",
|
|
75
75
|
"sax": "1.4.1",
|
|
76
76
|
"socket.io": "4.8.1",
|
|
@@ -233,7 +233,7 @@ let FilesManager = class FilesManager {
|
|
|
233
233
|
});
|
|
234
234
|
await (0, _files1.makeDir)(space.realPath, recursive);
|
|
235
235
|
}
|
|
236
|
-
async copyMove(user, srcSpace, dstSpace, isMove, overwrite = false, dav) {
|
|
236
|
+
async copyMove(user, srcSpace, dstSpace, isMove, overwrite = false, mkdirDstParentPath = false, dav) {
|
|
237
237
|
// checks
|
|
238
238
|
if (!(0, _permissions.canAccessToSpace)(user, dstSpace)) {
|
|
239
239
|
this.logger.warn(`${this.copyMove.name} - is not allowed to access to this space repository : ${dstSpace.repository}`);
|
|
@@ -251,7 +251,16 @@ let FilesManager = class FilesManager {
|
|
|
251
251
|
throw new _fileerror.FileError(_common.HttpStatus.NOT_FOUND, 'Location not found');
|
|
252
252
|
}
|
|
253
253
|
if (!await (0, _files1.isPathExists)((0, _files1.dirName)(dstSpace.realPath))) {
|
|
254
|
-
|
|
254
|
+
if (mkdirDstParentPath) {
|
|
255
|
+
try {
|
|
256
|
+
await (0, _files1.makeDir)((0, _files1.dirName)(dstSpace.realPath), true);
|
|
257
|
+
} catch (e) {
|
|
258
|
+
this.logger.error(`${this.copyMove.name} - Cannot create parent directory for destination ${dstSpace.realPath} : ${e}`);
|
|
259
|
+
throw new _fileerror.FileError(_common.HttpStatus.INTERNAL_SERVER_ERROR, 'Cannot create parent directory for destination');
|
|
260
|
+
}
|
|
261
|
+
} else {
|
|
262
|
+
throw new _fileerror.FileError(_common.HttpStatus.CONFLICT, 'Parent must exists');
|
|
263
|
+
}
|
|
255
264
|
}
|
|
256
265
|
if (srcSpace.realPath === dstSpace.realPath) {
|
|
257
266
|
throw new _fileerror.FileError(_common.HttpStatus.FORBIDDEN, 'Cannot copy/move source onto itself');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport archiver, { Archiver, ArchiverError } from 'archiver'\nimport { AxiosResponse } from 'axios'\nimport { PNGStream } from 'canvas'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { pipeline } from 'node:stream/promises'\nimport { extract as extractTar } from 'tar'\nimport { FastifyAuthenticatedRequest } from '../../../authentication/interfaces/auth-request.interface'\nimport { generateThumbnail } from '../../../common/image'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { realTrashPathFromSpace } from '../../spaces/utils/paths'\nimport { canAccessToSpace, haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport { UserModel } from '../../users/models/user.model'\nimport { DEPTH, LOCK_DEPTH } from '../../webdav/constants/webdav'\nimport { tarGzExtension } from '../constants/compress'\nimport { COMPRESSION_EXTENSION, DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FILE_OPERATION } from '../constants/operations'\nimport { DOCUMENT_TYPE, SAMPLE_PATH_WITHOUT_EXT } from '../constants/samples'\nimport { CompressFileDto } from '../dto/file-operations.dto'\nimport { FileTaskEvent } from '../events/file-task-event'\nimport { FileDBProps } from '../interfaces/file-db-props.interface'\nimport { FileLock } from '../interfaces/file-lock.interface'\nimport { FileError } from '../models/file-error'\nimport { LockConflict } from '../models/file-lock-error'\nimport {\n checkFileName,\n copyFiles,\n createEmptyFile,\n dirName,\n dirSize,\n fileName,\n fileSize,\n getMimeType,\n isPathExists,\n isPathIsDir,\n makeDir,\n moveFiles,\n removeFiles,\n touchFile,\n uniqueDatedFilePath,\n uniqueFilePathFromDir,\n writeFromStream,\n writeFromStreamAndChecksum\n} from '../utils/files'\nimport { SendFile } from '../utils/send-file'\nimport { extractZip } from '../utils/unzip-file'\nimport { regExpPrivateIP } from '../utils/url-file'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesManager {\n /* Spaces permissions are checked in the space guard, except for the copy/move destination */\n private logger = new Logger(FilesManager.name)\n\n constructor(\n private readonly http: HttpService,\n private readonly filesQueries: FilesQueries,\n private readonly filesLockManager: FilesLockManager\n ) {}\n\n sendFileFromSpace(space: SpaceEnv, asAttachment = false, downloadName = ''): SendFile {\n return new SendFile(space.realPath, asAttachment, downloadName)\n }\n\n async saveStream(\n user: UserModel,\n space: SpaceEnv,\n req: FastifyAuthenticatedRequest,\n options: {\n checksumAlg: string\n tmpPath?: string\n }\n ): Promise<string>\n async saveStream(user: UserModel, space: SpaceEnv, req: FastifyAuthenticatedRequest, options?: any): Promise<boolean>\n async saveStream(\n user: UserModel,\n space: SpaceEnv,\n req: FastifyAuthenticatedRequest,\n options?: { dav?: { depth: LOCK_DEPTH; lockTokens: string[] }; checksumAlg?: string; tmpPath?: string }\n ): Promise<boolean | string> {\n // if tmpPath is used, we lock the final destination during the transfer\n // space.realPath is replaced by tmpPath (if allowed), if the move operation failed we remove the tmp file\n const fExists = await isPathExists(space.realPath)\n const fTmpExists = options?.tmpPath ? await isPathExists(options.tmpPath) : false\n if (fExists && req.method === HTTP_METHOD.POST) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'Resource already exists')\n }\n if (fExists && (await isPathIsDir(space.realPath))) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'The location is a directory')\n }\n if (options?.tmpPath) {\n // ensure tmpPath parent dir exists\n await makeDir(dirName(options.tmpPath), true)\n } else if (!(await isPathExists(dirName(space.realPath)))) {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n /* File Lock */\n let fileLock: FileLock | undefined\n if (options?.dav) {\n // check locks\n await this.filesLockManager.checkConflicts(space.dbFile, options?.dav?.depth || DEPTH.RESOURCE, {\n userId: user.id,\n lockTokens: options.dav?.lockTokens\n })\n } else {\n // create lock if there is no webdav context\n const [ok, lock] = await this.filesLockManager.create(user, space.dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(lock, 'Conflicting lock')\n }\n fileLock = lock\n }\n try {\n // check range\n let startRange = 0\n if ((fExists || fTmpExists) && req.headers['content-range']) {\n // with PUT method, some webdav clients use the `content-range` header,\n // which is normally reserved for a response to a request containing the `range` header.\n // However, for more compatibility let's accept it\n const match = /\\d+/.exec(req.headers['content-range'])\n if (!match.length) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Content-range : header is malformed')\n }\n startRange = parseInt(match[0], 10)\n const size = await fileSize(options?.tmpPath || space.realPath)\n if (startRange !== size) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Content-range : start offset does not match the current file size')\n }\n }\n // todo: check file in db to update\n // todo : versioning here\n let checksum: string\n if (options?.checksumAlg) {\n checksum = await writeFromStreamAndChecksum(options?.tmpPath || space.realPath, req.raw, startRange, options.checksumAlg)\n } else {\n await writeFromStream(options?.tmpPath || space.realPath, req.raw, startRange)\n }\n if (options?.tmpPath) {\n try {\n // ensure parent path exists\n await makeDir(path.dirname(space.realPath), true)\n // move the uploaded file to destination\n await moveFiles(options.tmpPath, space.realPath, true)\n } catch (e) {\n // cleanup tmp file\n await removeFiles(options.tmpPath)\n this.logger.error(`${this.saveStream.name} - unable to move ${options.tmpPath} -> ${space.realPath} : ${e}`)\n throw new FileError(HttpStatus.INTERNAL_SERVER_ERROR, 'Unable to move tmp file to dst file')\n }\n }\n if (options?.checksumAlg) {\n return checksum\n }\n return fExists\n } finally {\n if (fileLock) {\n try {\n await this.filesLockManager.removeLock(fileLock.key)\n } catch (e) {\n this.logger.warn(`Failed to remove lock ${fileLock.key}: ${e}`)\n }\n }\n }\n }\n\n async saveMultipart(user: UserModel, space: SpaceEnv, req: FastifySpaceRequest) {\n /* Accepted methods:\n POST: create new resource\n PUT: create or update new resource (even if parent path does not exist)\n */\n const realParentPath = dirName(space.realPath)\n\n if (req.method === HTTP_METHOD.POST) {\n if (await isPathExists(space.realPath)) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Resource already exists')\n }\n if (!(await isPathExists(realParentPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Parent must exists')\n }\n if (!(await isPathIsDir(realParentPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Parent must be a directory')\n }\n }\n\n const basePath = realParentPath + path.sep\n\n for await (const part of req.files()) {\n // part.filename may contain a path like foo/bar.txt.\n const dstFile = path.resolve(basePath, part.filename)\n // prevent path traversal\n if (!dstFile.startsWith(basePath)) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Location is not allowed')\n }\n // make dir in space\n const dstDir = dirName(dstFile)\n if (!(await isPathExists(dstDir))) {\n await makeDir(dstDir, true)\n }\n // create lock\n const dbFile = { ...space.dbFile, path: path.join(dirName(space.dbFile.path), part.filename) }\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) throw new LockConflict(fileLock, 'Conflicting lock')\n // do\n try {\n await pipeline(part.file, fs.createWriteStream(dstFile, { highWaterMark: DEFAULT_HIGH_WATER_MARK }))\n } finally {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n }\n\n async touch(user: UserModel, space: SpaceEnv, mtime: number, checkLocks = true): Promise<void> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (checkLocks) {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id })\n }\n // todo: update mtime in last files ( & in db file ?)\n await touchFile(space.realPath, mtime)\n }\n\n async mkFile(user: UserModel, space: SpaceEnv, overwrite = false, checkLocks = true, checkDocument = false): Promise<void> {\n checkFileName(space.realPath)\n if (!overwrite && (await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Resource already exists')\n }\n if (checkLocks) {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id })\n }\n // use sample documents when possible\n const fileExtension = path.extname(space.realPath)\n if (checkDocument && fileExtension !== '.txt' && Object.values(DOCUMENT_TYPE).indexOf(fileExtension) > -1) {\n const srcSample = path.join(__dirname, `${SAMPLE_PATH_WITHOUT_EXT}${fileExtension}`)\n await copyFiles(srcSample, space.realPath)\n return touchFile(space.realPath)\n } else {\n return createEmptyFile(space.realPath)\n }\n }\n\n async mkDir(user: UserModel, space: SpaceEnv, recursive = false, dav?: { depth: LOCK_DEPTH; lockTokens: string[] }): Promise<void> {\n checkFileName(space.realPath)\n if (!recursive) {\n if (await isPathExists(space.realPath)) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'Resource already exists')\n } else if (!(await isPathExists(dirName(space.realPath)))) {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n }\n await this.filesLockManager.checkConflicts(space.dbFile, dav?.depth || DEPTH.RESOURCE, { userId: user.id, lockTokens: dav?.lockTokens })\n await makeDir(space.realPath, recursive)\n }\n\n async copyMove(\n user: UserModel,\n srcSpace: SpaceEnv,\n dstSpace: SpaceEnv,\n isMove: boolean,\n overwrite = false,\n dav?: { depth: LOCK_DEPTH; lockTokens: string[] }\n ): Promise<void> {\n // checks\n if (!canAccessToSpace(user, dstSpace)) {\n this.logger.warn(`${this.copyMove.name} - is not allowed to access to this space repository : ${dstSpace.repository}`)\n throw new FileError(HttpStatus.FORBIDDEN, 'You are not allowed to access to this repository')\n }\n if (!haveSpaceEnvPermissions(dstSpace, SPACE_OPERATION.ADD)) {\n this.logger.warn(`${this.copyMove.name} - is not allowed to copy/move on this space : *${dstSpace.alias}* (${dstSpace.id}) : ${dstSpace.url}`)\n throw new FileError(HttpStatus.FORBIDDEN, 'You are not allowed to copy/move on the destination')\n }\n if (dstSpace.quotaIsExceeded) {\n this.logger.warn(`${this.copyMove.name} - quota is exceeded for *${dstSpace.alias}* (${dstSpace.id})`)\n throw new FileError(HttpStatus.INSUFFICIENT_STORAGE, 'Quota is exceeded')\n }\n if (!(await isPathExists(srcSpace.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (!(await isPathExists(dirName(dstSpace.realPath)))) {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n if (srcSpace.realPath === dstSpace.realPath) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Cannot copy/move source onto itself')\n }\n if (`${dstSpace.realPath}/`.startsWith(`${srcSpace.realPath}/`)) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Cannot copy/move source below itself')\n }\n if (dirName(srcSpace.url) === dirName(dstSpace.url) && dirName(srcSpace.realPath) !== dirName(dstSpace.realPath)) {\n /* Handle renaming a space file with the same name as a space root :\n srcSpace.url = '/space/sync-in/code2.ts' (a space file)\n srcSpace.realPath = '/home/sync-in/spaces/sync-in/code2.ts\n dstSpace.url = '/space/sync-in/code.ts' (a space root)\n dstSpace.realPath = '/home/sync-in/users/jo/files/code2.ts !!\n */\n throw new FileError(HttpStatus.BAD_REQUEST, 'An anchored file already has this name')\n }\n if (!overwrite && (await isPathExists(dstSpace.realPath))) {\n /* Handle case-sensitive (in renaming context):\n srcSpace.url = '/space/sync-in/code.ts'\n dstSpace.url = '/space/sync-in/code.TS'\n The destination exists because it's the same file, bypass this\n */\n if (!(isMove && srcSpace.realPath.toLowerCase() === dstSpace.realPath.toLowerCase())) {\n throw new FileError(dav ? HttpStatus.PRECONDITION_FAILED : HttpStatus.BAD_REQUEST, 'The destination already exists')\n }\n }\n\n const isDir = await isPathIsDir(srcSpace.realPath)\n\n if (dstSpace.storageQuota) {\n /* Skip validation when moving to the same space; for copy operations, run all checks. */\n if (!isMove || (isMove && srcSpace.id !== dstSpace.id)) {\n const size = isDir ? (await dirSize(srcSpace.realPath))[0] : await fileSize(srcSpace.realPath)\n if (dstSpace.willExceedQuota(size)) {\n this.logger.warn(`${this.copyMove.name} - quota will be exceeded for *${dstSpace.alias}* (${dstSpace.id})`)\n throw new FileError(HttpStatus.INSUFFICIENT_STORAGE, 'Quota will be exceeded')\n }\n }\n }\n\n // check lock conflicts on source & destination\n let recursive: boolean\n let depth: LOCK_DEPTH\n if (dav?.depth) {\n recursive = dav.depth === DEPTH.INFINITY\n depth = dav.depth\n } else {\n recursive = isDir\n depth = recursive ? DEPTH.INFINITY : DEPTH.RESOURCE\n }\n if (isMove) {\n // check source\n await this.filesLockManager.checkConflicts(srcSpace.dbFile, depth, { userId: user.id, lockTokens: dav?.lockTokens })\n }\n // check destination\n await this.filesLockManager.checkConflicts(dstSpace.dbFile, depth, { userId: user.id, lockTokens: dav?.lockTokens })\n\n // overwrite\n if (overwrite && (await isPathExists(dstSpace.realPath))) {\n // todo : versioning here\n await this.delete(user, dstSpace)\n }\n\n // send to task watcher\n if (srcSpace.task?.cacheKey) {\n if (!isDir) srcSpace.task.props.totalSize = await fileSize(srcSpace.realPath)\n FileTaskEvent.emit('startWatch', srcSpace, isMove ? FILE_OPERATION.MOVE : FILE_OPERATION.COPY, dstSpace.realPath)\n }\n\n // do\n if (isMove) {\n await moveFiles(srcSpace.realPath, dstSpace.realPath, overwrite)\n return this.filesQueries.moveFiles(srcSpace.dbFile, dstSpace.dbFile, isDir)\n }\n return copyFiles(srcSpace.realPath, dstSpace.realPath, overwrite, recursive)\n }\n\n async delete(user: UserModel, space: SpaceEnv, dav?: { lockTokens: string[] }): Promise<void> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n // check lock conflicts\n const isDir = await isPathIsDir(space.realPath)\n await this.filesLockManager.checkConflicts(space.dbFile, isDir ? DEPTH.INFINITY : DEPTH.RESOURCE, {\n userId: user.id,\n lockTokens: dav?.lockTokens\n })\n // file system deletion\n let forceDeleteInDB = false\n if (space.inTrashRepository) {\n await removeFiles(space.realPath)\n } else {\n const baseTrashPath = realTrashPathFromSpace(user, space)\n if (baseTrashPath) {\n const name = fileName(space.realPath)\n const trashDir = path.join(baseTrashPath, dirName(space.dbFile.path))\n const trashFile = path.join(trashDir, name)\n if (!(await isPathExists(trashDir))) {\n await makeDir(trashDir, true)\n }\n if (await isPathExists(trashFile)) {\n // if a resource already exists in the trash, rename it with the date\n const dstTrash = await uniqueDatedFilePath(trashFile)\n // move the resource on fs\n await moveFiles(trashFile, dstTrash.path)\n // move the resource in db\n const trashFileDB: FileDBProps = { ...space.dbFile, inTrash: true }\n const dstTrashFileDB: FileDBProps = { ...trashFileDB, path: path.join(dirName(trashFileDB.path), fileName(dstTrash.path)) }\n this.filesQueries\n .moveFiles(trashFileDB, dstTrashFileDB, dstTrash.isDir)\n .catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n await moveFiles(space.realPath, trashFile, true)\n } else {\n this.logger.log(`Unable to find trash path for space - *${space.alias}* (${space.id}) : delete permanently : ${space.realPath}`)\n // todo: define a default trash for external paths\n forceDeleteInDB = true\n await removeFiles(space.realPath)\n }\n }\n // remove locks, these locks have already been checked in the `checkConflicts` function\n if (isDir) {\n this.filesLockManager.removeChildLocks(user, space.dbFile).catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n this.filesLockManager.removeLock(lock.key).catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n // delete or move to trash the files in db\n return this.filesQueries.deleteFiles(space.dbFile, isDir, forceDeleteInDB)\n }\n\n async downloadFromUrl(user: UserModel, space: SpaceEnv, url: string): Promise<void> {\n this.logger.log(`${this.downloadFromUrl.name} : ${url}`)\n // create lock\n const rPath = await uniqueFilePathFromDir(space.realPath)\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(space.realPath))\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(fileLock, 'Conflicting lock')\n }\n // tasking\n if (space.task.cacheKey) {\n let headRes: AxiosResponse\n\n try {\n headRes = await this.http.axiosRef({ method: HTTP_METHOD.HEAD, url: url, maxRedirects: 1 })\n } catch (e) {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n this.logger.error(`${this.downloadFromUrl.name} - ${url} : ${e}`)\n throw new FileError(HttpStatus.BAD_REQUEST, 'Unable to download file')\n }\n\n if (regExpPrivateIP.test(headRes.request.socket.remoteAddress)) {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n // prevent SSRF attack\n throw new FileError(HttpStatus.FORBIDDEN, 'Access to internal IP addresses is forbidden')\n }\n\n // attempt to retrieve the Content-Length header\n try {\n if ('content-length' in headRes.headers) {\n space.task.props.totalSize = parseInt(headRes.headers['content-length'], 10) || null\n }\n } catch (e) {\n this.logger.debug(`${this.downloadFromUrl.name} - content-length : ${e}`)\n }\n FileTaskEvent.emit('startWatch', space, FILE_OPERATION.DOWNLOAD, rPath)\n }\n // do\n try {\n const getRes = await this.http.axiosRef({ method: HTTP_METHOD.GET, url: url, responseType: 'stream', maxRedirects: 1 })\n if (regExpPrivateIP.test(getRes.request.socket.remoteAddress)) {\n // Prevent SSRF attacks and perform a DNS-rebinding check if a HEAD request has already been made\n throw new FileError(HttpStatus.FORBIDDEN, 'Access to internal IP addresses is forbidden')\n }\n await writeFromStream(rPath, getRes.data)\n } finally {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n\n async compress(user: UserModel, space: SpaceEnv, dto: CompressFileDto): Promise<void> {\n // This method is currently used only by files-methods.service, which handles input sanitization.\n // If it is used in other services in the future, make sure to refactor accordingly to sanitize inputs properly.\n const srcPath = dirName(space.realPath)\n // todo: a guest link tasksPath should be in specific directory (guest link has no home)\n const archiveExt = dto.name.endsWith(dto.extension) ? '' : `.${dto.extension}`\n const dstPath = await uniqueFilePathFromDir(path.join(dto.compressInDirectory ? srcPath : user.tasksPath, `${dto.name}${archiveExt}`))\n const archive: Archiver = archiver('tar', {\n gzip: dto.extension === tarGzExtension,\n gzipOptions: {\n level: 9\n }\n })\n // create lock\n let fileLock: FileLock\n if (dto.compressInDirectory) {\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(dstPath))\n const [ok, lock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(lock, 'Conflicting lock')\n }\n fileLock = lock\n }\n if (space.task?.cacheKey) {\n space.task.props.compressInDirectory = dto.compressInDirectory\n FileTaskEvent.emit('startWatch', space, FILE_OPERATION.COMPRESS, dstPath)\n }\n // do\n try {\n archive.on('error', (error: ArchiverError) => {\n throw error\n })\n const dstStream = fs.createWriteStream(dstPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n archive.pipe(dstStream)\n for (const f of dto.files) {\n if (await isPathIsDir(f.path)) {\n archive.directory(f.path, dto.files.length > 1 ? fileName(f.path) : false)\n } else {\n archive.file(f.path, {\n name: f.rootAlias ? f.name : fileName(f.path)\n })\n }\n }\n await archive.finalize()\n } finally {\n if (fileLock) {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n }\n\n async decompress(user: UserModel, space: SpaceEnv): Promise<void> {\n // checks\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n const extension = path.extname(space.realPath)\n if (!COMPRESSION_EXTENSION.has(extension)) {\n throw new FileError(HttpStatus.BAD_REQUEST, `${extension} is not supported`)\n }\n // make destination folder\n const dstPath = await uniqueFilePathFromDir(path.join(dirName(space.realPath), path.basename(space.realPath, extension)))\n await makeDir(dstPath)\n // create lock\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(dstPath))\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.INFINITY)\n if (!ok) {\n throw new LockConflict(fileLock, 'Conflicting lock')\n }\n // tasking\n if (space.task?.cacheKey) FileTaskEvent.emit('startWatch', space, FILE_OPERATION.DECOMPRESS, dstPath)\n // do\n try {\n if (extension === '.zip') {\n await extractZip(space.realPath, dstPath)\n } else {\n await extractTar({\n file: space.realPath,\n cwd: dstPath,\n gzip: COMPRESSION_EXTENSION.get(extension) === tarGzExtension,\n preserveOwner: false\n })\n }\n } finally {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n\n async generateThumbnail(space: SpaceEnv, size: number): Promise<PNGStream> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (getMimeType(space.realPath, false).indexOf('image') === -1) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'File is not an image')\n }\n try {\n return generateThumbnail(space.realPath, size)\n } catch (e) {\n this.logger.warn(e)\n throw new FileError(HttpStatus.BAD_REQUEST, 'File is not an image')\n }\n }\n}\n"],"names":["FilesManager","sendFileFromSpace","space","asAttachment","downloadName","SendFile","realPath","saveStream","user","req","options","fExists","isPathExists","fTmpExists","tmpPath","method","HTTP_METHOD","POST","FileError","HttpStatus","METHOD_NOT_ALLOWED","isPathIsDir","makeDir","dirName","CONFLICT","fileLock","dav","filesLockManager","checkConflicts","dbFile","depth","DEPTH","RESOURCE","userId","id","lockTokens","ok","lock","create","LockConflict","startRange","headers","match","exec","length","BAD_REQUEST","parseInt","size","fileSize","checksum","checksumAlg","writeFromStreamAndChecksum","raw","writeFromStream","path","dirname","moveFiles","e","removeFiles","logger","error","name","INTERNAL_SERVER_ERROR","removeLock","key","warn","saveMultipart","realParentPath","basePath","sep","part","files","dstFile","resolve","filename","startsWith","FORBIDDEN","dstDir","join","pipeline","file","fs","createWriteStream","highWaterMark","DEFAULT_HIGH_WATER_MARK","touch","mtime","checkLocks","NOT_FOUND","touchFile","mkFile","overwrite","checkDocument","checkFileName","fileExtension","extname","Object","values","DOCUMENT_TYPE","indexOf","srcSample","__dirname","SAMPLE_PATH_WITHOUT_EXT","copyFiles","createEmptyFile","mkDir","recursive","copyMove","srcSpace","dstSpace","isMove","canAccessToSpace","repository","haveSpaceEnvPermissions","SPACE_OPERATION","ADD","alias","url","quotaIsExceeded","INSUFFICIENT_STORAGE","toLowerCase","PRECONDITION_FAILED","isDir","storageQuota","dirSize","willExceedQuota","INFINITY","delete","task","cacheKey","props","totalSize","FileTaskEvent","emit","FILE_OPERATION","MOVE","COPY","filesQueries","forceDeleteInDB","inTrashRepository","baseTrashPath","realTrashPathFromSpace","fileName","trashDir","trashFile","dstTrash","uniqueDatedFilePath","trashFileDB","inTrash","dstTrashFileDB","catch","log","removeChildLocks","getLocksByPath","deleteFiles","downloadFromUrl","rPath","uniqueFilePathFromDir","headRes","http","axiosRef","HEAD","maxRedirects","regExpPrivateIP","test","request","socket","remoteAddress","debug","DOWNLOAD","getRes","GET","responseType","data","compress","dto","srcPath","archiveExt","endsWith","extension","dstPath","compressInDirectory","tasksPath","archive","archiver","gzip","tarGzExtension","gzipOptions","level","COMPRESS","on","dstStream","pipe","f","directory","rootAlias","finalize","decompress","COMPRESSION_EXTENSION","has","basename","DECOMPRESS","extractZip","extractTar","cwd","get","preserveOwner","generateThumbnail","getMimeType","Logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/services/files-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpService } from '@nestjs/axios'\nimport { HttpStatus, Injectable, Logger } from '@nestjs/common'\nimport archiver, { Archiver, ArchiverError } from 'archiver'\nimport { AxiosResponse } from 'axios'\nimport { PNGStream } from 'canvas'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport { pipeline } from 'node:stream/promises'\nimport { extract as extractTar } from 'tar'\nimport { FastifyAuthenticatedRequest } from '../../../authentication/interfaces/auth-request.interface'\nimport { generateThumbnail } from '../../../common/image'\nimport { HTTP_METHOD } from '../../applications.constants'\nimport { SPACE_OPERATION } from '../../spaces/constants/spaces'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { realTrashPathFromSpace } from '../../spaces/utils/paths'\nimport { canAccessToSpace, haveSpaceEnvPermissions } from '../../spaces/utils/permissions'\nimport { UserModel } from '../../users/models/user.model'\nimport { DEPTH, LOCK_DEPTH } from '../../webdav/constants/webdav'\nimport { tarGzExtension } from '../constants/compress'\nimport { COMPRESSION_EXTENSION, DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FILE_OPERATION } from '../constants/operations'\nimport { DOCUMENT_TYPE, SAMPLE_PATH_WITHOUT_EXT } from '../constants/samples'\nimport { CompressFileDto } from '../dto/file-operations.dto'\nimport { FileTaskEvent } from '../events/file-task-event'\nimport { FileDBProps } from '../interfaces/file-db-props.interface'\nimport { FileLock } from '../interfaces/file-lock.interface'\nimport { FileError } from '../models/file-error'\nimport { LockConflict } from '../models/file-lock-error'\nimport {\n checkFileName,\n copyFiles,\n createEmptyFile,\n dirName,\n dirSize,\n fileName,\n fileSize,\n getMimeType,\n isPathExists,\n isPathIsDir,\n makeDir,\n moveFiles,\n removeFiles,\n touchFile,\n uniqueDatedFilePath,\n uniqueFilePathFromDir,\n writeFromStream,\n writeFromStreamAndChecksum\n} from '../utils/files'\nimport { SendFile } from '../utils/send-file'\nimport { extractZip } from '../utils/unzip-file'\nimport { regExpPrivateIP } from '../utils/url-file'\nimport { FilesLockManager } from './files-lock-manager.service'\nimport { FilesQueries } from './files-queries.service'\n\n@Injectable()\nexport class FilesManager {\n /* Spaces permissions are checked in the space guard, except for the copy/move destination */\n private logger = new Logger(FilesManager.name)\n\n constructor(\n private readonly http: HttpService,\n private readonly filesQueries: FilesQueries,\n private readonly filesLockManager: FilesLockManager\n ) {}\n\n sendFileFromSpace(space: SpaceEnv, asAttachment = false, downloadName = ''): SendFile {\n return new SendFile(space.realPath, asAttachment, downloadName)\n }\n\n async saveStream(\n user: UserModel,\n space: SpaceEnv,\n req: FastifyAuthenticatedRequest,\n options: {\n checksumAlg: string\n tmpPath?: string\n }\n ): Promise<string>\n async saveStream(user: UserModel, space: SpaceEnv, req: FastifyAuthenticatedRequest, options?: any): Promise<boolean>\n async saveStream(\n user: UserModel,\n space: SpaceEnv,\n req: FastifyAuthenticatedRequest,\n options?: { dav?: { depth: LOCK_DEPTH; lockTokens: string[] }; checksumAlg?: string; tmpPath?: string }\n ): Promise<boolean | string> {\n // if tmpPath is used, we lock the final destination during the transfer\n // space.realPath is replaced by tmpPath (if allowed), if the move operation failed we remove the tmp file\n const fExists = await isPathExists(space.realPath)\n const fTmpExists = options?.tmpPath ? await isPathExists(options.tmpPath) : false\n if (fExists && req.method === HTTP_METHOD.POST) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'Resource already exists')\n }\n if (fExists && (await isPathIsDir(space.realPath))) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'The location is a directory')\n }\n if (options?.tmpPath) {\n // ensure tmpPath parent dir exists\n await makeDir(dirName(options.tmpPath), true)\n } else if (!(await isPathExists(dirName(space.realPath)))) {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n /* File Lock */\n let fileLock: FileLock | undefined\n if (options?.dav) {\n // check locks\n await this.filesLockManager.checkConflicts(space.dbFile, options?.dav?.depth || DEPTH.RESOURCE, {\n userId: user.id,\n lockTokens: options.dav?.lockTokens\n })\n } else {\n // create lock if there is no webdav context\n const [ok, lock] = await this.filesLockManager.create(user, space.dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(lock, 'Conflicting lock')\n }\n fileLock = lock\n }\n try {\n // check range\n let startRange = 0\n if ((fExists || fTmpExists) && req.headers['content-range']) {\n // with PUT method, some webdav clients use the `content-range` header,\n // which is normally reserved for a response to a request containing the `range` header.\n // However, for more compatibility let's accept it\n const match = /\\d+/.exec(req.headers['content-range'])\n if (!match.length) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Content-range : header is malformed')\n }\n startRange = parseInt(match[0], 10)\n const size = await fileSize(options?.tmpPath || space.realPath)\n if (startRange !== size) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Content-range : start offset does not match the current file size')\n }\n }\n // todo: check file in db to update\n // todo : versioning here\n let checksum: string\n if (options?.checksumAlg) {\n checksum = await writeFromStreamAndChecksum(options?.tmpPath || space.realPath, req.raw, startRange, options.checksumAlg)\n } else {\n await writeFromStream(options?.tmpPath || space.realPath, req.raw, startRange)\n }\n if (options?.tmpPath) {\n try {\n // ensure parent path exists\n await makeDir(path.dirname(space.realPath), true)\n // move the uploaded file to destination\n await moveFiles(options.tmpPath, space.realPath, true)\n } catch (e) {\n // cleanup tmp file\n await removeFiles(options.tmpPath)\n this.logger.error(`${this.saveStream.name} - unable to move ${options.tmpPath} -> ${space.realPath} : ${e}`)\n throw new FileError(HttpStatus.INTERNAL_SERVER_ERROR, 'Unable to move tmp file to dst file')\n }\n }\n if (options?.checksumAlg) {\n return checksum\n }\n return fExists\n } finally {\n if (fileLock) {\n try {\n await this.filesLockManager.removeLock(fileLock.key)\n } catch (e) {\n this.logger.warn(`Failed to remove lock ${fileLock.key}: ${e}`)\n }\n }\n }\n }\n\n async saveMultipart(user: UserModel, space: SpaceEnv, req: FastifySpaceRequest) {\n /* Accepted methods:\n POST: create new resource\n PUT: create or update new resource (even if parent path does not exist)\n */\n const realParentPath = dirName(space.realPath)\n\n if (req.method === HTTP_METHOD.POST) {\n if (await isPathExists(space.realPath)) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Resource already exists')\n }\n if (!(await isPathExists(realParentPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Parent must exists')\n }\n if (!(await isPathIsDir(realParentPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Parent must be a directory')\n }\n }\n\n const basePath = realParentPath + path.sep\n\n for await (const part of req.files()) {\n // part.filename may contain a path like foo/bar.txt.\n const dstFile = path.resolve(basePath, part.filename)\n // prevent path traversal\n if (!dstFile.startsWith(basePath)) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Location is not allowed')\n }\n // make dir in space\n const dstDir = dirName(dstFile)\n if (!(await isPathExists(dstDir))) {\n await makeDir(dstDir, true)\n }\n // create lock\n const dbFile = { ...space.dbFile, path: path.join(dirName(space.dbFile.path), part.filename) }\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) throw new LockConflict(fileLock, 'Conflicting lock')\n // do\n try {\n await pipeline(part.file, fs.createWriteStream(dstFile, { highWaterMark: DEFAULT_HIGH_WATER_MARK }))\n } finally {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n }\n\n async touch(user: UserModel, space: SpaceEnv, mtime: number, checkLocks = true): Promise<void> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (checkLocks) {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id })\n }\n // todo: update mtime in last files ( & in db file ?)\n await touchFile(space.realPath, mtime)\n }\n\n async mkFile(user: UserModel, space: SpaceEnv, overwrite = false, checkLocks = true, checkDocument = false): Promise<void> {\n checkFileName(space.realPath)\n if (!overwrite && (await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Resource already exists')\n }\n if (checkLocks) {\n await this.filesLockManager.checkConflicts(space.dbFile, DEPTH.RESOURCE, { userId: user.id })\n }\n // use sample documents when possible\n const fileExtension = path.extname(space.realPath)\n if (checkDocument && fileExtension !== '.txt' && Object.values(DOCUMENT_TYPE).indexOf(fileExtension) > -1) {\n const srcSample = path.join(__dirname, `${SAMPLE_PATH_WITHOUT_EXT}${fileExtension}`)\n await copyFiles(srcSample, space.realPath)\n return touchFile(space.realPath)\n } else {\n return createEmptyFile(space.realPath)\n }\n }\n\n async mkDir(user: UserModel, space: SpaceEnv, recursive = false, dav?: { depth: LOCK_DEPTH; lockTokens: string[] }): Promise<void> {\n checkFileName(space.realPath)\n if (!recursive) {\n if (await isPathExists(space.realPath)) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'Resource already exists')\n } else if (!(await isPathExists(dirName(space.realPath)))) {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n }\n await this.filesLockManager.checkConflicts(space.dbFile, dav?.depth || DEPTH.RESOURCE, { userId: user.id, lockTokens: dav?.lockTokens })\n await makeDir(space.realPath, recursive)\n }\n\n async copyMove(\n user: UserModel,\n srcSpace: SpaceEnv,\n dstSpace: SpaceEnv,\n isMove: boolean,\n overwrite = false,\n mkdirDstParentPath = false,\n dav?: { depth: LOCK_DEPTH; lockTokens: string[] }\n ): Promise<void> {\n // checks\n if (!canAccessToSpace(user, dstSpace)) {\n this.logger.warn(`${this.copyMove.name} - is not allowed to access to this space repository : ${dstSpace.repository}`)\n throw new FileError(HttpStatus.FORBIDDEN, 'You are not allowed to access to this repository')\n }\n if (!haveSpaceEnvPermissions(dstSpace, SPACE_OPERATION.ADD)) {\n this.logger.warn(`${this.copyMove.name} - is not allowed to copy/move on this space : *${dstSpace.alias}* (${dstSpace.id}) : ${dstSpace.url}`)\n throw new FileError(HttpStatus.FORBIDDEN, 'You are not allowed to copy/move on the destination')\n }\n if (dstSpace.quotaIsExceeded) {\n this.logger.warn(`${this.copyMove.name} - quota is exceeded for *${dstSpace.alias}* (${dstSpace.id})`)\n throw new FileError(HttpStatus.INSUFFICIENT_STORAGE, 'Quota is exceeded')\n }\n if (!(await isPathExists(srcSpace.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (!(await isPathExists(dirName(dstSpace.realPath)))) {\n if (mkdirDstParentPath) {\n try {\n await makeDir(dirName(dstSpace.realPath), true)\n } catch (e) {\n this.logger.error(`${this.copyMove.name} - Cannot create parent directory for destination ${dstSpace.realPath} : ${e}`)\n throw new FileError(HttpStatus.INTERNAL_SERVER_ERROR, 'Cannot create parent directory for destination')\n }\n } else {\n throw new FileError(HttpStatus.CONFLICT, 'Parent must exists')\n }\n }\n if (srcSpace.realPath === dstSpace.realPath) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Cannot copy/move source onto itself')\n }\n if (`${dstSpace.realPath}/`.startsWith(`${srcSpace.realPath}/`)) {\n throw new FileError(HttpStatus.FORBIDDEN, 'Cannot copy/move source below itself')\n }\n if (dirName(srcSpace.url) === dirName(dstSpace.url) && dirName(srcSpace.realPath) !== dirName(dstSpace.realPath)) {\n /* Handle renaming a space file with the same name as a space root :\n srcSpace.url = '/space/sync-in/code2.ts' (a space file)\n srcSpace.realPath = '/home/sync-in/spaces/sync-in/code2.ts\n dstSpace.url = '/space/sync-in/code.ts' (a space root)\n dstSpace.realPath = '/home/sync-in/users/jo/files/code2.ts !!\n */\n throw new FileError(HttpStatus.BAD_REQUEST, 'An anchored file already has this name')\n }\n if (!overwrite && (await isPathExists(dstSpace.realPath))) {\n /* Handle case-sensitive (in renaming context):\n srcSpace.url = '/space/sync-in/code.ts'\n dstSpace.url = '/space/sync-in/code.TS'\n The destination exists because it's the same file, bypass this\n */\n if (!(isMove && srcSpace.realPath.toLowerCase() === dstSpace.realPath.toLowerCase())) {\n throw new FileError(dav ? HttpStatus.PRECONDITION_FAILED : HttpStatus.BAD_REQUEST, 'The destination already exists')\n }\n }\n\n const isDir = await isPathIsDir(srcSpace.realPath)\n\n if (dstSpace.storageQuota) {\n /* Skip validation when moving to the same space; for copy operations, run all checks. */\n if (!isMove || (isMove && srcSpace.id !== dstSpace.id)) {\n const size = isDir ? (await dirSize(srcSpace.realPath))[0] : await fileSize(srcSpace.realPath)\n if (dstSpace.willExceedQuota(size)) {\n this.logger.warn(`${this.copyMove.name} - quota will be exceeded for *${dstSpace.alias}* (${dstSpace.id})`)\n throw new FileError(HttpStatus.INSUFFICIENT_STORAGE, 'Quota will be exceeded')\n }\n }\n }\n\n // check lock conflicts on source & destination\n let recursive: boolean\n let depth: LOCK_DEPTH\n if (dav?.depth) {\n recursive = dav.depth === DEPTH.INFINITY\n depth = dav.depth\n } else {\n recursive = isDir\n depth = recursive ? DEPTH.INFINITY : DEPTH.RESOURCE\n }\n if (isMove) {\n // check source\n await this.filesLockManager.checkConflicts(srcSpace.dbFile, depth, { userId: user.id, lockTokens: dav?.lockTokens })\n }\n // check destination\n await this.filesLockManager.checkConflicts(dstSpace.dbFile, depth, { userId: user.id, lockTokens: dav?.lockTokens })\n\n // overwrite\n if (overwrite && (await isPathExists(dstSpace.realPath))) {\n // todo : versioning here\n await this.delete(user, dstSpace)\n }\n\n // send to task watcher\n if (srcSpace.task?.cacheKey) {\n if (!isDir) srcSpace.task.props.totalSize = await fileSize(srcSpace.realPath)\n FileTaskEvent.emit('startWatch', srcSpace, isMove ? FILE_OPERATION.MOVE : FILE_OPERATION.COPY, dstSpace.realPath)\n }\n\n // do\n if (isMove) {\n await moveFiles(srcSpace.realPath, dstSpace.realPath, overwrite)\n return this.filesQueries.moveFiles(srcSpace.dbFile, dstSpace.dbFile, isDir)\n }\n return copyFiles(srcSpace.realPath, dstSpace.realPath, overwrite, recursive)\n }\n\n async delete(user: UserModel, space: SpaceEnv, dav?: { lockTokens: string[] }): Promise<void> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n // check lock conflicts\n const isDir = await isPathIsDir(space.realPath)\n await this.filesLockManager.checkConflicts(space.dbFile, isDir ? DEPTH.INFINITY : DEPTH.RESOURCE, {\n userId: user.id,\n lockTokens: dav?.lockTokens\n })\n // file system deletion\n let forceDeleteInDB = false\n if (space.inTrashRepository) {\n await removeFiles(space.realPath)\n } else {\n const baseTrashPath = realTrashPathFromSpace(user, space)\n if (baseTrashPath) {\n const name = fileName(space.realPath)\n const trashDir = path.join(baseTrashPath, dirName(space.dbFile.path))\n const trashFile = path.join(trashDir, name)\n if (!(await isPathExists(trashDir))) {\n await makeDir(trashDir, true)\n }\n if (await isPathExists(trashFile)) {\n // if a resource already exists in the trash, rename it with the date\n const dstTrash = await uniqueDatedFilePath(trashFile)\n // move the resource on fs\n await moveFiles(trashFile, dstTrash.path)\n // move the resource in db\n const trashFileDB: FileDBProps = { ...space.dbFile, inTrash: true }\n const dstTrashFileDB: FileDBProps = { ...trashFileDB, path: path.join(dirName(trashFileDB.path), fileName(dstTrash.path)) }\n this.filesQueries\n .moveFiles(trashFileDB, dstTrashFileDB, dstTrash.isDir)\n .catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n await moveFiles(space.realPath, trashFile, true)\n } else {\n this.logger.log(`Unable to find trash path for space - *${space.alias}* (${space.id}) : delete permanently : ${space.realPath}`)\n // todo: define a default trash for external paths\n forceDeleteInDB = true\n await removeFiles(space.realPath)\n }\n }\n // remove locks, these locks have already been checked in the `checkConflicts` function\n if (isDir) {\n this.filesLockManager.removeChildLocks(user, space.dbFile).catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n for (const lock of await this.filesLockManager.getLocksByPath(space.dbFile)) {\n this.filesLockManager.removeLock(lock.key).catch((e: Error) => this.logger.error(`${this.delete.name} - ${e}`))\n }\n // delete or move to trash the files in db\n return this.filesQueries.deleteFiles(space.dbFile, isDir, forceDeleteInDB)\n }\n\n async downloadFromUrl(user: UserModel, space: SpaceEnv, url: string): Promise<void> {\n this.logger.log(`${this.downloadFromUrl.name} : ${url}`)\n // create lock\n const rPath = await uniqueFilePathFromDir(space.realPath)\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(space.realPath))\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(fileLock, 'Conflicting lock')\n }\n // tasking\n if (space.task.cacheKey) {\n let headRes: AxiosResponse\n\n try {\n headRes = await this.http.axiosRef({ method: HTTP_METHOD.HEAD, url: url, maxRedirects: 1 })\n } catch (e) {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n this.logger.error(`${this.downloadFromUrl.name} - ${url} : ${e}`)\n throw new FileError(HttpStatus.BAD_REQUEST, 'Unable to download file')\n }\n\n if (regExpPrivateIP.test(headRes.request.socket.remoteAddress)) {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n // prevent SSRF attack\n throw new FileError(HttpStatus.FORBIDDEN, 'Access to internal IP addresses is forbidden')\n }\n\n // attempt to retrieve the Content-Length header\n try {\n if ('content-length' in headRes.headers) {\n space.task.props.totalSize = parseInt(headRes.headers['content-length'], 10) || null\n }\n } catch (e) {\n this.logger.debug(`${this.downloadFromUrl.name} - content-length : ${e}`)\n }\n FileTaskEvent.emit('startWatch', space, FILE_OPERATION.DOWNLOAD, rPath)\n }\n // do\n try {\n const getRes = await this.http.axiosRef({ method: HTTP_METHOD.GET, url: url, responseType: 'stream', maxRedirects: 1 })\n if (regExpPrivateIP.test(getRes.request.socket.remoteAddress)) {\n // Prevent SSRF attacks and perform a DNS-rebinding check if a HEAD request has already been made\n throw new FileError(HttpStatus.FORBIDDEN, 'Access to internal IP addresses is forbidden')\n }\n await writeFromStream(rPath, getRes.data)\n } finally {\n // release lock\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n\n async compress(user: UserModel, space: SpaceEnv, dto: CompressFileDto): Promise<void> {\n // This method is currently used only by files-methods.service, which handles input sanitization.\n // If it is used in other services in the future, make sure to refactor accordingly to sanitize inputs properly.\n const srcPath = dirName(space.realPath)\n // todo: a guest link tasksPath should be in specific directory (guest link has no home)\n const archiveExt = dto.name.endsWith(dto.extension) ? '' : `.${dto.extension}`\n const dstPath = await uniqueFilePathFromDir(path.join(dto.compressInDirectory ? srcPath : user.tasksPath, `${dto.name}${archiveExt}`))\n const archive: Archiver = archiver('tar', {\n gzip: dto.extension === tarGzExtension,\n gzipOptions: {\n level: 9\n }\n })\n // create lock\n let fileLock: FileLock\n if (dto.compressInDirectory) {\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(dstPath))\n const [ok, lock] = await this.filesLockManager.create(user, dbFile, DEPTH.RESOURCE)\n if (!ok) {\n throw new LockConflict(lock, 'Conflicting lock')\n }\n fileLock = lock\n }\n if (space.task?.cacheKey) {\n space.task.props.compressInDirectory = dto.compressInDirectory\n FileTaskEvent.emit('startWatch', space, FILE_OPERATION.COMPRESS, dstPath)\n }\n // do\n try {\n archive.on('error', (error: ArchiverError) => {\n throw error\n })\n const dstStream = fs.createWriteStream(dstPath, { highWaterMark: DEFAULT_HIGH_WATER_MARK })\n archive.pipe(dstStream)\n for (const f of dto.files) {\n if (await isPathIsDir(f.path)) {\n archive.directory(f.path, dto.files.length > 1 ? fileName(f.path) : false)\n } else {\n archive.file(f.path, {\n name: f.rootAlias ? f.name : fileName(f.path)\n })\n }\n }\n await archive.finalize()\n } finally {\n if (fileLock) {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n }\n\n async decompress(user: UserModel, space: SpaceEnv): Promise<void> {\n // checks\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n const extension = path.extname(space.realPath)\n if (!COMPRESSION_EXTENSION.has(extension)) {\n throw new FileError(HttpStatus.BAD_REQUEST, `${extension} is not supported`)\n }\n // make destination folder\n const dstPath = await uniqueFilePathFromDir(path.join(dirName(space.realPath), path.basename(space.realPath, extension)))\n await makeDir(dstPath)\n // create lock\n const dbFile = space.dbFile\n dbFile.path = path.join(dirName(dbFile.path), fileName(dstPath))\n const [ok, fileLock] = await this.filesLockManager.create(user, dbFile, DEPTH.INFINITY)\n if (!ok) {\n throw new LockConflict(fileLock, 'Conflicting lock')\n }\n // tasking\n if (space.task?.cacheKey) FileTaskEvent.emit('startWatch', space, FILE_OPERATION.DECOMPRESS, dstPath)\n // do\n try {\n if (extension === '.zip') {\n await extractZip(space.realPath, dstPath)\n } else {\n await extractTar({\n file: space.realPath,\n cwd: dstPath,\n gzip: COMPRESSION_EXTENSION.get(extension) === tarGzExtension,\n preserveOwner: false\n })\n }\n } finally {\n await this.filesLockManager.removeLock(fileLock.key)\n }\n }\n\n async generateThumbnail(space: SpaceEnv, size: number): Promise<PNGStream> {\n if (!(await isPathExists(space.realPath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (getMimeType(space.realPath, false).indexOf('image') === -1) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'File is not an image')\n }\n try {\n return generateThumbnail(space.realPath, size)\n } catch (e) {\n this.logger.warn(e)\n throw new FileError(HttpStatus.BAD_REQUEST, 'File is not an image')\n }\n }\n}\n"],"names":["FilesManager","sendFileFromSpace","space","asAttachment","downloadName","SendFile","realPath","saveStream","user","req","options","fExists","isPathExists","fTmpExists","tmpPath","method","HTTP_METHOD","POST","FileError","HttpStatus","METHOD_NOT_ALLOWED","isPathIsDir","makeDir","dirName","CONFLICT","fileLock","dav","filesLockManager","checkConflicts","dbFile","depth","DEPTH","RESOURCE","userId","id","lockTokens","ok","lock","create","LockConflict","startRange","headers","match","exec","length","BAD_REQUEST","parseInt","size","fileSize","checksum","checksumAlg","writeFromStreamAndChecksum","raw","writeFromStream","path","dirname","moveFiles","e","removeFiles","logger","error","name","INTERNAL_SERVER_ERROR","removeLock","key","warn","saveMultipart","realParentPath","basePath","sep","part","files","dstFile","resolve","filename","startsWith","FORBIDDEN","dstDir","join","pipeline","file","fs","createWriteStream","highWaterMark","DEFAULT_HIGH_WATER_MARK","touch","mtime","checkLocks","NOT_FOUND","touchFile","mkFile","overwrite","checkDocument","checkFileName","fileExtension","extname","Object","values","DOCUMENT_TYPE","indexOf","srcSample","__dirname","SAMPLE_PATH_WITHOUT_EXT","copyFiles","createEmptyFile","mkDir","recursive","copyMove","srcSpace","dstSpace","isMove","mkdirDstParentPath","canAccessToSpace","repository","haveSpaceEnvPermissions","SPACE_OPERATION","ADD","alias","url","quotaIsExceeded","INSUFFICIENT_STORAGE","toLowerCase","PRECONDITION_FAILED","isDir","storageQuota","dirSize","willExceedQuota","INFINITY","delete","task","cacheKey","props","totalSize","FileTaskEvent","emit","FILE_OPERATION","MOVE","COPY","filesQueries","forceDeleteInDB","inTrashRepository","baseTrashPath","realTrashPathFromSpace","fileName","trashDir","trashFile","dstTrash","uniqueDatedFilePath","trashFileDB","inTrash","dstTrashFileDB","catch","log","removeChildLocks","getLocksByPath","deleteFiles","downloadFromUrl","rPath","uniqueFilePathFromDir","headRes","http","axiosRef","HEAD","maxRedirects","regExpPrivateIP","test","request","socket","remoteAddress","debug","DOWNLOAD","getRes","GET","responseType","data","compress","dto","srcPath","archiveExt","endsWith","extension","dstPath","compressInDirectory","tasksPath","archive","archiver","gzip","tarGzExtension","gzipOptions","level","COMPRESS","on","dstStream","pipe","f","directory","rootAlias","finalize","decompress","COMPRESSION_EXTENSION","has","basename","DECOMPRESS","extractZip","extractTar","cwd","get","preserveOwner","generateThumbnail","getMimeType","Logger"],"mappings":"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"}
|
|
@@ -34,7 +34,7 @@ let SendFile = class SendFile {
|
|
|
34
34
|
// Ranges, LastModified, Etag are also handled
|
|
35
35
|
// Send function uses decodeURIComponent, but filePath is already decoded : we need to encode it again before passing it.
|
|
36
36
|
const encodedFilePath = encodeURIComponent(this.filePath);
|
|
37
|
-
this.fileName = this.downloadName ?
|
|
37
|
+
this.fileName = encodeURIComponent(this.downloadName ? this.downloadName : (0, _files1.fileName)(this.filePath));
|
|
38
38
|
const sendResult = await (0, _send.send)(req.raw, encodedFilePath, this.sendOptions);
|
|
39
39
|
// Check if the path was correctly validated
|
|
40
40
|
if (sendResult.metadata['path'] === undefined) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/send-file.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { send, SendOptions, SendResult } from '@fastify/send'\nimport { HttpStatus, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FileError } from '../models/file-error'\nimport { fileName, isPathExists, isPathIsDir, isPathIsReadable } from './files'\n\nexport class SendFile {\n private fileName: string\n\n constructor(\n private readonly filePath: string,\n private readonly asAttachment = true,\n private readonly downloadName = '',\n private readonly sendOptions: SendOptions = {\n acceptRanges: true,\n etag: true,\n dotfiles: 'allow',\n lastModified: true,\n cacheControl: false,\n index: false,\n highWaterMark: DEFAULT_HIGH_WATER_MARK\n }\n ) {}\n\n async checks() {\n if (!(await isPathExists(this.filePath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (await isPathIsDir(this.filePath)) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'The location is a directory')\n }\n if (!(await isPathIsReadable(this.filePath))) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'The location is not readable')\n }\n }\n\n async stream(req: FastifyRequest, res: FastifyReply): Promise<StreamableFile> {\n // SendStream manages HEAD (no including body in response) & GET request (with body)\n // Ranges, LastModified, Etag are also handled\n // Send function uses decodeURIComponent, but filePath is already decoded : we need to encode it again before passing it.\n const encodedFilePath = encodeURIComponent(this.filePath)\n this.fileName = this.downloadName ?
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/files/utils/send-file.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { send, SendOptions, SendResult } from '@fastify/send'\nimport { HttpStatus, StreamableFile } from '@nestjs/common'\nimport { FastifyReply, FastifyRequest } from 'fastify'\nimport { DEFAULT_HIGH_WATER_MARK } from '../constants/files'\nimport { FileError } from '../models/file-error'\nimport { fileName, isPathExists, isPathIsDir, isPathIsReadable } from './files'\n\nexport class SendFile {\n private fileName: string\n\n constructor(\n private readonly filePath: string,\n private readonly asAttachment = true,\n private readonly downloadName = '',\n private readonly sendOptions: SendOptions = {\n acceptRanges: true,\n etag: true,\n dotfiles: 'allow',\n lastModified: true,\n cacheControl: false,\n index: false,\n highWaterMark: DEFAULT_HIGH_WATER_MARK\n }\n ) {}\n\n async checks() {\n if (!(await isPathExists(this.filePath))) {\n throw new FileError(HttpStatus.NOT_FOUND, 'Location not found')\n }\n if (await isPathIsDir(this.filePath)) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'The location is a directory')\n }\n if (!(await isPathIsReadable(this.filePath))) {\n throw new FileError(HttpStatus.METHOD_NOT_ALLOWED, 'The location is not readable')\n }\n }\n\n async stream(req: FastifyRequest, res: FastifyReply): Promise<StreamableFile> {\n // SendStream manages HEAD (no including body in response) & GET request (with body)\n // Ranges, LastModified, Etag are also handled\n // Send function uses decodeURIComponent, but filePath is already decoded : we need to encode it again before passing it.\n const encodedFilePath = encodeURIComponent(this.filePath)\n this.fileName = encodeURIComponent(this.downloadName ? this.downloadName : fileName(this.filePath))\n const sendResult: SendResult = await send(req.raw, encodedFilePath, this.sendOptions)\n // Check if the path was correctly validated\n if (sendResult.metadata['path'] === undefined) {\n throw new FileError(HttpStatus.BAD_REQUEST, 'Location not found')\n }\n if (this.asAttachment) {\n const downloadName = this.fileName.normalize('NFD').replace(/[\\u0300-\\u036f]/g, '')\n sendResult.headers['content-disposition'] = `attachment; filename=\"${downloadName}\";filename*=UTF-8''${this.fileName}`\n }\n res.headers(sendResult.headers)\n res.status(sendResult.statusCode)\n // sendStream.once('stream', () => console.log(`Sending: ${this.fileName}`))\n // sendStream.once('end', () => console.log(`Received: ${this.fileName}`))\n // sendStream.once('error', (e: Error) => console.error(`Transfer error : ${this.fileName} - ${e}`))\n return new StreamableFile(sendResult.stream)\n }\n}\n"],"names":["SendFile","checks","isPathExists","filePath","FileError","HttpStatus","NOT_FOUND","isPathIsDir","BAD_REQUEST","isPathIsReadable","METHOD_NOT_ALLOWED","stream","req","res","encodedFilePath","encodeURIComponent","fileName","downloadName","sendResult","send","raw","sendOptions","metadata","undefined","asAttachment","normalize","replace","headers","status","statusCode","StreamableFile","acceptRanges","etag","dotfiles","lastModified","cacheControl","index","highWaterMark","DEFAULT_HIGH_WATER_MARK"],"mappings":"AAAA;;;;CAIC;;;;+BASYA;;;eAAAA;;;sBAPiC;wBACH;uBAEH;2BACd;wBAC4C;AAE/D,IAAA,AAAMA,WAAN,MAAMA;IAkBX,MAAMC,SAAS;QACb,IAAI,CAAE,MAAMC,IAAAA,oBAAY,EAAC,IAAI,CAACC,QAAQ,GAAI;YACxC,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACC,SAAS,EAAE;QAC5C;QACA,IAAI,MAAMC,IAAAA,mBAAW,EAAC,IAAI,CAACJ,QAAQ,GAAG;YACpC,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACG,WAAW,EAAE;QAC9C;QACA,IAAI,CAAE,MAAMC,IAAAA,wBAAgB,EAAC,IAAI,CAACN,QAAQ,GAAI;YAC5C,MAAM,IAAIC,oBAAS,CAACC,kBAAU,CAACK,kBAAkB,EAAE;QACrD;IACF;IAEA,MAAMC,OAAOC,GAAmB,EAAEC,GAAiB,EAA2B;QAC5E,oFAAoF;QACpF,8CAA8C;QAC9C,yHAAyH;QACzH,MAAMC,kBAAkBC,mBAAmB,IAAI,CAACZ,QAAQ;QACxD,IAAI,CAACa,QAAQ,GAAGD,mBAAmB,IAAI,CAACE,YAAY,GAAG,IAAI,CAACA,YAAY,GAAGD,IAAAA,gBAAQ,EAAC,IAAI,CAACb,QAAQ;QACjG,MAAMe,aAAyB,MAAMC,IAAAA,UAAI,EAACP,IAAIQ,GAAG,EAAEN,iBAAiB,IAAI,CAACO,WAAW;QACpF,4CAA4C;QAC5C,IAAIH,WAAWI,QAAQ,CAAC,OAAO,KAAKC,WAAW;YAC7C,MAAM,IAAInB,oBAAS,CAACC,kBAAU,CAACG,WAAW,EAAE;QAC9C;QACA,IAAI,IAAI,CAACgB,YAAY,EAAE;YACrB,MAAMP,eAAe,IAAI,CAACD,QAAQ,CAACS,SAAS,CAAC,OAAOC,OAAO,CAAC,oBAAoB;YAChFR,WAAWS,OAAO,CAAC,sBAAsB,GAAG,CAAC,sBAAsB,EAAEV,aAAa,mBAAmB,EAAE,IAAI,CAACD,QAAQ,EAAE;QACxH;QACAH,IAAIc,OAAO,CAACT,WAAWS,OAAO;QAC9Bd,IAAIe,MAAM,CAACV,WAAWW,UAAU;QAChC,4EAA4E;QAC5E,0EAA0E;QAC1E,oGAAoG;QACpG,OAAO,IAAIC,sBAAc,CAACZ,WAAWP,MAAM;IAC7C;IAhDA,YACE,AAAiBR,QAAgB,EACjC,AAAiBqB,eAAe,IAAI,EACpC,AAAiBP,eAAe,EAAE,EAClC,AAAiBI,cAA2B;QAC1CU,cAAc;QACdC,MAAM;QACNC,UAAU;QACVC,cAAc;QACdC,cAAc;QACdC,OAAO;QACPC,eAAeC,8BAAuB;IACxC,CAAC,CACD;aAZiBnC,WAAAA;aACAqB,eAAAA;aACAP,eAAAA;aACAI,cAAAA;IAShB;AAoCL"}
|
|
@@ -114,7 +114,7 @@ let SyncManager = class SyncManager {
|
|
|
114
114
|
async copyMove(req, syncCopyMoveDto, isMove) {
|
|
115
115
|
const dstSpace = await this.spacesManager.spaceEnv(req.user, (0, _routes.SYNC_PATH_TO_SPACE_SEGMENTS)(syncCopyMoveDto.destination));
|
|
116
116
|
try {
|
|
117
|
-
await this.filesManager.copyMove(req.user, req.space, dstSpace, isMove, true);
|
|
117
|
+
await this.filesManager.copyMove(req.user, req.space, dstSpace, isMove, true, true);
|
|
118
118
|
if (!isMove) {
|
|
119
119
|
if (syncCopyMoveDto.mtime) {
|
|
120
120
|
// update mtime
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger, StreamableFile } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport fs from 'fs/promises'\nimport { Dirent, Stats } from 'node:fs'\nimport path from 'node:path'\nimport { regExpPathPattern } from '../../../common/functions'\nimport { FILE_OPERATION } from '../../files/constants/operations'\nimport { FileError } from '../../files/models/file-error'\nimport { LockConflict } from '../../files/models/file-lock-error'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { checksumFile, isPathExists, isPathIsDir, removeFiles, touchFile } from '../../files/utils/files'\nimport { SendFile } from '../../files/utils/send-file'\nimport { ParseDiffContext } from '../../spaces/interfaces/space-diff.interface'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { UserModel } from '../../users/models/user.model'\nimport { F_SPECIAL_STAT, F_STAT, SYNC_CHECKSUM_ALG, SYNC_DIFF_DONE } from '../constants/sync'\nimport { SyncCopyMoveDto, SyncDiffDto, SyncMakeDto, SyncPropsDto } from '../dtos/sync-operations.dto'\nimport { SyncUploadDto } from '../dtos/sync-upload.dto'\nimport { SyncFileSpecialStats, SyncFileStats } from '../interfaces/sync-diff.interface'\nimport { SyncPathSettings } from '../interfaces/sync-path.interface'\nimport { getTmpFilePath } from '../utils/functions'\nimport { SYNC_PATH_TO_SPACE_SEGMENTS } from '../utils/routes'\nimport { SyncQueries } from './sync-queries.service'\n\n@Injectable()\nexport class SyncManager {\n private readonly logger = new Logger(SyncManager.name)\n\n constructor(\n private readonly spacesManager: SpacesManager,\n private readonly filesManager: FilesManager,\n private readonly syncQueries: SyncQueries\n ) {}\n\n async download(req: FastifySpaceRequest, res: FastifyReply): Promise<StreamableFile> {\n const sendFile: SendFile = this.filesManager.sendFileFromSpace(req.space)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n this.handleError(req.space, req.method, e)\n }\n }\n\n async upload(req: FastifySpaceRequest, syncUploadDto: SyncUploadDto): Promise<{ ino: number }> {\n const tmpPath = getTmpFilePath(req.space.realPath)\n try {\n if (syncUploadDto.checksum) {\n const checksum = await this.filesManager.saveStream(req.user, req.space, req, { tmpPath: tmpPath, checksumAlg: SYNC_CHECKSUM_ALG })\n if (checksum !== syncUploadDto.checksum) {\n await removeFiles(tmpPath)\n this.handleError(req.space, req.method, new FileError(HttpStatus.BAD_REQUEST, 'checksums are not identical'))\n }\n } else {\n await this.filesManager.saveStream(req.user, req.space, req, { tmpPath: tmpPath })\n }\n const fileStats = await fs.stat(req.space.realPath)\n if (fileStats.size !== syncUploadDto.size) {\n await removeFiles(tmpPath)\n this.handleError(\n req.space,\n req.method,\n new FileError(HttpStatus.BAD_REQUEST, `sizes are not identical : ${fileStats.size} != ${syncUploadDto.size}`)\n )\n }\n // update mtime\n await touchFile(req.space.realPath, syncUploadDto.mtime)\n // return inode number\n return { ino: fileStats.ino }\n } catch (e) {\n this.handleError(req.space, req.method, e)\n }\n }\n\n async delete(req: FastifySpaceRequest): Promise<void> {\n try {\n return await this.filesManager.delete(req.user, req.space)\n } catch (e) {\n this.handleError(req.space, FILE_OPERATION.DELETE, e)\n }\n }\n\n async props(req: FastifySpaceRequest, syncPropsDto: SyncPropsDto): Promise<void> {\n try {\n await this.filesManager.touch(req.user, req.space, syncPropsDto.mtime, false)\n } catch (e) {\n this.handleError(req.space, FILE_OPERATION.TOUCH, e)\n }\n }\n\n async make(req: FastifySpaceRequest, syncMakeDto: SyncMakeDto): Promise<{ ino: number }> {\n try {\n if (syncMakeDto.type === 'directory') {\n await this.filesManager.mkDir(req.user, req.space, true)\n } else {\n await this.filesManager.mkFile(req.user, req.space, true)\n }\n await touchFile(req.space.realPath, syncMakeDto.mtime)\n return { ino: (await fs.stat(req.space.realPath)).ino }\n } catch (e) {\n this.handleError(req.space, `${FILE_OPERATION.MAKE} ${syncMakeDto.type}`, e)\n }\n }\n\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: true): Promise<void>\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: false): Promise<{ ino: number; mtime: number }>\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: boolean): Promise<void | { ino: number; mtime: number }> {\n const dstSpace: SpaceEnv = await this.spacesManager.spaceEnv(req.user, SYNC_PATH_TO_SPACE_SEGMENTS(syncCopyMoveDto.destination))\n try {\n await this.filesManager.copyMove(req.user, req.space, dstSpace, isMove, true)\n if (!isMove) {\n if (syncCopyMoveDto.mtime) {\n // update mtime\n await touchFile(dstSpace.realPath, syncCopyMoveDto.mtime)\n }\n // return inode & mtime\n const stats = await fs.stat(dstSpace.realPath)\n return { ino: stats.ino, mtime: Math.floor(stats.mtime.getTime() / 1000) }\n }\n } catch (e) {\n this.handleError(req.space, isMove ? FILE_OPERATION.MOVE : FILE_OPERATION.COPY, e, dstSpace)\n }\n }\n\n async diff(user: UserModel, pathId: number, syncDiff: SyncDiffDto, res: FastifyReply): Promise<void> {\n if (!user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n const syncPathSettings: SyncPathSettings = await this.syncQueries.getPathSettings(user.clientId, pathId)\n if (!syncPathSettings) {\n throw new HttpException('Path not found', HttpStatus.NOT_FOUND)\n }\n let space: SpaceEnv\n try {\n space = await this.spacesManager.spaceEnv(user, SYNC_PATH_TO_SPACE_SEGMENTS(syncPathSettings.remotePath))\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n if (!space) {\n throw new HttpException('Space not found', HttpStatus.NOT_FOUND)\n }\n if (space.quotaIsExceeded) {\n throw new HttpException('Space quota is exceeded', HttpStatus.INSUFFICIENT_STORAGE)\n }\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException(`Remote path not found : ${syncPathSettings.remotePath}`, HttpStatus.NOT_FOUND)\n }\n if (!(await isPathIsDir(space.realPath))) {\n throw new HttpException('Remote path must be a directory', HttpStatus.BAD_REQUEST)\n }\n // start\n res.raw.writeHead(200, {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Transfer-Encoding': 'chunked'\n })\n try {\n for await (const f of this.parseSyncPath(space, syncDiff)) {\n res.raw.write(`${JSON.stringify(f)}\\n`)\n }\n res.raw.write(SYNC_DIFF_DONE)\n } catch (e) {\n this.logger.error(`${this.diff.name} : ${e.message}`)\n res.raw.write(`${e.message}\\n`)\n res.status(HttpStatus.INTERNAL_SERVER_ERROR)\n }\n res.raw.end()\n }\n\n private async *parseSyncPath(space: SpaceEnv, syncDiff: SyncDiffDto): AsyncGenerator<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n const context: ParseDiffContext = {\n regexBasePath: regExpPathPattern(space.realPath),\n syncDiff: syncDiff\n }\n yield* this.parseFiles(space.realPath, context)\n }\n\n private async *parseFiles(dir: string, ctx: ParseDiffContext): AsyncGenerator<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n try {\n for (const entry of await fs.readdir(dir, { withFileTypes: true })) {\n const realPath = path.join(entry.parentPath, entry.name)\n if (!entry.isDirectory() && !entry.isFile()) {\n this.logger.log(`${this.parseFiles.name} - ignore special file: ${realPath}`)\n continue\n }\n if (entry.isDirectory()) {\n const dirStats: Record<string, SyncFileStats | SyncFileSpecialStats> = await this.analyzeFile(entry, ctx)\n if (dirStats !== null) {\n yield dirStats\n }\n yield* this.parseFiles(realPath, ctx)\n } else {\n const fileStats: Record<string, SyncFileStats | SyncFileSpecialStats> = await this.analyzeFile(entry, ctx)\n if (fileStats !== null) {\n yield fileStats\n }\n }\n }\n } catch (e) {\n this.logger.error(`${this.parseFiles.name} - unable to parse directory : ${dir} : ${e}`)\n throw new Error('Unable to parse path')\n }\n }\n\n private async analyzeFile(entry: Dirent, ctx: ParseDiffContext): Promise<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n if (ctx.syncDiff.defaultFilters.has(entry.name)) {\n return null\n }\n\n const realPath = path.join(entry.parentPath, entry.name)\n const filePath = realPath.replace(ctx.regexBasePath, '')\n\n let stats: Stats\n try {\n stats = await fs.stat(realPath)\n } catch (e) {\n this.logger.warn(`${this.analyzeFile.name} - unable to get file stats : ${realPath} : ${e}`)\n return { [filePath]: [F_SPECIAL_STAT.ERROR, e.toString()] }\n }\n\n if (ctx.syncDiff.pathFilters && ctx.syncDiff.pathFilters.test(filePath)) {\n this.logger.verbose(`${this.analyzeFile.name} - ignore filtered file : ${realPath}`)\n return { [filePath]: [F_SPECIAL_STAT.FILTERED, stats.isDirectory()] }\n }\n\n const fileStats: SyncFileStats = [\n stats.isDirectory(),\n stats.isDirectory() ? 0 : stats.size,\n Math.floor(stats.mtime.getTime() / 1000),\n stats.ino,\n null\n ]\n if (ctx.syncDiff.secureDiff && !fileStats[F_STAT.IS_DIR]) {\n try {\n await this.checkSumFile(ctx, filePath, realPath, fileStats)\n } catch (e) {\n this.logger.error(`${this.analyzeFile.name} - file error : ${realPath} - ${e}`)\n return { [filePath]: [F_SPECIAL_STAT.ERROR, e.toString()] }\n }\n }\n return { [filePath]: fileStats }\n }\n\n private async checkSumFile(ctx: ParseDiffContext, filePath: string, realPath: string, fileStats: SyncFileStats): Promise<void> {\n if (!ctx.syncDiff.firstSync && ctx.syncDiff.snapshot.has(filePath)) {\n const snapFileStats: SyncFileStats = ctx.syncDiff.snapshot.get(filePath)\n if (\n snapFileStats[F_STAT.CHECKSUM] &&\n snapFileStats[F_STAT.MTIME] == fileStats[F_STAT.MTIME] &&\n snapFileStats[F_STAT.SIZE] == fileStats[F_STAT.SIZE] &&\n snapFileStats[F_STAT.INO] == fileStats[F_STAT.INO]\n ) {\n fileStats[F_STAT.CHECKSUM] = snapFileStats[F_STAT.CHECKSUM]\n return\n }\n }\n fileStats[F_STAT.CHECKSUM] = await checksumFile(realPath, SYNC_CHECKSUM_ALG)\n }\n\n private handleError(space: SpaceEnv, action: string, e: any, dstSpace?: SpaceEnv) {\n this.logger.error(`unable to ${action} ${space.url}${dstSpace?.url ? ` -> ${dstSpace.url}` : ''} : ${e}`)\n if (e instanceof LockConflict) {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n } else if (e instanceof FileError) {\n throw new HttpException(e.message, e.httpCode)\n }\n throw new HttpException(e.message, HttpStatus.INTERNAL_SERVER_ERROR)\n }\n}\n"],"names":["SyncManager","download","req","res","sendFile","filesManager","sendFileFromSpace","space","checks","stream","e","handleError","method","upload","syncUploadDto","tmpPath","getTmpFilePath","realPath","checksum","saveStream","user","checksumAlg","SYNC_CHECKSUM_ALG","removeFiles","FileError","HttpStatus","BAD_REQUEST","fileStats","fs","stat","size","touchFile","mtime","ino","delete","FILE_OPERATION","DELETE","props","syncPropsDto","touch","TOUCH","make","syncMakeDto","type","mkDir","mkFile","MAKE","copyMove","syncCopyMoveDto","isMove","dstSpace","spacesManager","spaceEnv","SYNC_PATH_TO_SPACE_SEGMENTS","destination","stats","Math","floor","getTime","MOVE","COPY","diff","pathId","syncDiff","clientId","HttpException","syncPathSettings","syncQueries","getPathSettings","NOT_FOUND","remotePath","message","quotaIsExceeded","INSUFFICIENT_STORAGE","isPathExists","isPathIsDir","raw","writeHead","f","parseSyncPath","write","JSON","stringify","SYNC_DIFF_DONE","logger","error","name","status","INTERNAL_SERVER_ERROR","end","context","regexBasePath","regExpPathPattern","parseFiles","dir","ctx","entry","readdir","withFileTypes","path","join","parentPath","isDirectory","isFile","log","dirStats","analyzeFile","Error","defaultFilters","has","filePath","replace","warn","F_SPECIAL_STAT","ERROR","toString","pathFilters","test","verbose","FILTERED","secureDiff","F_STAT","IS_DIR","checkSumFile","firstSync","snapshot","snapFileStats","get","CHECKSUM","MTIME","SIZE","INO","checksumFile","action","url","LockConflict","LOCKED","httpCode","Logger"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../backend/src/applications/sync/services/sync-manager.service.ts"],"sourcesContent":["/*\n * Copyright (C) 2012-2025 Johan Legrand <johan.legrand@sync-in.com>\n * This file is part of Sync-in | The open source file sync and share solution\n * See the LICENSE file for licensing details\n */\n\nimport { HttpException, HttpStatus, Injectable, Logger, StreamableFile } from '@nestjs/common'\nimport { FastifyReply } from 'fastify'\nimport fs from 'fs/promises'\nimport { Dirent, Stats } from 'node:fs'\nimport path from 'node:path'\nimport { regExpPathPattern } from '../../../common/functions'\nimport { FILE_OPERATION } from '../../files/constants/operations'\nimport { FileError } from '../../files/models/file-error'\nimport { LockConflict } from '../../files/models/file-lock-error'\nimport { FilesManager } from '../../files/services/files-manager.service'\nimport { checksumFile, isPathExists, isPathIsDir, removeFiles, touchFile } from '../../files/utils/files'\nimport { SendFile } from '../../files/utils/send-file'\nimport { ParseDiffContext } from '../../spaces/interfaces/space-diff.interface'\nimport { FastifySpaceRequest } from '../../spaces/interfaces/space-request.interface'\nimport { SpaceEnv } from '../../spaces/models/space-env.model'\nimport { SpacesManager } from '../../spaces/services/spaces-manager.service'\nimport { UserModel } from '../../users/models/user.model'\nimport { F_SPECIAL_STAT, F_STAT, SYNC_CHECKSUM_ALG, SYNC_DIFF_DONE } from '../constants/sync'\nimport { SyncCopyMoveDto, SyncDiffDto, SyncMakeDto, SyncPropsDto } from '../dtos/sync-operations.dto'\nimport { SyncUploadDto } from '../dtos/sync-upload.dto'\nimport { SyncFileSpecialStats, SyncFileStats } from '../interfaces/sync-diff.interface'\nimport { SyncPathSettings } from '../interfaces/sync-path.interface'\nimport { getTmpFilePath } from '../utils/functions'\nimport { SYNC_PATH_TO_SPACE_SEGMENTS } from '../utils/routes'\nimport { SyncQueries } from './sync-queries.service'\n\n@Injectable()\nexport class SyncManager {\n private readonly logger = new Logger(SyncManager.name)\n\n constructor(\n private readonly spacesManager: SpacesManager,\n private readonly filesManager: FilesManager,\n private readonly syncQueries: SyncQueries\n ) {}\n\n async download(req: FastifySpaceRequest, res: FastifyReply): Promise<StreamableFile> {\n const sendFile: SendFile = this.filesManager.sendFileFromSpace(req.space)\n try {\n await sendFile.checks()\n return await sendFile.stream(req, res)\n } catch (e) {\n this.handleError(req.space, req.method, e)\n }\n }\n\n async upload(req: FastifySpaceRequest, syncUploadDto: SyncUploadDto): Promise<{ ino: number }> {\n const tmpPath = getTmpFilePath(req.space.realPath)\n try {\n if (syncUploadDto.checksum) {\n const checksum = await this.filesManager.saveStream(req.user, req.space, req, { tmpPath: tmpPath, checksumAlg: SYNC_CHECKSUM_ALG })\n if (checksum !== syncUploadDto.checksum) {\n await removeFiles(tmpPath)\n this.handleError(req.space, req.method, new FileError(HttpStatus.BAD_REQUEST, 'checksums are not identical'))\n }\n } else {\n await this.filesManager.saveStream(req.user, req.space, req, { tmpPath: tmpPath })\n }\n const fileStats = await fs.stat(req.space.realPath)\n if (fileStats.size !== syncUploadDto.size) {\n await removeFiles(tmpPath)\n this.handleError(\n req.space,\n req.method,\n new FileError(HttpStatus.BAD_REQUEST, `sizes are not identical : ${fileStats.size} != ${syncUploadDto.size}`)\n )\n }\n // update mtime\n await touchFile(req.space.realPath, syncUploadDto.mtime)\n // return inode number\n return { ino: fileStats.ino }\n } catch (e) {\n this.handleError(req.space, req.method, e)\n }\n }\n\n async delete(req: FastifySpaceRequest): Promise<void> {\n try {\n return await this.filesManager.delete(req.user, req.space)\n } catch (e) {\n this.handleError(req.space, FILE_OPERATION.DELETE, e)\n }\n }\n\n async props(req: FastifySpaceRequest, syncPropsDto: SyncPropsDto): Promise<void> {\n try {\n await this.filesManager.touch(req.user, req.space, syncPropsDto.mtime, false)\n } catch (e) {\n this.handleError(req.space, FILE_OPERATION.TOUCH, e)\n }\n }\n\n async make(req: FastifySpaceRequest, syncMakeDto: SyncMakeDto): Promise<{ ino: number }> {\n try {\n if (syncMakeDto.type === 'directory') {\n await this.filesManager.mkDir(req.user, req.space, true)\n } else {\n await this.filesManager.mkFile(req.user, req.space, true)\n }\n await touchFile(req.space.realPath, syncMakeDto.mtime)\n return { ino: (await fs.stat(req.space.realPath)).ino }\n } catch (e) {\n this.handleError(req.space, `${FILE_OPERATION.MAKE} ${syncMakeDto.type}`, e)\n }\n }\n\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: true): Promise<void>\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: false): Promise<{ ino: number; mtime: number }>\n async copyMove(req: FastifySpaceRequest, syncCopyMoveDto: SyncCopyMoveDto, isMove: boolean): Promise<void | { ino: number; mtime: number }> {\n const dstSpace: SpaceEnv = await this.spacesManager.spaceEnv(req.user, SYNC_PATH_TO_SPACE_SEGMENTS(syncCopyMoveDto.destination))\n try {\n await this.filesManager.copyMove(req.user, req.space, dstSpace, isMove, true, true)\n if (!isMove) {\n if (syncCopyMoveDto.mtime) {\n // update mtime\n await touchFile(dstSpace.realPath, syncCopyMoveDto.mtime)\n }\n // return inode & mtime\n const stats = await fs.stat(dstSpace.realPath)\n return { ino: stats.ino, mtime: Math.floor(stats.mtime.getTime() / 1000) }\n }\n } catch (e) {\n this.handleError(req.space, isMove ? FILE_OPERATION.MOVE : FILE_OPERATION.COPY, e, dstSpace)\n }\n }\n\n async diff(user: UserModel, pathId: number, syncDiff: SyncDiffDto, res: FastifyReply): Promise<void> {\n if (!user.clientId) {\n throw new HttpException('Client id is missing', HttpStatus.BAD_REQUEST)\n }\n const syncPathSettings: SyncPathSettings = await this.syncQueries.getPathSettings(user.clientId, pathId)\n if (!syncPathSettings) {\n throw new HttpException('Path not found', HttpStatus.NOT_FOUND)\n }\n let space: SpaceEnv\n try {\n space = await this.spacesManager.spaceEnv(user, SYNC_PATH_TO_SPACE_SEGMENTS(syncPathSettings.remotePath))\n } catch (e) {\n throw new HttpException(e.message, HttpStatus.BAD_REQUEST)\n }\n if (!space) {\n throw new HttpException('Space not found', HttpStatus.NOT_FOUND)\n }\n if (space.quotaIsExceeded) {\n throw new HttpException('Space quota is exceeded', HttpStatus.INSUFFICIENT_STORAGE)\n }\n if (!(await isPathExists(space.realPath))) {\n throw new HttpException(`Remote path not found : ${syncPathSettings.remotePath}`, HttpStatus.NOT_FOUND)\n }\n if (!(await isPathIsDir(space.realPath))) {\n throw new HttpException('Remote path must be a directory', HttpStatus.BAD_REQUEST)\n }\n // start\n res.raw.writeHead(200, {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Transfer-Encoding': 'chunked'\n })\n try {\n for await (const f of this.parseSyncPath(space, syncDiff)) {\n res.raw.write(`${JSON.stringify(f)}\\n`)\n }\n res.raw.write(SYNC_DIFF_DONE)\n } catch (e) {\n this.logger.error(`${this.diff.name} : ${e.message}`)\n res.raw.write(`${e.message}\\n`)\n res.status(HttpStatus.INTERNAL_SERVER_ERROR)\n }\n res.raw.end()\n }\n\n private async *parseSyncPath(space: SpaceEnv, syncDiff: SyncDiffDto): AsyncGenerator<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n const context: ParseDiffContext = {\n regexBasePath: regExpPathPattern(space.realPath),\n syncDiff: syncDiff\n }\n yield* this.parseFiles(space.realPath, context)\n }\n\n private async *parseFiles(dir: string, ctx: ParseDiffContext): AsyncGenerator<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n try {\n for (const entry of await fs.readdir(dir, { withFileTypes: true })) {\n const realPath = path.join(entry.parentPath, entry.name)\n if (!entry.isDirectory() && !entry.isFile()) {\n this.logger.log(`${this.parseFiles.name} - ignore special file: ${realPath}`)\n continue\n }\n if (entry.isDirectory()) {\n const dirStats: Record<string, SyncFileStats | SyncFileSpecialStats> = await this.analyzeFile(entry, ctx)\n if (dirStats !== null) {\n yield dirStats\n }\n yield* this.parseFiles(realPath, ctx)\n } else {\n const fileStats: Record<string, SyncFileStats | SyncFileSpecialStats> = await this.analyzeFile(entry, ctx)\n if (fileStats !== null) {\n yield fileStats\n }\n }\n }\n } catch (e) {\n this.logger.error(`${this.parseFiles.name} - unable to parse directory : ${dir} : ${e}`)\n throw new Error('Unable to parse path')\n }\n }\n\n private async analyzeFile(entry: Dirent, ctx: ParseDiffContext): Promise<Record<string, SyncFileStats | SyncFileSpecialStats>> {\n if (ctx.syncDiff.defaultFilters.has(entry.name)) {\n return null\n }\n\n const realPath = path.join(entry.parentPath, entry.name)\n const filePath = realPath.replace(ctx.regexBasePath, '')\n\n let stats: Stats\n try {\n stats = await fs.stat(realPath)\n } catch (e) {\n this.logger.warn(`${this.analyzeFile.name} - unable to get file stats : ${realPath} : ${e}`)\n return { [filePath]: [F_SPECIAL_STAT.ERROR, e.toString()] }\n }\n\n if (ctx.syncDiff.pathFilters && ctx.syncDiff.pathFilters.test(filePath)) {\n this.logger.verbose(`${this.analyzeFile.name} - ignore filtered file : ${realPath}`)\n return { [filePath]: [F_SPECIAL_STAT.FILTERED, stats.isDirectory()] }\n }\n\n const fileStats: SyncFileStats = [\n stats.isDirectory(),\n stats.isDirectory() ? 0 : stats.size,\n Math.floor(stats.mtime.getTime() / 1000),\n stats.ino,\n null\n ]\n if (ctx.syncDiff.secureDiff && !fileStats[F_STAT.IS_DIR]) {\n try {\n await this.checkSumFile(ctx, filePath, realPath, fileStats)\n } catch (e) {\n this.logger.error(`${this.analyzeFile.name} - file error : ${realPath} - ${e}`)\n return { [filePath]: [F_SPECIAL_STAT.ERROR, e.toString()] }\n }\n }\n return { [filePath]: fileStats }\n }\n\n private async checkSumFile(ctx: ParseDiffContext, filePath: string, realPath: string, fileStats: SyncFileStats): Promise<void> {\n if (!ctx.syncDiff.firstSync && ctx.syncDiff.snapshot.has(filePath)) {\n const snapFileStats: SyncFileStats = ctx.syncDiff.snapshot.get(filePath)\n if (\n snapFileStats[F_STAT.CHECKSUM] &&\n snapFileStats[F_STAT.MTIME] == fileStats[F_STAT.MTIME] &&\n snapFileStats[F_STAT.SIZE] == fileStats[F_STAT.SIZE] &&\n snapFileStats[F_STAT.INO] == fileStats[F_STAT.INO]\n ) {\n fileStats[F_STAT.CHECKSUM] = snapFileStats[F_STAT.CHECKSUM]\n return\n }\n }\n fileStats[F_STAT.CHECKSUM] = await checksumFile(realPath, SYNC_CHECKSUM_ALG)\n }\n\n private handleError(space: SpaceEnv, action: string, e: any, dstSpace?: SpaceEnv) {\n this.logger.error(`unable to ${action} ${space.url}${dstSpace?.url ? ` -> ${dstSpace.url}` : ''} : ${e}`)\n if (e instanceof LockConflict) {\n throw new HttpException('The file is locked', HttpStatus.LOCKED)\n } else if (e instanceof FileError) {\n throw new HttpException(e.message, e.httpCode)\n }\n throw new HttpException(e.message, HttpStatus.INTERNAL_SERVER_ERROR)\n }\n}\n"],"names":["SyncManager","download","req","res","sendFile","filesManager","sendFileFromSpace","space","checks","stream","e","handleError","method","upload","syncUploadDto","tmpPath","getTmpFilePath","realPath","checksum","saveStream","user","checksumAlg","SYNC_CHECKSUM_ALG","removeFiles","FileError","HttpStatus","BAD_REQUEST","fileStats","fs","stat","size","touchFile","mtime","ino","delete","FILE_OPERATION","DELETE","props","syncPropsDto","touch","TOUCH","make","syncMakeDto","type","mkDir","mkFile","MAKE","copyMove","syncCopyMoveDto","isMove","dstSpace","spacesManager","spaceEnv","SYNC_PATH_TO_SPACE_SEGMENTS","destination","stats","Math","floor","getTime","MOVE","COPY","diff","pathId","syncDiff","clientId","HttpException","syncPathSettings","syncQueries","getPathSettings","NOT_FOUND","remotePath","message","quotaIsExceeded","INSUFFICIENT_STORAGE","isPathExists","isPathIsDir","raw","writeHead","f","parseSyncPath","write","JSON","stringify","SYNC_DIFF_DONE","logger","error","name","status","INTERNAL_SERVER_ERROR","end","context","regexBasePath","regExpPathPattern","parseFiles","dir","ctx","entry","readdir","withFileTypes","path","join","parentPath","isDirectory","isFile","log","dirStats","analyzeFile","Error","defaultFilters","has","filePath","replace","warn","F_SPECIAL_STAT","ERROR","toString","pathFilters","test","verbose","FILTERED","secureDiff","F_STAT","IS_DIR","checkSumFile","firstSync","snapshot","snapFileStats","get","CHECKSUM","MTIME","SIZE","INO","checksumFile","action","url","LockConflict","LOCKED","httpCode","Logger"],"mappings":"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"}
|