download.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. upload.load.need('js/dragresize.js', function() { return window.dragresize })
  2. upload.modules.addmodule({
  3. name: 'download',
  4. delkeys: {},
  5. // Dear santa, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings
  6. template: '\
  7. <div class="modulecontent" id="dlarea">\
  8. <div class="topbar">\
  9. <h1 id="downloaded_filename"></h1>\
  10. <div class="viewswitcher">\
  11. <a id="editpaste" class="btn">Edit Paste</a\
  12. ><a class="btn" id="newupload" href="#">New Upload</a>\
  13. </div>\
  14. </div>\
  15. <div id="downloaddetails"></div>\
  16. <div id="btnarea">\
  17. <a class="btn" id="dlbtn" href="#">Download</a\
  18. ><a class="btn" id="inbrowserbtn" target="_blank" href="#">View In Browser</a\
  19. ><a class="btn" id="deletebtn" >Delete</a\
  20. ><div class="right"><a class="btn" id="prevbtn" href="#">Prev</a\
  21. ><a class="btn" id="nextbtn" href="#">Next</a\
  22. ><a class="btn" id="helpbtn" >Help</a\
  23. ><a class="dbtn" id="donatemebtn" target="_blank" href="#">Donate</a\
  24. ></div>\
  25. </div>\
  26. <div id="donatemearea" class="donate"><img src="donate.png">\
  27. </div>\
  28. <div id="deleted" class="deleted"><h1>File successfully deleted</h1>\
  29. </div>\
  30. <div id="helparea" class="help">&nbsp;To share this file, copy and send the link that appears in your browser\'s adress bar.<br><br><br><br>\
  31. "New Upload" : click to upload another file<br><br>\
  32. "Download" : click to download the file to your local drive<br><br>\
  33. "View in Browser" : click to view the file in full size<br><br>\
  34. "Delete" : only visible if you are the uploader : delete Safeshare link<br><br>\
  35. "Help" : hover to display this help<br><br>\
  36. "Donate" : hover to display bitcoin donation adress qrcode , click to send a donation to support SafeShare development\
  37. </div>\
  38. </div>\
  39. ',
  40. init: function () {
  41. $(document).on('click', '#editpaste', this.editpaste.bind(this))
  42. $(document).on('mouseover', '#helpbtn', this.help.bind(this))
  43. $(document).on('mouseout', '#helpbtn', this.help.bind(this))
  44. $(document).on('mouseover', '#donatemebtn', this.donateme.bind(this))
  45. $(document).on('mouseout', '#donatemebtn', this.donateme.bind(this))
  46. $(document).on('click', '#deletebtn', this.deletefile.bind(this))
  47. },
  48. route: function (route, content) {
  49. if (content != 'noref') {
  50. return this
  51. }
  52. },
  53. render: function (view) {
  54. view.html(this.template)
  55. this._ = {}
  56. this._.view = view
  57. this._.detailsarea = view.find('#downloaddetails')
  58. this._.filename = view.find('#downloaded_filename')
  59. this._.btns = view.find('#btnarea')
  60. this._.deletebtn = view.find('#deletebtn')
  61. this._.deleted = view.find('#deleted')
  62. this._.donatemebtn = view.find('#donatemebtn')
  63. this._.dlbtn = view.find('#dlbtn')
  64. this._.nextbtn = view.find('#nextbtn')
  65. this._.prevbtn = view.find('#prevbtn')
  66. this._.viewbtn = view.find('#inbrowserbtn')
  67. this._.helpbtn = view.find('#helpbtn')
  68. this._.viewswitcher = view.find('.viewswitcher')
  69. this._.newupload = view.find('#newupload')
  70. this._.editpaste = view.find('#editpaste')
  71. this._.dlarea = view.find('#dlarea')
  72. this._.help = view.find('#helparea')
  73. this._.title = $('title')
  74. this._.donatemearea = view.find('#donatemearea')
  75. $('#footer').hide()
  76. $('#waiting').hide()
  77. $('#helparea').hide()
  78. $('#donatemearea').hide()
  79. $('#deleted').hide()
  80. },
  81. initroute: function (content, contentroot) {
  82. contentroot = contentroot ? contentroot : content
  83. this._.nextbtn.hide()
  84. this._.prevbtn.hide()
  85. if (contentroot.indexOf('&') > -1) {
  86. var which = 0
  87. var values = contentroot.split('&')
  88. var howmany = values.length
  89. if (content != contentroot) {
  90. which = parseInt(content) - 1
  91. }
  92. content = values[which]
  93. this._.nextbtn.attr('href', '#' + contentroot + '/' + (which + 2))
  94. this._.prevbtn.attr('href', '#' + contentroot + '/' + (which))
  95. if (!(which >= howmany - 1)) {
  96. this._.nextbtn.show()
  97. }
  98. if (!(which <= 0)) {
  99. this._.prevbtn.show()
  100. }
  101. }
  102. //console.log('contentroot: ' ,contentroot)
  103. //console.log('content: ' , content )
  104. delete this._['text']
  105. this._.help.hide()
  106. this._.filename.hide()
  107. this._.title.text("SafeShare")
  108. this._.btns.hide()
  109. this._.editpaste.hide()
  110. this._.newupload.hide()
  111. this._.content = {}
  112. this._.content.main = this._.content.loading = $('<h1>').prop('id', 'downloadprogress').addClass('centertext centerable').text('Downloading')
  113. this._.detailsarea.empty().append(this._.content.main)
  114. this._.deletebtn.hide()
  115. this._.deleted.hide()
  116. upload.updown.download(content, this.progress.bind(this), this.downloaded.bind(this))
  117. },
  118. unrender: function () {
  119. this._.title.text('SafeShare')
  120. delete this['_']
  121. },
  122. /* These mimes are trusted, anything not on this list will not embed
  123. nor provide view in browser links. Some embed exceptions apply
  124. like svg will embed but will not directly link and pdf vice versa.
  125. ALl text mime types support view in browser and translate to text/plain */
  126. assocations: {
  127. 'application/javascript': 'text',
  128. 'application/x-javascript': 'text',
  129. 'application/xml': 'text',
  130. 'image/svg+xml': 'svg',
  131. // PDF for now only offers 'view in browser'
  132. 'application/pdf': 'pdf',
  133. 'application/x-pdf': 'pdf',
  134. 'text/plain': 'text',
  135. 'audio/aac': 'audio',
  136. 'audio/mp4': 'audio',
  137. 'audio/mpeg': 'audio',
  138. 'audio/ogg': 'audio',
  139. 'audio/wav': 'audio',
  140. 'audio/webm': 'audio',
  141. 'video/mp4': 'video',
  142. 'video/ogg': 'video',
  143. 'video/webm': 'video',
  144. 'audio/wave': 'audio',
  145. 'audio/wav': 'audio',
  146. 'audio/x-wav': 'audio',
  147. 'audio/x-pn-wav': 'audio',
  148. 'audio/vnd.wave': 'audio',
  149. 'image/tiff': 'image',
  150. 'image/x-tiff': 'image',
  151. 'image/bmp': 'image',
  152. 'image/x-windows-bmp': 'image',
  153. 'image/gif': 'image',
  154. 'image/x-icon': 'image',
  155. 'image/jpeg': 'image',
  156. 'image/pjpeg': 'image',
  157. 'image/png': 'image',
  158. 'image/webp': 'image',
  159. 'text/': 'text'
  160. },
  161. // Mime types to use for "View in browser" for safety reasons such as html we use text/plain
  162. // Other display types such as PDF and images you want native viewing so we leave those
  163. // SVG can be unsafe for viewing in a browser directly
  164. safeassocations: {
  165. 'text': 'text/plain',
  166. 'svg': 'text/plain'
  167. },
  168. getassociation: function(mime) {
  169. for (var key in this.assocations) {
  170. if (mime.startsWith(key)) {
  171. return this.assocations[key]
  172. }
  173. }
  174. },
  175. setupLineNumbers: function(ele) {
  176. var markup = ele.html()
  177. ele.html('<div class="line">' + markup.replace(/\n/g, '</div><div class="line">') + '</div>')
  178. ele.find('.line').each(function(i, e) {
  179. $(e).prepend($('<span>').addClass('linenum').text(i + 1))
  180. })
  181. },
  182. downloaded: function (data) {
  183. this._.filename.text(data.header.name)
  184. this._.title.text(data.header.name + ' - SafeShare')
  185. var stored = this.delkeys[data.ident]
  186. if (!stored) {
  187. try {
  188. stored = localStorage.getItem('delete-' + data.ident)
  189. } catch (e) {
  190. console.log(e)
  191. }
  192. }
  193. try {
  194. localStorage.setItem('delkey' , stored)
  195. } catch (e) {
  196. console.log(e)
  197. }
  198. if (stored && !isiframed()) {
  199. this._.deletebtn.show()
  200. }
  201. this._.newupload.show()
  202. var association = this.getassociation(data.header.mime)
  203. var safemime = this.safeassocations[association]
  204. var decrypted = new Blob([data.decrypted], { type: data.header.mime })
  205. var safedecrypted = new Blob([decrypted], { type: safemime ? safemime : data.header.mime })
  206. var url = URL.createObjectURL(decrypted)
  207. var safeurl = URL.createObjectURL(safedecrypted)
  208. this._.viewbtn.prop('href', safeurl).hide()
  209. this._.dlbtn.prop('href', url)
  210. this._.dlbtn.prop('download', data.header.name)
  211. this._.donatemebtn.prop('href', upload.config.donate_key )
  212. delete this._['content']
  213. this._.detailsarea.empty()
  214. if (!!association) {
  215. this._.viewbtn.show()
  216. }
  217. if (association == 'image' || association == 'svg') {
  218. var imgcontent = $('<div>').prop('id', 'previewimg').addClass('preview centerable').appendTo(this._.detailsarea)
  219. var previewimg = $('<img>').addClass('dragresize').appendTo(imgcontent).prop('src', url)
  220. } else if (association == 'text') {
  221. var textcontent = $('<div>').prop('id', 'downloaded_text').addClass('preview').addClass('previewtext').appendTo(this._.detailsarea)
  222. var pre = $('<pre>').appendTo(textcontent)
  223. var code = $('<code>').appendTo(pre)
  224. var fr = new FileReader()
  225. fr.onload = function () {
  226. var text = fr.result
  227. this._.text = {}
  228. this._.text.header = data.header
  229. this._.text.data = text
  230. code.text(text)
  231. hljs.highlightBlock(code[0])
  232. this.setupLineNumbers(code)
  233. }.bind(this)
  234. fr.readAsText(data.decrypted)
  235. this._.editpaste.show()
  236. } else if (association == 'video') {
  237. $('<div>').addClass('preview centerable').append($('<video>').prop('controls', true).prop('autoplay', true).prop('src', url)).appendTo(this._.detailsarea)
  238. } else if (association == 'audio') {
  239. $('<div>').addClass('preview centerable').append($('<audio>').prop('controls', true).prop('autoplay', true).prop('src', url)).appendTo(this._.detailsarea)
  240. } else {
  241. $('<div>').addClass('preview').addClass('downloadexplain centerable centertext').text("Click the Download link in the bottom-left to download this file.").appendTo(this._.detailsarea)
  242. }
  243. this._.filename.show()
  244. this._.btns.show()
  245. },
  246. closepaste: function() {
  247. this._.dlarea.show()
  248. },
  249. editpaste: function() {
  250. this._.dlarea.hide()
  251. upload.textpaste.render(this._.view, this._.text.header.name, this._.text.data, this._.text.header.mime, this.closepaste.bind(this))
  252. },
  253. help: function() {
  254. //console.log ( 'help' );
  255. if( $("#helparea").is(":visible") == false )
  256. { this._.help.show();this._.detailsarea.hide();} else
  257. { this._.help.hide();this._.detailsarea.show();
  258. }
  259. },
  260. donateme: function() {
  261. //console.log ( 'donateme' );
  262. if( $("#donatemearea").is(":visible") == false )
  263. { this._.donatemearea.show();this._.detailsarea.hide();} else
  264. { this._.donatemearea.hide();this._.detailsarea.show();
  265. }
  266. },
  267. deletefile: function() {
  268. filename = localStorage.getItem('delkey' ) ;
  269. //console.log ( 'delete : ident : ', filename );
  270. deletename ( filename )
  271. this._.detailsarea.hide();
  272. this._.btns.hide();
  273. this._.filename.hide();
  274. this._.editpaste.hide()
  275. this._.deleted.show();
  276. },
  277. progress: function (e) {
  278. if (e == 'decrypting') {
  279. this._.content.loading.text('Decrypting')
  280. } else if (e == 'error') {
  281. this._.content.loading.text('File not found or corrupt')
  282. this._.newupload.show()
  283. } else {
  284. var text = ''
  285. if (e.eventsource != 'encrypt') {
  286. text = 'Downloading'
  287. } else {
  288. text = 'Decrypting'
  289. }
  290. var percent = (e.loaded / e.total) * 100
  291. this._.content.loading.text(text + ' ' + Math.floor(percent) + '%')
  292. }
  293. }
  294. })