download.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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" href="#">Delete</a>\
  20. </div>\
  21. </div>\
  22. ',
  23. init: function () {
  24. $(document).on('click', '#editpaste', this.editpaste.bind(this))
  25. },
  26. route: function (route, content) {
  27. if (content != 'noref') {
  28. return this
  29. }
  30. },
  31. render: function (view) {
  32. view.html(this.template)
  33. this._ = {}
  34. this._.view = view
  35. this._.detailsarea = view.find('#downloaddetails')
  36. this._.filename = view.find('#downloaded_filename')
  37. this._.btns = view.find('#btnarea')
  38. this._.deletebtn = view.find('#deletebtn')
  39. this._.dlbtn = view.find('#dlbtn')
  40. this._.viewbtn = view.find('#inbrowserbtn')
  41. this._.viewswitcher = view.find('.viewswitcher')
  42. this._.newupload = view.find('#newupload')
  43. this._.editpaste = view.find('#editpaste')
  44. this._.dlarea = view.find('#dlarea')
  45. this._.title = $('title')
  46. $('#footer').hide()
  47. },
  48. initroute: function (content) {
  49. delete this._['text']
  50. this._.filename.hide()
  51. this._.title.text("Up1")
  52. this._.btns.hide()
  53. this._.editpaste.hide()
  54. this._.newupload.hide()
  55. this._.content = {}
  56. this._.content.main = this._.content.loading = $('<h1>').prop('id', 'downloadprogress').text('Downloading')
  57. this._.detailsarea.empty().append(this._.content.main)
  58. this._.deletebtn.hide()
  59. upload.updown.download(content, this.progress.bind(this), this.downloaded.bind(this))
  60. },
  61. unrender: function () {
  62. this._.title.text('Up1')
  63. delete this['_']
  64. },
  65. /* These mimes are trusted, anything not on this list will not embed
  66. nor provide view in browser links. Some embed exceptions apply
  67. like svg will embed but will not directly link and pdf vice versa.
  68. ALl text mime types support view in browser and translate to text/plain */
  69. assocations: {
  70. 'application/javascript': 'text',
  71. 'application/x-javascript': 'text',
  72. 'application/xml': 'text',
  73. 'image/svg+xml': 'svg',
  74. // PDF for now only offers 'view in browser'
  75. 'application/pdf': 'pdf',
  76. 'application/x-pdf': 'pdf',
  77. 'text/plain': 'text',
  78. 'audio/aac': 'audio',
  79. 'audio/mp4': 'audio',
  80. 'audio/mpeg': 'audio',
  81. 'audio/ogg': 'audio',
  82. 'audio/wav': 'audio',
  83. 'audio/webm': 'audio',
  84. 'video/mp4': 'video',
  85. 'video/ogg': 'video',
  86. 'video/webm': 'video',
  87. 'audio/wave': 'audio',
  88. 'audio/wav': 'audio',
  89. 'audio/x-wav': 'audio',
  90. 'audio/x-pn-wav': 'audio',
  91. 'audio/vnd.wave': 'audio',
  92. 'image/tiff': 'image',
  93. 'image/x-tiff': 'image',
  94. 'image/bmp': 'image',
  95. 'image/x-windows-bmp': 'image',
  96. 'image/gif': 'image',
  97. 'image/x-icon': 'image',
  98. 'image/jpeg': 'image',
  99. 'image/pjpeg': 'image',
  100. 'image/png': 'image',
  101. 'image/webp': 'image',
  102. 'text/': 'text'
  103. },
  104. // Mime types to use for "View in browser" for safety reasons such as html we use text/plain
  105. // Other display types such as PDF and images you want native viewing so we leave those
  106. // SVG can be unsafe for viewing in a browser directly
  107. safeassocations: {
  108. 'text': 'text/plain',
  109. 'svg': 'text/plain'
  110. },
  111. getassociation: function(mime) {
  112. for (var key in this.assocations) {
  113. if (mime.startsWith(key)) {
  114. return this.assocations[key]
  115. }
  116. }
  117. },
  118. setupLineNumbers: function(ele) {
  119. var markup = ele.html()
  120. ele.html('<div class="line">' + markup.replace(/\n/g, '</div><div class="line">') + '</div>')
  121. ele.find('.line').each(function(i, e) {
  122. $(e).prepend($('<span>').addClass('linenum').text(i + 1))
  123. })
  124. },
  125. downloaded: function (data) {
  126. this._.filename.text(data.header.name)
  127. this._.title.text(data.header.name + ' - Up1')
  128. var stored = this.delkeys[data.ident]
  129. if (!stored) {
  130. try {
  131. stored = localStorage.getItem('delete-' + data.ident)
  132. } catch (e) {
  133. console.log(e)
  134. }
  135. }
  136. if (stored && !isiframed()) {
  137. this._.deletebtn.show().prop('href', (upload.config.server ? upload.config.server : '') + 'del?delkey=' + stored + '&ident=' + data.ident)
  138. }
  139. this._.newupload.show()
  140. var association = this.getassociation(data.header.mime)
  141. var safemime = this.safeassocations[association]
  142. var decrypted = new Blob([data.decrypted], { type: data.header.mime })
  143. var safedecrypted = new Blob([decrypted], { type: safemime ? safemime : data.header.mime })
  144. var url = URL.createObjectURL(decrypted)
  145. var safeurl = URL.createObjectURL(safedecrypted)
  146. this._.viewbtn.prop('href', safeurl).hide()
  147. this._.dlbtn.prop('href', url)
  148. this._.dlbtn.prop('download', data.header.name)
  149. delete this._['content']
  150. this._.detailsarea.empty()
  151. if (!!association) {
  152. this._.viewbtn.show()
  153. }
  154. if (association == 'image' || association == 'svg') {
  155. var imgcontent = $('<div>').prop('id', 'previewimg').addClass('preview').appendTo(this._.detailsarea)
  156. var previewimg = $('<img>').addClass('dragresize').appendTo(imgcontent).prop('src', url)
  157. } else if (association == 'text') {
  158. var textcontent = $('<div>').prop('id', 'downloaded_text').addClass('preview').addClass('previewtext').appendTo(this._.detailsarea)
  159. var pre = $('<pre>').appendTo(textcontent)
  160. var code = $('<code>').appendTo(pre)
  161. var fr = new FileReader()
  162. fr.onload = function () {
  163. var text = fr.result
  164. this._.text = {}
  165. this._.text.header = data.header
  166. this._.text.data = text
  167. code.text(text)
  168. hljs.highlightBlock(code[0])
  169. this.setupLineNumbers(code)
  170. }.bind(this)
  171. fr.readAsText(data.decrypted)
  172. this._.editpaste.show()
  173. } else if (association == 'video') {
  174. $('<video>').addClass('preview').prop('controls', true).prop('autoplay', true).appendTo(this._.detailsarea).prop('src', url)
  175. } else if (association == 'audio') {
  176. $('<audio>').addClass('preview').prop('controls', true).prop('autoplay', true).appendTo(this._.detailsarea).prop('src', url)
  177. } else {
  178. $('<div>').addClass('preview').addClass('downloadexplain').text("Click the Download link in the bottom-left to download this file.").appendTo(this._.detailsarea)
  179. }
  180. this._.filename.show()
  181. this._.btns.show()
  182. },
  183. closepaste: function() {
  184. this._.dlarea.show()
  185. },
  186. editpaste: function() {
  187. this._.dlarea.hide()
  188. upload.textpaste.render(this._.view, this._.text.header.name, this._.text.data, this._.text.header.mime, this.closepaste.bind(this))
  189. },
  190. progress: function (e) {
  191. if (e == 'decrypting') {
  192. this._.content.loading.text('Decrypting')
  193. } else if (e == 'error') {
  194. this._.content.loading.text('File not found or corrupt')
  195. this._.newupload.show()
  196. } else {
  197. var text = ''
  198. if (e.eventsource != 'encrypt') {
  199. text = 'Downloading'
  200. } else {
  201. text = 'Decrypting'
  202. }
  203. var percent = (e.loaded / e.total) * 100
  204. this._.content.loading.text(text + ' ' + Math.floor(percent) + '%')
  205. }
  206. }
  207. })