drg_default_html_editor 0.4.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (458) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +3 -0
  4. data/Rakefile +40 -0
  5. data/app/assets/images/elfinder/arrows-active.png +0 -0
  6. data/app/assets/images/elfinder/arrows-normal.png +0 -0
  7. data/app/assets/images/elfinder/crop.gif +0 -0
  8. data/app/assets/images/elfinder/dialogs.png +0 -0
  9. data/app/assets/images/elfinder/icons-big.png +0 -0
  10. data/app/assets/images/elfinder/icons-small.png +0 -0
  11. data/app/assets/images/elfinder/progress.gif +0 -0
  12. data/app/assets/images/elfinder/quicklook-bg.png +0 -0
  13. data/app/assets/images/elfinder/quicklook-icons.png +0 -0
  14. data/app/assets/images/elfinder/resize.png +0 -0
  15. data/app/assets/images/elfinder/spinner-mini.gif +0 -0
  16. data/app/assets/images/elfinder/toolbar.png +0 -0
  17. data/app/assets/javascripts/drg_default_html_editor/ckeditor/CHANGES.md +612 -0
  18. data/app/assets/javascripts/drg_default_html_editor/ckeditor/LICENSE.md +1264 -0
  19. data/app/assets/javascripts/drg_default_html_editor/ckeditor/README.md +39 -0
  20. data/app/assets/javascripts/drg_default_html_editor/ckeditor/adapters/jquery.js +10 -0
  21. data/app/assets/javascripts/drg_default_html_editor/ckeditor/build-config.js +173 -0
  22. data/app/assets/javascripts/drg_default_html_editor/ckeditor/ckeditor.js +993 -0
  23. data/app/assets/javascripts/drg_default_html_editor/ckeditor/config.js +10 -0
  24. data/app/assets/javascripts/drg_default_html_editor/ckeditor/contents.css +134 -0
  25. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/af.js +5 -0
  26. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ar.js +5 -0
  27. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/bg.js +5 -0
  28. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/bn.js +5 -0
  29. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/bs.js +5 -0
  30. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ca.js +5 -0
  31. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/cs.js +5 -0
  32. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/cy.js +5 -0
  33. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/da.js +5 -0
  34. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/de.js +5 -0
  35. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/el.js +5 -0
  36. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/en-au.js +5 -0
  37. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/en-ca.js +5 -0
  38. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/en-gb.js +5 -0
  39. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/en.js +5 -0
  40. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/eo.js +5 -0
  41. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/es.js +5 -0
  42. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/et.js +5 -0
  43. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/eu.js +5 -0
  44. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/fa.js +5 -0
  45. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/fi.js +5 -0
  46. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/fo.js +5 -0
  47. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/fr-ca.js +5 -0
  48. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/fr.js +5 -0
  49. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/gl.js +5 -0
  50. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/gu.js +5 -0
  51. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/he.js +5 -0
  52. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/hi.js +5 -0
  53. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/hr.js +5 -0
  54. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/hu.js +5 -0
  55. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/id.js +5 -0
  56. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/is.js +5 -0
  57. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/it.js +5 -0
  58. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ja.js +5 -0
  59. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ka.js +5 -0
  60. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/km.js +5 -0
  61. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ko.js +5 -0
  62. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ku.js +5 -0
  63. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/lt.js +5 -0
  64. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/lv.js +5 -0
  65. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/mk.js +5 -0
  66. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/mn.js +5 -0
  67. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ms.js +5 -0
  68. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/nb.js +5 -0
  69. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/nl.js +5 -0
  70. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/no.js +5 -0
  71. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/pl.js +5 -0
  72. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/pt-br.js +5 -0
  73. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/pt.js +5 -0
  74. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ro.js +5 -0
  75. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ru.js +5 -0
  76. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/si.js +5 -0
  77. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sk.js +5 -0
  78. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sl.js +5 -0
  79. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sq.js +5 -0
  80. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sr-latn.js +5 -0
  81. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sr.js +5 -0
  82. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/sv.js +5 -0
  83. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/th.js +5 -0
  84. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/tr.js +5 -0
  85. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/tt.js +5 -0
  86. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/ug.js +5 -0
  87. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/uk.js +5 -0
  88. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/vi.js +5 -0
  89. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/zh-cn.js +5 -0
  90. data/app/assets/javascripts/drg_default_html_editor/ckeditor/lang/zh.js +5 -0
  91. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/a11yhelp.js +10 -0
  92. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/_translationstatus.txt +25 -0
  93. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ar.js +11 -0
  94. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/bg.js +11 -0
  95. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ca.js +13 -0
  96. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/cs.js +13 -0
  97. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/cy.js +11 -0
  98. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/da.js +11 -0
  99. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/de.js +12 -0
  100. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/el.js +13 -0
  101. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/en-gb.js +11 -0
  102. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/en.js +11 -0
  103. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/eo.js +13 -0
  104. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/es.js +12 -0
  105. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/et.js +11 -0
  106. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/fa.js +11 -0
  107. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/fi.js +12 -0
  108. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/fr-ca.js +12 -0
  109. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/fr.js +13 -0
  110. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/gl.js +12 -0
  111. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/gu.js +11 -0
  112. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/he.js +11 -0
  113. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/hi.js +11 -0
  114. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/hr.js +11 -0
  115. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/hu.js +13 -0
  116. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/id.js +11 -0
  117. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/it.js +13 -0
  118. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ja.js +9 -0
  119. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/km.js +11 -0
  120. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ko.js +10 -0
  121. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ku.js +12 -0
  122. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/lt.js +11 -0
  123. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/lv.js +13 -0
  124. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/mk.js +11 -0
  125. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/mn.js +11 -0
  126. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/nb.js +12 -0
  127. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/nl.js +12 -0
  128. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/no.js +11 -0
  129. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/pl.js +13 -0
  130. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/pt-br.js +12 -0
  131. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/pt.js +12 -0
  132. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ro.js +12 -0
  133. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ru.js +11 -0
  134. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/si.js +10 -0
  135. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sk.js +12 -0
  136. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sl.js +12 -0
  137. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sq.js +11 -0
  138. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sr-latn.js +11 -0
  139. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sr.js +11 -0
  140. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/sv.js +12 -0
  141. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/th.js +11 -0
  142. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/tr.js +12 -0
  143. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/tt.js +11 -0
  144. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/ug.js +11 -0
  145. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/uk.js +12 -0
  146. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/vi.js +11 -0
  147. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/zh-cn.js +9 -0
  148. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/a11yhelp/dialogs/lang/zh.js +10 -0
  149. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/about/dialogs/about.js +7 -0
  150. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/about/dialogs/hidpi/logo_ckeditor.png +0 -0
  151. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/about/dialogs/logo_ckeditor.png +0 -0
  152. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/clipboard/dialogs/paste.js +11 -0
  153. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/colordialog/dialogs/colordialog.js +13 -0
  154. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/dialog/dialogDefinition.js +4 -0
  155. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/div/dialogs/div.js +9 -0
  156. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/find/dialogs/find.js +24 -0
  157. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/flash/dialogs/flash.js +24 -0
  158. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/flash/images/placeholder.png +0 -0
  159. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/button.js +8 -0
  160. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/checkbox.js +8 -0
  161. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/form.js +8 -0
  162. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/hiddenfield.js +8 -0
  163. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/radio.js +8 -0
  164. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/select.js +20 -0
  165. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/textarea.js +8 -0
  166. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/dialogs/textfield.js +10 -0
  167. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/forms/images/hiddenfield.gif +0 -0
  168. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/icons.png +0 -0
  169. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/icons_hidpi.png +0 -0
  170. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/iframe/dialogs/iframe.js +10 -0
  171. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/iframe/images/placeholder.png +0 -0
  172. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/image/dialogs/image.js +43 -0
  173. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/image/images/noimage.png +0 -0
  174. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/link/dialogs/anchor.js +7 -0
  175. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/link/dialogs/link.js +26 -0
  176. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/link/images/anchor.png +0 -0
  177. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/link/images/hidpi/anchor.png +0 -0
  178. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/liststyle/dialogs/liststyle.js +10 -0
  179. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/magicline/images/hidpi/icon.png +0 -0
  180. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/magicline/images/icon.png +0 -0
  181. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/pagebreak/images/pagebreak.gif +0 -0
  182. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/pastefromword/filter/default.js +31 -0
  183. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/preview/preview.html +13 -0
  184. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/scayt/LICENSE.md +28 -0
  185. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/scayt/README.md +25 -0
  186. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/scayt/dialogs/options.js +17 -0
  187. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/scayt/dialogs/toolbar.css +71 -0
  188. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_address.png +0 -0
  189. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_blockquote.png +0 -0
  190. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_div.png +0 -0
  191. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h1.png +0 -0
  192. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h2.png +0 -0
  193. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h3.png +0 -0
  194. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h4.png +0 -0
  195. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h5.png +0 -0
  196. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_h6.png +0 -0
  197. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_p.png +0 -0
  198. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/showblocks/images/block_pre.png +0 -0
  199. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/dialogs/smiley.js +10 -0
  200. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/angel_smile.gif +0 -0
  201. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/angel_smile.png +0 -0
  202. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/angry_smile.gif +0 -0
  203. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/angry_smile.png +0 -0
  204. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/broken_heart.gif +0 -0
  205. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/broken_heart.png +0 -0
  206. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/confused_smile.gif +0 -0
  207. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/confused_smile.png +0 -0
  208. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/cry_smile.gif +0 -0
  209. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/cry_smile.png +0 -0
  210. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/devil_smile.gif +0 -0
  211. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/devil_smile.png +0 -0
  212. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/embaressed_smile.gif +0 -0
  213. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/embarrassed_smile.gif +0 -0
  214. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/embarrassed_smile.png +0 -0
  215. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/envelope.gif +0 -0
  216. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/envelope.png +0 -0
  217. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/heart.gif +0 -0
  218. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/heart.png +0 -0
  219. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/kiss.gif +0 -0
  220. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/kiss.png +0 -0
  221. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/lightbulb.gif +0 -0
  222. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/lightbulb.png +0 -0
  223. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/omg_smile.gif +0 -0
  224. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/omg_smile.png +0 -0
  225. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/regular_smile.gif +0 -0
  226. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/regular_smile.png +0 -0
  227. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/sad_smile.gif +0 -0
  228. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/sad_smile.png +0 -0
  229. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/shades_smile.gif +0 -0
  230. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/shades_smile.png +0 -0
  231. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/teeth_smile.gif +0 -0
  232. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/teeth_smile.png +0 -0
  233. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/thumbs_down.gif +0 -0
  234. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/thumbs_down.png +0 -0
  235. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/thumbs_up.gif +0 -0
  236. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/thumbs_up.png +0 -0
  237. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/tongue_smile.gif +0 -0
  238. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/tongue_smile.png +0 -0
  239. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/tounge_smile.gif +0 -0
  240. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.gif +0 -0
  241. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/whatchutalkingabout_smile.png +0 -0
  242. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/wink_smile.gif +0 -0
  243. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/smiley/images/wink_smile.png +0 -0
  244. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/_translationstatus.txt +20 -0
  245. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ar.js +13 -0
  246. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/bg.js +13 -0
  247. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ca.js +14 -0
  248. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/cs.js +13 -0
  249. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/cy.js +14 -0
  250. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/de.js +13 -0
  251. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/el.js +13 -0
  252. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/en-gb.js +13 -0
  253. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/en.js +13 -0
  254. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/eo.js +12 -0
  255. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/es.js +13 -0
  256. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/et.js +13 -0
  257. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/fa.js +12 -0
  258. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/fi.js +13 -0
  259. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/fr-ca.js +10 -0
  260. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/fr.js +11 -0
  261. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/gl.js +13 -0
  262. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/he.js +12 -0
  263. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/hr.js +13 -0
  264. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/hu.js +12 -0
  265. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/id.js +13 -0
  266. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/it.js +14 -0
  267. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ja.js +9 -0
  268. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/km.js +13 -0
  269. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ku.js +13 -0
  270. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/lv.js +13 -0
  271. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/nb.js +11 -0
  272. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/nl.js +13 -0
  273. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/no.js +11 -0
  274. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/pl.js +12 -0
  275. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/pt-br.js +11 -0
  276. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/pt.js +13 -0
  277. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ru.js +13 -0
  278. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/si.js +13 -0
  279. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/sk.js +13 -0
  280. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/sl.js +12 -0
  281. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/sq.js +13 -0
  282. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/sv.js +11 -0
  283. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/th.js +13 -0
  284. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/tr.js +12 -0
  285. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/tt.js +13 -0
  286. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/ug.js +13 -0
  287. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/uk.js +12 -0
  288. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/vi.js +14 -0
  289. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/zh-cn.js +9 -0
  290. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/lang/zh.js +12 -0
  291. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/specialchar/dialogs/specialchar.js +14 -0
  292. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/table/dialogs/table.js +21 -0
  293. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/tabletools/dialogs/tableCell.js +17 -0
  294. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/dialogs/templates.css +84 -0
  295. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/dialogs/templates.js +10 -0
  296. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/templates/default.js +6 -0
  297. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/templates/images/template1.gif +0 -0
  298. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/templates/images/template2.gif +0 -0
  299. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/templates/templates/images/template3.gif +0 -0
  300. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/LICENSE.md +28 -0
  301. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/README.md +25 -0
  302. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/dialogs/ciframe.html +66 -0
  303. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/dialogs/tmpFrameset.html +52 -0
  304. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/dialogs/wsc.css +82 -0
  305. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/dialogs/wsc.js +74 -0
  306. data/app/assets/javascripts/drg_default_html_editor/ckeditor/plugins/wsc/dialogs/wsc_ie.js +11 -0
  307. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/ajax.html +82 -0
  308. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/api.html +207 -0
  309. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/appendto.html +56 -0
  310. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/assets/inlineall/logo.png +0 -0
  311. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/assets/outputxhtml/outputxhtml.css +204 -0
  312. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/assets/posteddata.php +59 -0
  313. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/assets/sample.jpg +0 -0
  314. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/assets/uilanguages/languages.js +7 -0
  315. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/datafiltering.html +401 -0
  316. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/divreplace.html +141 -0
  317. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/index.html +128 -0
  318. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/inlineall.html +311 -0
  319. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/inlinebycode.html +121 -0
  320. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/inlinetextarea.html +110 -0
  321. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/jquery.html +100 -0
  322. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/dialog/assets/my_dialog.js +48 -0
  323. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/dialog/dialog.html +187 -0
  324. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/enterkey/enterkey.html +103 -0
  325. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/outputforflash.fla +0 -0
  326. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/outputforflash.swf +0 -0
  327. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/htmlwriter/assets/outputforflash/swfobject.js +18 -0
  328. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/htmlwriter/outputforflash.html +280 -0
  329. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/htmlwriter/outputhtml.html +221 -0
  330. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/magicline/magicline.html +206 -0
  331. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/toolbar/toolbar.html +232 -0
  332. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/plugins/wysiwygarea/fullpage.html +77 -0
  333. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/readonly.html +73 -0
  334. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/replacebyclass.html +57 -0
  335. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/replacebycode.html +56 -0
  336. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/sample.css +365 -0
  337. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/sample.js +50 -0
  338. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/sample_posteddata.php +16 -0
  339. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/tabindex.html +75 -0
  340. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/uicolor.html +69 -0
  341. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/uilanguages.html +119 -0
  342. data/app/assets/javascripts/drg_default_html_editor/ckeditor/samples/xhtmlstyle.html +231 -0
  343. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/dialog.css +5 -0
  344. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/dialog_ie.css +5 -0
  345. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/dialog_ie7.css +5 -0
  346. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/dialog_ie8.css +5 -0
  347. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/dialog_iequirks.css +5 -0
  348. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor.css +5 -0
  349. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor_gecko.css +5 -0
  350. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor_ie.css +5 -0
  351. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor_ie7.css +5 -0
  352. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor_ie8.css +5 -0
  353. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/editor_iequirks.css +5 -0
  354. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/icons.png +0 -0
  355. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/icons_hidpi.png +0 -0
  356. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/arrow.png +0 -0
  357. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/close.png +0 -0
  358. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/hidpi/close.png +0 -0
  359. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/hidpi/lock-open.png +0 -0
  360. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/hidpi/lock.png +0 -0
  361. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/hidpi/refresh.png +0 -0
  362. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/lock-open.png +0 -0
  363. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/lock.png +0 -0
  364. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/images/refresh.png +0 -0
  365. data/app/assets/javascripts/drg_default_html_editor/ckeditor/skins/moono/readme.md +51 -0
  366. data/app/assets/javascripts/drg_default_html_editor/ckeditor/styles.js +111 -0
  367. data/app/assets/javascripts/drg_default_html_editor/elfinder/Changelog.txt +63 -0
  368. data/app/assets/javascripts/drg_default_html_editor/elfinder/README.md +118 -0
  369. data/app/assets/javascripts/drg_default_html_editor/elfinder/css/elfinder.min.css +9 -0
  370. data/app/assets/javascripts/drg_default_html_editor/elfinder/css/theme.css +49 -0
  371. data/app/assets/javascripts/drg_default_html_editor/elfinder/elfinder.html +56 -0
  372. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/arrows-active.png +0 -0
  373. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/arrows-normal.png +0 -0
  374. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/crop.gif +0 -0
  375. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/dialogs.png +0 -0
  376. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/icons-big.png +0 -0
  377. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/icons-small.png +0 -0
  378. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/progress.gif +0 -0
  379. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/quicklook-bg.png +0 -0
  380. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/quicklook-icons.png +0 -0
  381. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/resize.png +0 -0
  382. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/spinner-mini.gif +0 -0
  383. data/app/assets/javascripts/drg_default_html_editor/elfinder/img/toolbar.png +0 -0
  384. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/elfinder.min.js +25 -0
  385. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/elfinder.min_1.js +25 -0
  386. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.LANG.js +348 -0
  387. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.ar.js +290 -0
  388. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.bg.js +310 -0
  389. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.ca.js +310 -0
  390. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.cs.js +285 -0
  391. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.de.js +280 -0
  392. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.es.js +291 -0
  393. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.fr.js +298 -0
  394. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.hu.js +280 -0
  395. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.jp.js +316 -0
  396. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.nl.js +342 -0
  397. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.no.js +280 -0
  398. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.pl.js +309 -0
  399. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.pt_BR.js +280 -0
  400. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.ru.js +344 -0
  401. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.sl.js +348 -0
  402. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/i18n/elfinder.zh_CN.js +280 -0
  403. data/app/assets/javascripts/drg_default_html_editor/elfinder/js/proxy/elFinderSupportVer1.js +338 -0
  404. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/MySQLStorage.sql +23 -0
  405. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/connector.php +44 -0
  406. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/elFinder.class.php +1103 -0
  407. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/elFinderConnector.class.php +133 -0
  408. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/elFinderVolumeDriver.class.php +3370 -0
  409. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/elFinderVolumeLocalFileSystem.class.php +835 -0
  410. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/elFinderVolumeMySQL.class.php +896 -0
  411. data/app/assets/javascripts/drg_default_html_editor/elfinder/php/mime.types +512 -0
  412. data/app/assets/javascripts/drg_default_html_editor_application.js +7 -0
  413. data/app/assets/javascripts/drg_default_html_editor_cms.js +14 -0
  414. data/app/assets/stylesheets/drg_default_html_editor/elfinder.min.css +9 -0
  415. data/app/assets/stylesheets/drg_default_html_editor_application.css +11 -0
  416. data/app/assets/stylesheets/drg_default_html_editor_cms.css +21 -0
  417. data/app/controllers/dc_elfinder_controller.rb +58 -0
  418. data/config/initializers/patch_drgcms_form_field.rb +96 -0
  419. data/config/initializers/patch_for_elfinder.rb +114 -0
  420. data/config/routes.rb +2 -0
  421. data/lib/drg_default_html_editor/engine.rb +14 -0
  422. data/lib/drg_default_html_editor/version.rb +3 -0
  423. data/lib/drg_default_html_editor.rb +6 -0
  424. data/lib/drg_default_html_editor.rb~ +6 -0
  425. data/lib/tasks/drg_default_html_editor_copy_assets.rake +10 -0
  426. data/lib/tasks/drg_default_html_editor_tasks.rake +4 -0
  427. data/test/drg_default_html_editor_test.rb +7 -0
  428. data/test/dummy/README.rdoc +261 -0
  429. data/test/dummy/Rakefile +7 -0
  430. data/test/dummy/app/assets/javascripts/application.js +15 -0
  431. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  432. data/test/dummy/app/controllers/application_controller.rb +3 -0
  433. data/test/dummy/app/helpers/application_helper.rb +2 -0
  434. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  435. data/test/dummy/config/application.rb +59 -0
  436. data/test/dummy/config/boot.rb +10 -0
  437. data/test/dummy/config/database.yml +25 -0
  438. data/test/dummy/config/environment.rb +5 -0
  439. data/test/dummy/config/environments/development.rb +37 -0
  440. data/test/dummy/config/environments/production.rb +67 -0
  441. data/test/dummy/config/environments/test.rb +37 -0
  442. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  443. data/test/dummy/config/initializers/inflections.rb +15 -0
  444. data/test/dummy/config/initializers/mime_types.rb +5 -0
  445. data/test/dummy/config/initializers/secret_token.rb +7 -0
  446. data/test/dummy/config/initializers/session_store.rb +8 -0
  447. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  448. data/test/dummy/config/locales/en.yml +5 -0
  449. data/test/dummy/config/routes.rb +58 -0
  450. data/test/dummy/config.ru +4 -0
  451. data/test/dummy/public/404.html +26 -0
  452. data/test/dummy/public/422.html +26 -0
  453. data/test/dummy/public/500.html +25 -0
  454. data/test/dummy/public/favicon.ico +0 -0
  455. data/test/dummy/script/rails +6 -0
  456. data/test/integration/navigation_test.rb +10 -0
  457. data/test/test_helper.rb +15 -0
  458. metadata +574 -0
@@ -0,0 +1,3370 @@
1
+ <?php
2
+ /**
3
+ * Base class for elFinder volume.
4
+ * Provide 2 layers:
5
+ * 1. Public API (commands)
6
+ * 2. abstract fs API
7
+ *
8
+ * All abstract methods begin with "_"
9
+ *
10
+ * @author Dmitry (dio) Levashov
11
+ * @author Troex Nevelin
12
+ * @author Alexey Sukhotin
13
+ **/
14
+ abstract class elFinderVolumeDriver {
15
+
16
+ /**
17
+ * Driver id
18
+ * Must be started from letter and contains [a-z0-9]
19
+ * Used as part of volume id
20
+ *
21
+ * @var string
22
+ **/
23
+ protected $driverId = 'a';
24
+
25
+ /**
26
+ * Volume id - used as prefix for files hashes
27
+ *
28
+ * @var string
29
+ **/
30
+ protected $id = '';
31
+
32
+ /**
33
+ * Flag - volume "mounted" and available
34
+ *
35
+ * @var bool
36
+ **/
37
+ protected $mounted = false;
38
+
39
+ /**
40
+ * Root directory path
41
+ *
42
+ * @var string
43
+ **/
44
+ protected $root = '';
45
+
46
+ /**
47
+ * Root basename | alias
48
+ *
49
+ * @var string
50
+ **/
51
+ protected $rootName = '';
52
+
53
+ /**
54
+ * Default directory to open
55
+ *
56
+ * @var string
57
+ **/
58
+ protected $startPath = '';
59
+
60
+ /**
61
+ * Base URL
62
+ *
63
+ * @var string
64
+ **/
65
+ protected $URL = '';
66
+
67
+ /**
68
+ * Thumbnails dir path
69
+ *
70
+ * @var string
71
+ **/
72
+ protected $tmbPath = '';
73
+
74
+ /**
75
+ * Is thumbnails dir writable
76
+ *
77
+ * @var bool
78
+ **/
79
+ protected $tmbPathWritable = false;
80
+
81
+ /**
82
+ * Thumbnails base URL
83
+ *
84
+ * @var string
85
+ **/
86
+ protected $tmbURL = '';
87
+
88
+ /**
89
+ * Thumbnails size in px
90
+ *
91
+ * @var int
92
+ **/
93
+ protected $tmbSize = 48;
94
+
95
+ /**
96
+ * Image manipulation lib name
97
+ * auto|imagick|mogtify|gd
98
+ *
99
+ * @var string
100
+ **/
101
+ protected $imgLib = 'auto';
102
+
103
+ /**
104
+ * Library to crypt files name
105
+ *
106
+ * @var string
107
+ **/
108
+ protected $cryptLib = '';
109
+
110
+ /**
111
+ * Archivers config
112
+ *
113
+ * @var array
114
+ **/
115
+ protected $archivers = array(
116
+ 'create' => array(),
117
+ 'extract' => array()
118
+ );
119
+
120
+ /**
121
+ * How many subdirs levels return for tree
122
+ *
123
+ * @var int
124
+ **/
125
+ protected $treeDeep = 1;
126
+
127
+ /**
128
+ * Errors from last failed action
129
+ *
130
+ * @var array
131
+ **/
132
+ protected $error = array();
133
+
134
+ /**
135
+ * Today 24:00 timestamp
136
+ *
137
+ * @var int
138
+ **/
139
+ protected $today = 0;
140
+
141
+ /**
142
+ * Yesterday 24:00 timestamp
143
+ *
144
+ * @var int
145
+ **/
146
+ protected $yesterday = 0;
147
+
148
+ /**
149
+ * Object configuration
150
+ *
151
+ * @var array
152
+ **/
153
+ protected $options = array(
154
+ 'id' => '',
155
+ // root directory path
156
+ 'path' => '',
157
+ // open this path on initial request instead of root path
158
+ 'startPath' => '',
159
+ // how many subdirs levels return per request
160
+ 'treeDeep' => 1,
161
+ // root url, not set to disable sending URL to client (replacement for old "fileURL" option)
162
+ 'URL' => '',
163
+ // directory separator. required by client to show paths correctly
164
+ 'separator' => DIRECTORY_SEPARATOR,
165
+ // library to crypt/uncrypt files names (not implemented)
166
+ 'cryptLib' => '',
167
+ // how to detect files mimetypes. (auto/internal/finfo/mime_content_type)
168
+ 'mimeDetect' => 'auto',
169
+ // mime.types file path (for mimeDetect==internal)
170
+ 'mimefile' => '',
171
+ // directory for thumbnails
172
+ 'tmbPath' => '.tmb',
173
+ // mode to create thumbnails dir
174
+ 'tmbPathMode' => 0777,
175
+ // thumbnails dir URL. Set it if store thumbnails outside root directory
176
+ 'tmbURL' => '',
177
+ // thumbnails size (px)
178
+ 'tmbSize' => 48,
179
+ // thumbnails crop (true - crop, false - scale image to fit thumbnail size)
180
+ 'tmbCrop' => true,
181
+ // thumbnails background color (hex #rrggbb or 'transparent')
182
+ 'tmbBgColor' => '#ffffff',
183
+ // image manipulations library
184
+ 'imgLib' => 'auto',
185
+ // on paste file - if true - old file will be replaced with new one, if false new file get name - original_name-number.ext
186
+ 'copyOverwrite' => true,
187
+ // if true - join new and old directories content on paste
188
+ 'copyJoin' => true,
189
+ // on upload - if true - old file will be replaced with new one, if false new file get name - original_name-number.ext
190
+ 'uploadOverwrite' => true,
191
+ // mimetypes allowed to upload
192
+ 'uploadAllow' => array(),
193
+ // mimetypes not allowed to upload
194
+ 'uploadDeny' => array(),
195
+ // order to proccess uploadAllow and uploadDeny options
196
+ 'uploadOrder' => array('deny', 'allow'),
197
+ // maximum upload file size. NOTE - this is size for every uploaded files
198
+ 'uploadMaxSize' => 0,
199
+ // files dates format
200
+ 'dateFormat' => 'j M Y H:i',
201
+ // files time format
202
+ 'timeFormat' => 'H:i',
203
+ // if true - every folder will be check for children folders, otherwise all folders will be marked as having subfolders
204
+ 'checkSubfolders' => true,
205
+ // allow to copy from this volume to other ones?
206
+ 'copyFrom' => true,
207
+ // allow to copy from other volumes to this one?
208
+ 'copyTo' => true,
209
+ // list of commands disabled on this root
210
+ 'disabled' => array(),
211
+ // regexp or function name to validate new file name
212
+ 'acceptedName' => '/^\w[\w\s\.\%\-\(\)\[\]]*$/u',
213
+ // function/class method to control files permissions
214
+ 'accessControl' => null,
215
+ // some data required by access control
216
+ 'accessControlData' => null,
217
+ // default permissions. not set hidden/locked here - take no effect
218
+ 'defaults' => array(
219
+ 'read' => true,
220
+ 'write' => true
221
+ ),
222
+ // files attributes
223
+ 'attributes' => array(),
224
+ // Allowed archive's mimetypes to create. Leave empty for all available types.
225
+ 'archiveMimes' => array(),
226
+ // Manual config for archivers. See example below. Leave empty for auto detect
227
+ 'archivers' => array(),
228
+ // required to fix bug on macos
229
+ 'utf8fix' => false,
230
+ // й ё Й Ё Ø Å
231
+ 'utf8patterns' => array("\u0438\u0306", "\u0435\u0308", "\u0418\u0306", "\u0415\u0308", "\u00d8A", "\u030a"),
232
+ 'utf8replace' => array("\u0439", "\u0451", "\u0419", "\u0401", "\u00d8", "\u00c5")
233
+ );
234
+
235
+ /**
236
+ * Defaults permissions
237
+ *
238
+ * @var array
239
+ **/
240
+ protected $defaults = array(
241
+ 'read' => true,
242
+ 'write' => true,
243
+ 'locked' => false,
244
+ 'hidden' => false
245
+ );
246
+
247
+ /**
248
+ * Access control function/class
249
+ *
250
+ * @var mixed
251
+ **/
252
+ protected $attributes = array();
253
+
254
+ /**
255
+ * Access control function/class
256
+ *
257
+ * @var mixed
258
+ **/
259
+ protected $access = null;
260
+
261
+ /**
262
+ * Mime types allowed to upload
263
+ *
264
+ * @var array
265
+ **/
266
+ protected $uploadAllow = array();
267
+
268
+ /**
269
+ * Mime types denied to upload
270
+ *
271
+ * @var array
272
+ **/
273
+ protected $uploadDeny = array();
274
+
275
+ /**
276
+ * Order to validate uploadAllow and uploadDeny
277
+ *
278
+ * @var array
279
+ **/
280
+ protected $uploadOrder = array();
281
+
282
+ /**
283
+ * Maximum allowed upload file size.
284
+ * Set as number or string with unit - "10M", "500K", "1G"
285
+ *
286
+ * @var int|string
287
+ **/
288
+ protected $uploadMaxSize = 0;
289
+
290
+ /**
291
+ * Mimetype detect method
292
+ *
293
+ * @var string
294
+ **/
295
+ protected $mimeDetect = 'auto';
296
+
297
+ /**
298
+ * Flag - mimetypes from externail file was loaded
299
+ *
300
+ * @var bool
301
+ **/
302
+ private static $mimetypesLoaded = false;
303
+
304
+ /**
305
+ * Finfo object for mimeDetect == 'finfo'
306
+ *
307
+ * @var object
308
+ **/
309
+ protected $finfo = null;
310
+
311
+ /**
312
+ * List of disabled client's commands
313
+ *
314
+ * @var array
315
+ **/
316
+ protected $diabled = array();
317
+
318
+ /**
319
+ * default extensions/mimetypes for mimeDetect == 'internal'
320
+ *
321
+ * @var array
322
+ **/
323
+ protected static $mimetypes = array(
324
+ // applications
325
+ 'ai' => 'application/postscript',
326
+ 'eps' => 'application/postscript',
327
+ 'exe' => 'application/x-executable',
328
+ 'doc' => 'application/vnd.ms-word',
329
+ 'xls' => 'application/vnd.ms-excel',
330
+ 'ppt' => 'application/vnd.ms-powerpoint',
331
+ 'pps' => 'application/vnd.ms-powerpoint',
332
+ 'pdf' => 'application/pdf',
333
+ 'xml' => 'application/xml',
334
+ 'odt' => 'application/vnd.oasis.opendocument.text',
335
+ 'swf' => 'application/x-shockwave-flash',
336
+ 'torrent' => 'application/x-bittorrent',
337
+ 'jar' => 'application/x-jar',
338
+ // archives
339
+ 'gz' => 'application/x-gzip',
340
+ 'tgz' => 'application/x-gzip',
341
+ 'bz' => 'application/x-bzip2',
342
+ 'bz2' => 'application/x-bzip2',
343
+ 'tbz' => 'application/x-bzip2',
344
+ 'zip' => 'application/zip',
345
+ 'rar' => 'application/x-rar',
346
+ 'tar' => 'application/x-tar',
347
+ '7z' => 'application/x-7z-compressed',
348
+ // texts
349
+ 'txt' => 'text/plain',
350
+ 'php' => 'text/x-php',
351
+ 'html' => 'text/html',
352
+ 'htm' => 'text/html',
353
+ 'js' => 'text/javascript',
354
+ 'css' => 'text/css',
355
+ 'rtf' => 'text/rtf',
356
+ 'rtfd' => 'text/rtfd',
357
+ 'py' => 'text/x-python',
358
+ 'java' => 'text/x-java-source',
359
+ 'rb' => 'text/x-ruby',
360
+ 'sh' => 'text/x-shellscript',
361
+ 'pl' => 'text/x-perl',
362
+ 'xml' => 'text/xml',
363
+ 'sql' => 'text/x-sql',
364
+ 'c' => 'text/x-csrc',
365
+ 'h' => 'text/x-chdr',
366
+ 'cpp' => 'text/x-c++src',
367
+ 'hh' => 'text/x-c++hdr',
368
+ 'log' => 'text/plain',
369
+ 'csv' => 'text/x-comma-separated-values',
370
+ // images
371
+ 'bmp' => 'image/x-ms-bmp',
372
+ 'jpg' => 'image/jpeg',
373
+ 'jpeg' => 'image/jpeg',
374
+ 'gif' => 'image/gif',
375
+ 'png' => 'image/png',
376
+ 'tif' => 'image/tiff',
377
+ 'tiff' => 'image/tiff',
378
+ 'tga' => 'image/x-targa',
379
+ 'psd' => 'image/vnd.adobe.photoshop',
380
+ 'ai' => 'image/vnd.adobe.photoshop',
381
+ 'xbm' => 'image/xbm',
382
+ 'pxm' => 'image/pxm',
383
+ //audio
384
+ 'mp3' => 'audio/mpeg',
385
+ 'mid' => 'audio/midi',
386
+ 'ogg' => 'audio/ogg',
387
+ 'oga' => 'audio/ogg',
388
+ 'm4a' => 'audio/x-m4a',
389
+ 'wav' => 'audio/wav',
390
+ 'wma' => 'audio/x-ms-wma',
391
+ // video
392
+ 'avi' => 'video/x-msvideo',
393
+ 'dv' => 'video/x-dv',
394
+ 'mp4' => 'video/mp4',
395
+ 'mpeg' => 'video/mpeg',
396
+ 'mpg' => 'video/mpeg',
397
+ 'mov' => 'video/quicktime',
398
+ 'wm' => 'video/x-ms-wmv',
399
+ 'flv' => 'video/x-flv',
400
+ 'mkv' => 'video/x-matroska',
401
+ 'webm' => 'video/webm',
402
+ 'ogv' => 'video/ogg',
403
+ 'ogm' => 'video/ogg'
404
+ );
405
+
406
+ /**
407
+ * Directory separator - required by client
408
+ *
409
+ * @var string
410
+ **/
411
+ protected $separator = DIRECTORY_SEPARATOR;
412
+
413
+ /**
414
+ * Mimetypes allowed to display
415
+ *
416
+ * @var array
417
+ **/
418
+ protected $onlyMimes = array();
419
+
420
+ /**
421
+ * Store files moved or overwrited files info
422
+ *
423
+ * @var array
424
+ **/
425
+ protected $removed = array();
426
+
427
+ /**
428
+ * Cache storage
429
+ *
430
+ * @var array
431
+ **/
432
+ protected $cache = array();
433
+
434
+ /**
435
+ * Cache by folders
436
+ *
437
+ * @var array
438
+ **/
439
+ protected $dirsCache = array();
440
+
441
+ /*********************************************************************/
442
+ /* INITIALIZATION */
443
+ /*********************************************************************/
444
+
445
+ /**
446
+ * Prepare driver before mount volume.
447
+ * Return true if volume is ready.
448
+ *
449
+ * @return bool
450
+ * @author Dmitry (dio) Levashov
451
+ **/
452
+ protected function init() {
453
+ return true;
454
+ }
455
+
456
+ /**
457
+ * Configure after successfull mount.
458
+ * By default set thumbnails path and image manipulation library.
459
+ *
460
+ * @return void
461
+ * @author Dmitry (dio) Levashov
462
+ **/
463
+ protected function configure() {
464
+ // set thumbnails path
465
+ $path = $this->options['tmbPath'];
466
+ if ($path) {
467
+ if (!file_exists($path)) {
468
+ if (@mkdir($path)) {
469
+ chmod($path, $this->options['tmbPathMode']);
470
+ } else {
471
+ $path = '';
472
+ }
473
+ }
474
+
475
+ if (is_dir($path) && is_readable($path)) {
476
+ $this->tmbPath = $path;
477
+ $this->tmbPathWritable = is_writable($path);
478
+ }
479
+ }
480
+
481
+ // set image manipulation library
482
+ $type = preg_match('/^(imagick|gd|auto)$/i', $this->options['imgLib'])
483
+ ? strtolower($this->options['imgLib'])
484
+ : 'auto';
485
+
486
+ if (($type == 'imagick' || $type == 'auto') && extension_loaded('imagick')) {
487
+ $this->imgLib = 'imagick';
488
+ } else {
489
+ $this->imgLib = function_exists('gd_info') ? 'gd' : '';
490
+ }
491
+
492
+ }
493
+
494
+
495
+ /*********************************************************************/
496
+ /* PUBLIC API */
497
+ /*********************************************************************/
498
+
499
+ /**
500
+ * Return driver id. Used as a part of volume id.
501
+ *
502
+ * @return string
503
+ * @author Dmitry (dio) Levashov
504
+ **/
505
+ public function driverId() {
506
+ return $this->driverId;
507
+ }
508
+
509
+ /**
510
+ * Return volume id
511
+ *
512
+ * @return string
513
+ * @author Dmitry (dio) Levashov
514
+ **/
515
+ public function id() {
516
+ return $this->id;
517
+ }
518
+
519
+ /**
520
+ * Return debug info for client
521
+ *
522
+ * @return array
523
+ * @author Dmitry (dio) Levashov
524
+ **/
525
+ public function debug() {
526
+ return array(
527
+ 'id' => $this->id(),
528
+ 'name' => strtolower(substr(get_class($this), strlen('elfinderdriver'))),
529
+ 'mimeDetect' => $this->mimeDetect,
530
+ 'imgLib' => $this->imgLib
531
+ );
532
+ }
533
+
534
+ /**
535
+ * "Mount" volume.
536
+ * Return true if volume available for read or write,
537
+ * false - otherwise
538
+ *
539
+ * @return bool
540
+ * @author Dmitry (dio) Levashov
541
+ * @author Alexey Sukhotin
542
+ **/
543
+ public function mount(array $opts) {
544
+ if (!isset($opts['path']) || $opts['path'] === '') {
545
+ return false;
546
+ }
547
+
548
+ $this->options = array_merge($this->options, $opts);
549
+ $this->id = $this->driverId.(!empty($this->options['id']) ? $this->options['id'] : elFinder::$volumesCnt++).'_';
550
+ $this->root = $this->_normpath($this->options['path']);
551
+ $this->separator = isset($this->options['separator']) ? $this->options['separator'] : DIRECTORY_SEPARATOR;
552
+
553
+ // default file attribute
554
+ $this->defaults = array(
555
+ 'read' => isset($this->options['defaults']['read']) ? !!$this->options['defaults']['read'] : true,
556
+ 'write' => isset($this->options['defaults']['write']) ? !!$this->options['defaults']['write'] : true,
557
+ 'locked' => false,
558
+ 'hidden' => false
559
+ );
560
+
561
+ // root attributes
562
+ $this->attributes[] = array(
563
+ 'pattern' => '~^'.preg_quote(DIRECTORY_SEPARATOR).'$~',
564
+ 'locked' => true,
565
+ 'hidden' => false
566
+ );
567
+ // set files attributes
568
+ if (!empty($this->options['attributes']) && is_array($this->options['attributes'])) {
569
+
570
+ foreach ($this->options['attributes'] as $a) {
571
+ // attributes must contain pattern and at least one rule
572
+ if (!empty($a['pattern']) || count($a) > 1) {
573
+ $this->attributes[] = $a;
574
+ }
575
+ }
576
+ }
577
+
578
+ if (!empty($this->options['accessControl'])) {
579
+ if (is_string($this->options['accessControl'])
580
+ && function_exists($this->options['accessControl'])) {
581
+ $this->access = $this->options['accessControl'];
582
+ } elseif (is_array($this->options['accessControl'])
583
+ && count($this->options['accessControl']) > 1
584
+ && is_object($this->options['accessControl'][0])
585
+ && method_exists($this->options['accessControl'][0], $this->options['accessControl'][1])) {
586
+ $this->access = array($this->options['accessControl'][0], $this->options['accessControl'][1]);
587
+ }
588
+ }
589
+
590
+ $this->today = mktime(0,0,0, date('m'), date('d'), date('Y'));
591
+ $this->yesterday = $this->today-86400;
592
+
593
+ // debug($this->attributes);
594
+ if (!$this->init()) {
595
+ return false;
596
+ }
597
+
598
+ // check some options is arrays
599
+ $this->uploadAllow = isset($this->options['uploadAllow']) && is_array($this->options['uploadAllow'])
600
+ ? $this->options['uploadAllow']
601
+ : array();
602
+
603
+ $this->uploadDeny = isset($this->options['uploadDeny']) && is_array($this->options['uploadDeny'])
604
+ ? $this->options['uploadDeny']
605
+ : array();
606
+
607
+ if (is_string($this->options['uploadOrder'])) { // telephat_mode on, compatibility with 1.x
608
+ $parts = explode(',', isset($this->options['uploadOrder']) ? $this->options['uploadOrder'] : 'deny,allow');
609
+ $this->uploadOrder = array(trim($parts[0]), trim($parts[1]));
610
+ } else { // telephat_mode off
611
+ $this->uploadOrder = $this->options['uploadOrder'];
612
+ }
613
+
614
+ if (!empty($this->options['uploadMaxSize'])) {
615
+ $size = ''.$this->options['uploadMaxSize'];
616
+ $unit = strtolower(substr($size, strlen($size) - 1));
617
+ $n = 1;
618
+ switch ($unit) {
619
+ case 'k':
620
+ $n = 1024;
621
+ break;
622
+ case 'm':
623
+ $n = 1048576;
624
+ break;
625
+ case 'g':
626
+ $n = 1073741824;
627
+ }
628
+ $this->uploadMaxSize = intval($size)*$n;
629
+ }
630
+
631
+ $this->disabled = isset($this->options['disabled']) && is_array($this->options['disabled'])
632
+ ? $this->options['disabled']
633
+ : array();
634
+
635
+ $this->cryptLib = $this->options['cryptLib'];
636
+ $this->mimeDetect = $this->options['mimeDetect'];
637
+
638
+ // find available mimetype detect method
639
+ $type = strtolower($this->options['mimeDetect']);
640
+ $type = preg_match('/^(finfo|mime_content_type|internal|auto)$/i', $type) ? $type : 'auto';
641
+ $regexp = '/text\/x\-(php|c\+\+)/';
642
+
643
+ if (($type == 'finfo' || $type == 'auto')
644
+ && class_exists('finfo')
645
+ && preg_match($regexp, array_shift(explode(';', @finfo_file(finfo_open(FILEINFO_MIME), __FILE__))))) {
646
+ $type = 'finfo';
647
+ $this->finfo = finfo_open(FILEINFO_MIME);
648
+ } elseif (($type == 'mime_content_type' || $type == 'auto')
649
+ && function_exists('mime_content_type')
650
+ && preg_match($regexp, array_shift(explode(';', mime_content_type(__FILE__))))) {
651
+ $type = 'mime_content_type';
652
+ } else {
653
+ $type = 'internal';
654
+ }
655
+ $this->mimeDetect = $type;
656
+
657
+ // load mimes from external file for mimeDetect == 'internal'
658
+ // based on Alexey Sukhotin idea and patch: http://elrte.org/redmine/issues/163
659
+ // file must be in file directory or in parent one
660
+ if ($this->mimeDetect == 'internal' && !self::$mimetypesLoaded) {
661
+ self::$mimetypesLoaded = true;
662
+ $this->mimeDetect = 'internal';
663
+ $file = false;
664
+ if (!empty($this->options['mimefile']) && file_exists($this->options['mimefile'])) {
665
+ $file = $this->options['mimefile'];
666
+ } elseif (file_exists(dirname(__FILE__).DIRECTORY_SEPARATOR.'mime.types')) {
667
+ $file = dirname(__FILE__).DIRECTORY_SEPARATOR.'mime.types';
668
+ } elseif (file_exists(dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'mime.types')) {
669
+ $file = dirname(dirname(__FILE__)).DIRECTORY_SEPARATOR.'mime.types';
670
+ }
671
+
672
+ if ($file && file_exists($file)) {
673
+ $mimecf = file($file);
674
+
675
+ foreach ($mimecf as $line_num => $line) {
676
+ if (!preg_match('/^\s*#/', $line)) {
677
+ $mime = preg_split('/\s+/', $line, -1, PREG_SPLIT_NO_EMPTY);
678
+ for ($i = 1, $size = count($mime); $i < $size ; $i++) {
679
+ if (!isset(self::$mimetypes[$mime[$i]])) {
680
+ self::$mimetypes[$mime[$i]] = $mime[0];
681
+ }
682
+ }
683
+ }
684
+ }
685
+ }
686
+ }
687
+
688
+ $this->rootName = empty($this->options['alias']) ? $this->_basename($this->root) : $this->options['alias'];
689
+ $root = $this->stat($this->root);
690
+
691
+ if (!$root) {
692
+ return $this->setError('Root folder does not exists.');
693
+ }
694
+ if (!$root['read'] && !$root['write']) {
695
+ return $this->setError('Root folder has not read and write permissions.');
696
+ }
697
+
698
+ // debug($root);
699
+
700
+ if ($root['read']) {
701
+ // check startPath - path to open by default instead of root
702
+ if ($this->options['startPath']) {
703
+ $start = $this->stat($this->options['startPath']);
704
+ if (!empty($start)
705
+ && $start['mime'] == 'directory'
706
+ && $start['read']
707
+ && empty($start['hidden'])
708
+ && $this->_inpath($this->options['startPath'], $this->root)) {
709
+ $this->startPath = $this->options['startPath'];
710
+ if (substr($this->startPath, -1, 1) == $this->options['separator']) {
711
+ $this->startPath = substr($this->startPath, 0, -1);
712
+ }
713
+ }
714
+ }
715
+ } else {
716
+ $this->options['URL'] = '';
717
+ $this->options['tmbURL'] = '';
718
+ $this->options['tmbPath'] = '';
719
+ // read only volume
720
+ array_unshift($this->attributes, array(
721
+ 'pattern' => '/.*/',
722
+ 'read' => false
723
+ ));
724
+ }
725
+ $this->treeDeep = $this->options['treeDeep'] > 0 ? (int)$this->options['treeDeep'] : 1;
726
+ $this->tmbSize = $this->options['tmbSize'] > 0 ? (int)$this->options['tmbSize'] : 48;
727
+ $this->URL = $this->options['URL'];
728
+ if ($this->URL && preg_match("|[^/?&=]$|", $this->URL)) {
729
+ $this->URL .= '/';
730
+ }
731
+
732
+ $this->tmbURL = !empty($this->options['tmbURL']) ? $this->options['tmbURL'] : '';
733
+ if ($this->tmbURL && preg_match("|[^/?&=]$|", $this->tmbURL)) {
734
+ $this->tmbURL .= '/';
735
+ }
736
+
737
+ $this->nameValidator = is_string($this->options['acceptedName']) && !empty($this->options['acceptedName'])
738
+ ? $this->options['acceptedName']
739
+ : '';
740
+
741
+ $this->_checkArchivers();
742
+ // manual control archive types to create
743
+ if (!empty($this->options['archiveMimes']) && is_array($this->options['archiveMimes'])) {
744
+ foreach ($this->archivers['create'] as $mime => $v) {
745
+ if (!in_array($mime, $this->options['archiveMimes'])) {
746
+ unset($this->archivers['create'][$mime]);
747
+ }
748
+ }
749
+ }
750
+
751
+ // manualy add archivers
752
+ if (!empty($this->options['archivers']['create']) && is_array($this->options['archivers']['create'])) {
753
+ foreach ($this->options['archivers']['create'] as $mime => $conf) {
754
+ if (strpos($mime, 'application/') === 0
755
+ && !empty($conf['cmd'])
756
+ && isset($conf['argc'])
757
+ && !empty($conf['ext'])
758
+ && !isset($this->archivers['create'][$mime])) {
759
+ $this->archivers['create'][$mime] = $conf;
760
+ }
761
+ }
762
+ }
763
+
764
+ if (!empty($this->options['archivers']['extract']) && is_array($this->options['archivers']['extract'])) {
765
+ foreach ($this->options['archivers']['extract'] as $mime => $conf) {
766
+ if (substr($mime, 'application/') === 0
767
+ && !empty($cons['cmd'])
768
+ && isset($conf['argc'])
769
+ && !empty($conf['ext'])
770
+ && !isset($this->archivers['extract'][$mime])) {
771
+ $this->archivers['extract'][$mime] = $conf;
772
+ }
773
+ }
774
+ }
775
+
776
+ $this->configure();
777
+ // echo $this->uploadMaxSize;
778
+ // echo $this->options['uploadMaxSize'];
779
+ return $this->mounted = true;
780
+ }
781
+
782
+ /**
783
+ * Some "unmount" stuffs - may be required by virtual fs
784
+ *
785
+ * @return void
786
+ * @author Dmitry (dio) Levashov
787
+ **/
788
+ public function umount() {
789
+ }
790
+
791
+ /**
792
+ * Return error message from last failed action
793
+ *
794
+ * @return array
795
+ * @author Dmitry (dio) Levashov
796
+ **/
797
+ public function error() {
798
+ return $this->error;
799
+ }
800
+
801
+ /**
802
+ * Set mimetypes allowed to display to client
803
+ *
804
+ * @param array $mimes
805
+ * @return void
806
+ * @author Dmitry (dio) Levashov
807
+ **/
808
+ public function setMimesFilter($mimes) {
809
+ if (is_array($mimes)) {
810
+ $this->onlyMimes = $mimes;
811
+ }
812
+ }
813
+
814
+ /**
815
+ * Return root folder hash
816
+ *
817
+ * @return string
818
+ * @author Dmitry (dio) Levashov
819
+ **/
820
+ public function root() {
821
+ return $this->encode($this->root);
822
+ }
823
+
824
+ /**
825
+ * Return root or startPath hash
826
+ *
827
+ * @return string
828
+ * @author Dmitry (dio) Levashov
829
+ **/
830
+ public function defaultPath() {
831
+ return $this->encode($this->startPath ? $this->startPath : $this->root);
832
+ }
833
+
834
+ /**
835
+ * Return volume options required by client:
836
+ *
837
+ * @return array
838
+ * @author Dmitry (dio) Levashov
839
+ **/
840
+ public function options($hash) {
841
+ return array(
842
+ 'path' => $this->_path($this->decode($hash)),
843
+ 'url' => $this->URL,
844
+ 'tmbUrl' => $this->tmbURL,
845
+ 'disabled' => $this->disabled,
846
+ 'separator' => $this->separator,
847
+ 'copyOverwrite' => intval($this->options['copyOverwrite']),
848
+ 'archivers' => array(
849
+ 'create' => array_keys($this->archivers['create']),
850
+ 'extract' => array_keys($this->archivers['extract'])
851
+ )
852
+ );
853
+ }
854
+
855
+ /**
856
+ * Return true if command disabled in options
857
+ *
858
+ * @param string $cmd command name
859
+ * @return bool
860
+ * @author Dmitry (dio) Levashov
861
+ **/
862
+ public function commandDisabled($cmd) {
863
+ return in_array($cmd, $this->disabled);
864
+ }
865
+
866
+ /**
867
+ * Return true if mime is required mimes list
868
+ *
869
+ * @param string $mime mime type to check
870
+ * @param array $mimes allowed mime types list or not set to use client mimes list
871
+ * @param bool|null $empty what to return on empty list
872
+ * @return bool|null
873
+ * @author Dmitry (dio) Levashov
874
+ * @author Troex Nevelin
875
+ **/
876
+ public function mimeAccepted($mime, $mimes = array(), $empty = true) {
877
+ $mimes = !empty($mimes) ? $mimes : $this->onlyMimes;
878
+ if (empty($mimes)) {
879
+ return $empty;
880
+ }
881
+ return $mime == 'directory'
882
+ || in_array('all', $mimes)
883
+ || in_array('All', $mimes)
884
+ || in_array($mime, $mimes)
885
+ || in_array(substr($mime, 0, strpos($mime, '/')), $mimes);
886
+ }
887
+
888
+ /**
889
+ * Return true if voume is readable.
890
+ *
891
+ * @return bool
892
+ * @author Dmitry (dio) Levashov
893
+ **/
894
+ public function isReadable() {
895
+ $stat = $this->stat($this->root);
896
+ return $stat['read'];
897
+ }
898
+
899
+ /**
900
+ * Return true if copy from this volume allowed
901
+ *
902
+ * @return bool
903
+ * @author Dmitry (dio) Levashov
904
+ **/
905
+ public function copyFromAllowed() {
906
+ return !!$this->options['copyFrom'];
907
+ }
908
+
909
+ /**
910
+ * Return file path related to root
911
+ *
912
+ * @param string $hash file hash
913
+ * @return string
914
+ * @author Dmitry (dio) Levashov
915
+ **/
916
+ public function path($hash) {
917
+ return $this->_path($this->decode($hash));
918
+ }
919
+
920
+ /**
921
+ * Return file real path if file exists
922
+ *
923
+ * @param string $hash file hash
924
+ * @return string
925
+ * @author Dmitry (dio) Levashov
926
+ **/
927
+ public function realpath($hash) {
928
+ $path = $this->decode($hash);
929
+ return $this->stat($path) ? $path : false;
930
+ }
931
+
932
+ /**
933
+ * Return list of moved/overwrited files
934
+ *
935
+ * @return array
936
+ * @author Dmitry (dio) Levashov
937
+ **/
938
+ public function removed() {
939
+ return $this->removed;
940
+ }
941
+
942
+ /**
943
+ * Clean removed files list
944
+ *
945
+ * @return void
946
+ * @author Dmitry (dio) Levashov
947
+ **/
948
+ public function resetRemoved() {
949
+ $this->removed = array();
950
+ }
951
+
952
+ /**
953
+ * Return file/dir hash or first founded child hash with required attr == $val
954
+ *
955
+ * @param string $hash file hash
956
+ * @param string $attr attribute name
957
+ * @param bool $val attribute value
958
+ * @return string|false
959
+ * @author Dmitry (dio) Levashov
960
+ **/
961
+ public function closest($hash, $attr, $val) {
962
+ return ($path = $this->closestByAttr($this->decode($hash), $attr, $val)) ? $this->encode($path) : false;
963
+ }
964
+
965
+ /**
966
+ * Return file info or false on error
967
+ *
968
+ * @param string $hash file hash
969
+ * @param bool $realpath add realpath field to file info
970
+ * @return array|false
971
+ * @author Dmitry (dio) Levashov
972
+ **/
973
+ public function file($hash) {
974
+ $path = $this->decode($hash);
975
+
976
+ return ($file = $this->stat($path)) ? $file : $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
977
+
978
+ if (($file = $this->stat($path)) != false) {
979
+ if ($realpath) {
980
+ $file['realpath'] = $path;
981
+ }
982
+ return $file;
983
+ }
984
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
985
+ }
986
+
987
+ /**
988
+ * Return folder info
989
+ *
990
+ * @param string $hash folder hash
991
+ * @param bool $hidden return hidden file info
992
+ * @return array|false
993
+ * @author Dmitry (dio) Levashov
994
+ **/
995
+ public function dir($hash, $resolveLink=false) {
996
+ if (($dir = $this->file($hash)) == false) {
997
+ return $this->setError(elFinder::ERROR_DIR_NOT_FOUND);
998
+ }
999
+
1000
+ if ($resolveLink && !empty($dir['thash'])) {
1001
+ $dir = $this->file($dir['thash']);
1002
+ }
1003
+
1004
+ return $dir && $dir['mime'] == 'directory' && empty($dir['hidden'])
1005
+ ? $dir
1006
+ : $this->setError(elFinder::ERROR_NOT_DIR);
1007
+ }
1008
+
1009
+ /**
1010
+ * Return directory content or false on error
1011
+ *
1012
+ * @param string $hash file hash
1013
+ * @return array|false
1014
+ * @author Dmitry (dio) Levashov
1015
+ **/
1016
+ public function scandir($hash) {
1017
+ if (($dir = $this->dir($hash)) == false) {
1018
+ return false;
1019
+ }
1020
+
1021
+ return $dir['read']
1022
+ ? $this->getScandir($this->decode($hash))
1023
+ : $this->setError(elFinder::ERROR_PERM_DENIED);
1024
+ }
1025
+
1026
+ /**
1027
+ * Return dir files names list
1028
+ *
1029
+ * @param string $hash file hash
1030
+ * @return array
1031
+ * @author Dmitry (dio) Levashov
1032
+ **/
1033
+ public function ls($hash) {
1034
+ if (($dir = $this->dir($hash)) == false || !$dir['read']) {
1035
+ return false;
1036
+ }
1037
+
1038
+ $list = array();
1039
+ $path = $this->decode($hash);
1040
+
1041
+ foreach ($this->getScandir($path) as $stat) {
1042
+ if (empty($stat['hidden']) && $this->mimeAccepted($stat['mime'])) {
1043
+ $list[] = $stat['name'];
1044
+ }
1045
+ }
1046
+
1047
+ return $list;
1048
+ }
1049
+
1050
+ /**
1051
+ * Return subfolders for required folder or false on error
1052
+ *
1053
+ * @param string $hash folder hash or empty string to get tree from root folder
1054
+ * @param int $deep subdir deep
1055
+ * @param string $exclude dir hash which subfolders must be exluded from result, required to not get stat twice on cwd subfolders
1056
+ * @return array|false
1057
+ * @author Dmitry (dio) Levashov
1058
+ **/
1059
+ public function tree($hash='', $deep=0, $exclude='') {
1060
+ $path = $hash ? $this->decode($hash) : $this->root;
1061
+
1062
+ if (($dir = $this->stat($path)) == false || $dir['mime'] != 'directory') {
1063
+ return false;
1064
+ }
1065
+
1066
+ $dirs = $this->gettree($path, $deep > 0 ? $deep -1 : $this->treeDeep-1, $this->decode($exclude));
1067
+ array_unshift($dirs, $dir);
1068
+ return $dirs;
1069
+ }
1070
+
1071
+ /**
1072
+ * Return part of dirs tree from required dir up to root dir
1073
+ *
1074
+ * @param string $hash directory hash
1075
+ * @return array
1076
+ * @author Dmitry (dio) Levashov
1077
+ **/
1078
+ public function parents($hash) {
1079
+ if (($current = $this->dir($hash)) == false) {
1080
+ return false;
1081
+ }
1082
+
1083
+ $path = $this->decode($hash);
1084
+ $tree = array();
1085
+
1086
+ while ($path && $path != $this->root) {
1087
+ $path = $this->_dirname($path);
1088
+ $stat = $this->stat($path);
1089
+ if (!empty($stat['hidden']) || !$stat['read']) {
1090
+ return false;
1091
+ }
1092
+
1093
+ array_unshift($tree, $stat);
1094
+ if ($path != $this->root) {
1095
+ foreach ($this->gettree($path, 0) as $dir) {
1096
+ if (!in_array($dir, $tree)) {
1097
+ $tree[] = $dir;
1098
+ }
1099
+ }
1100
+ }
1101
+ }
1102
+
1103
+ return $tree ? $tree : array($current);
1104
+ }
1105
+
1106
+ /**
1107
+ * Create thumbnail for required file and return its name of false on failed
1108
+ *
1109
+ * @return string|false
1110
+ * @author Dmitry (dio) Levashov
1111
+ **/
1112
+ public function tmb($hash) {
1113
+ $path = $this->decode($hash);
1114
+ $stat = $this->stat($path);
1115
+
1116
+ if (isset($stat['tmb'])) {
1117
+ return $stat['tmb'] == "1" ? $this->createTmb($path, $stat) : $stat['tmb'];
1118
+ }
1119
+ return false;
1120
+ }
1121
+
1122
+ /**
1123
+ * Return file size / total directory size
1124
+ *
1125
+ * @param string file hash
1126
+ * @return int
1127
+ * @author Dmitry (dio) Levashov
1128
+ **/
1129
+ public function size($hash) {
1130
+ return $this->countSize($this->decode($hash));
1131
+ }
1132
+
1133
+ /**
1134
+ * Open file for reading and return file pointer
1135
+ *
1136
+ * @param string file hash
1137
+ * @return Resource
1138
+ * @author Dmitry (dio) Levashov
1139
+ **/
1140
+ public function open($hash) {
1141
+ if (($file = $this->file($hash)) == false
1142
+ || $file['mime'] == 'directory') {
1143
+ return false;
1144
+ }
1145
+
1146
+ return $this->_fopen($this->decode($hash), 'rb');
1147
+ }
1148
+
1149
+ /**
1150
+ * Close file pointer
1151
+ *
1152
+ * @param Resource $fp file pointer
1153
+ * @param string $hash file hash
1154
+ * @return void
1155
+ * @author Dmitry (dio) Levashov
1156
+ **/
1157
+ public function close($fp, $hash) {
1158
+ $this->_fclose($fp, $this->decode($hash));
1159
+ }
1160
+
1161
+ /**
1162
+ * Create directory and return dir info
1163
+ *
1164
+ * @param string $dst destination directory
1165
+ * @param string $name directory name
1166
+ * @return array|false
1167
+ * @author Dmitry (dio) Levashov
1168
+ **/
1169
+ public function mkdir($dst, $name) {
1170
+ if ($this->commandDisabled('mkdir')) {
1171
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1172
+ }
1173
+
1174
+ if (!$this->nameAccepted($name)) {
1175
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
1176
+ }
1177
+
1178
+ if (($dir = $this->dir($dst)) == false) {
1179
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
1180
+ }
1181
+
1182
+ if (!$dir['write']) {
1183
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1184
+ }
1185
+
1186
+ $path = $this->decode($dst);
1187
+ $dst = $this->_joinPath($path, $name);
1188
+ $stat = $this->stat($dst);
1189
+ if (!empty($stat)) {
1190
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
1191
+ }
1192
+ $this->clearcache();
1193
+ return ($path = $this->_mkdir($path, $name)) ? $this->stat($path) : false;
1194
+ }
1195
+
1196
+ /**
1197
+ * Create empty file and return its info
1198
+ *
1199
+ * @param string $dst destination directory
1200
+ * @param string $name file name
1201
+ * @return array|false
1202
+ * @author Dmitry (dio) Levashov
1203
+ **/
1204
+ public function mkfile($dst, $name) {
1205
+ if ($this->commandDisabled('mkfile')) {
1206
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1207
+ }
1208
+
1209
+ if (!$this->nameAccepted($name)) {
1210
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
1211
+ }
1212
+
1213
+ if (($dir = $this->dir($dst)) == false) {
1214
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
1215
+ }
1216
+
1217
+ if (!$dir['write']) {
1218
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1219
+ }
1220
+
1221
+ $path = $this->decode($dst);
1222
+
1223
+ if ($this->stat($this->_joinPath($path, $name))) {
1224
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
1225
+ }
1226
+ $this->clearcache();
1227
+ return ($path = $this->_mkfile($path, $name)) ? $this->stat($path) : false;
1228
+ }
1229
+
1230
+ /**
1231
+ * Rename file and return file info
1232
+ *
1233
+ * @param string $hash file hash
1234
+ * @param string $name new file name
1235
+ * @return array|false
1236
+ * @author Dmitry (dio) Levashov
1237
+ **/
1238
+ public function rename($hash, $name) {
1239
+ if ($this->commandDisabled('rename')) {
1240
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1241
+ }
1242
+
1243
+ if (!$this->nameAccepted($name)) {
1244
+ return $this->setError(elFinder::ERROR_INVALID_NAME, $name);
1245
+ }
1246
+
1247
+ if (!($file = $this->file($hash))) {
1248
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
1249
+ }
1250
+
1251
+ if ($name == $file['name']) {
1252
+ return $file;
1253
+ }
1254
+
1255
+ if (!empty($file['locked'])) {
1256
+ return $this->setError(elFinder::ERROR_LOCKED, $file['name']);
1257
+ }
1258
+
1259
+ $path = $this->decode($hash);
1260
+ $dir = $this->_dirname($path);
1261
+ $stat = $this->stat($this->_joinPath($dir, $name));
1262
+ if ($stat) {
1263
+ return $this->setError(elFinder::ERROR_EXISTS, $name);
1264
+ }
1265
+
1266
+ if (!$this->_move($path, $dir, $name)) {
1267
+ return false;
1268
+ }
1269
+
1270
+ if (!empty($stat['tmb']) && $stat['tmb'] != "1") {
1271
+ $this->rmTmb($stat['tmb']);
1272
+ }
1273
+
1274
+ $path = $this->_joinPath($dir, $name);
1275
+
1276
+ $this->clearcache();
1277
+ return $this->stat($path);
1278
+ }
1279
+
1280
+ /**
1281
+ * Create file copy with suffix "copy number" and return its info
1282
+ *
1283
+ * @param string $hash file hash
1284
+ * @param string $suffix suffix to add to file name
1285
+ * @return array|false
1286
+ * @author Dmitry (dio) Levashov
1287
+ **/
1288
+ public function duplicate($hash, $suffix='copy') {
1289
+ if ($this->commandDisabled('duplicate')) {
1290
+ return $this->setError(elFinder::ERROR_COPY, '#'.$hash, elFinder::ERROR_PERM_DENIED);
1291
+ }
1292
+
1293
+ if (($file = $this->file($hash)) == false) {
1294
+ return $this->setError(elFinder::ERROR_COPY, elFinder::ERROR_FILE_NOT_FOUND);
1295
+ }
1296
+
1297
+ $path = $this->decode($hash);
1298
+ $dir = $this->_dirname($path);
1299
+
1300
+ return ($path = $this->copy($path, $dir, $this->uniqueName($dir, $this->_basename($path), ' '.$suffix.' '))) == false
1301
+ ? false
1302
+ : $this->stat($path);
1303
+ }
1304
+
1305
+ /**
1306
+ * Save uploaded file.
1307
+ * On success return array with new file stat and with removed file hash (if existed file was replaced)
1308
+ *
1309
+ * @param Resource $fp file pointer
1310
+ * @param string $dst destination folder hash
1311
+ * @param string $src file name
1312
+ * @param string $tmpname file tmp name - required to detect mime type
1313
+ * @return array|false
1314
+ * @author Dmitry (dio) Levashov
1315
+ **/
1316
+ public function upload($fp, $dst, $name, $tmpname) {
1317
+ if ($this->commandDisabled('upload')) {
1318
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1319
+ }
1320
+
1321
+ if (($dir = $this->dir($dst)) == false) {
1322
+ return $this->setError(elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
1323
+ }
1324
+
1325
+ if (!$dir['write']) {
1326
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1327
+ }
1328
+
1329
+ if (!$this->nameAccepted($name)) {
1330
+ return $this->setError(elFinder::ERROR_INVALID_NAME);
1331
+ }
1332
+
1333
+ $mime = $this->mimetype($this->mimeDetect == 'internal' ? $name : $tmpname);
1334
+ if ($mime == 'unknown' && $this->mimeDetect == 'internal') {
1335
+ $mime = elFinderVolumeDriver::mimetypeInternalDetect($name);
1336
+ }
1337
+
1338
+ // logic based on http://httpd.apache.org/docs/2.2/mod/mod_authz_host.html#order
1339
+ $allow = $this->mimeAccepted($mime, $this->uploadAllow, null);
1340
+ $deny = $this->mimeAccepted($mime, $this->uploadDeny, null);
1341
+ $upload = true; // default to allow
1342
+ if (strtolower($this->uploadOrder[0]) == 'allow') { // array('allow', 'deny'), default is to 'deny'
1343
+ $upload = false; // default is deny
1344
+ if (!$deny && ($allow === true)) { // match only allow
1345
+ $upload = true;
1346
+ }// else (both match | no match | match only deny) { deny }
1347
+ } else { // array('deny', 'allow'), default is to 'allow' - this is the default rule
1348
+ $upload = true; // default is allow
1349
+ if (($deny === true) && !$allow) { // match only deny
1350
+ $upload = false;
1351
+ } // else (both match | no match | match only allow) { allow }
1352
+ }
1353
+ if (!$upload) {
1354
+ return $this->setError(elFinder::ERROR_UPLOAD_FILE_MIME);
1355
+ }
1356
+
1357
+ if ($this->uploadMaxSize > 0 && filesize($tmpname) > $this->uploadMaxSize) {
1358
+ return $this->setError(elFinder::ERROR_UPLOAD_FILE_SIZE);
1359
+ }
1360
+
1361
+ $dstpath = $this->decode($dst);
1362
+ $test = $this->_joinPath($dstpath, $name);
1363
+
1364
+ $file = $this->stat($test);
1365
+ $this->clearcache();
1366
+
1367
+ if ($file) { // file exists
1368
+ if ($this->options['uploadOverwrite']) {
1369
+ if (!$file['write']) {
1370
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1371
+ } elseif ($file['mime'] == 'directory') {
1372
+ return $this->setError(elFinder::ERROR_NOT_REPLACE, $name);
1373
+ }
1374
+ $this->remove($file);
1375
+ } else {
1376
+ $name = $this->uniqueName($dstpath, $name, '-', false);
1377
+ }
1378
+ }
1379
+
1380
+ $w = $h = 0;
1381
+ if (strpos($mime, 'image') === 0 && ($s = getimagesize($tmpname))) {
1382
+ $w = $s[0];
1383
+ $h = $s[1];
1384
+ }
1385
+ // $this->clearcache();
1386
+ if (($path = $this->_save($fp, $dstpath, $name, $mime, $w, $h)) == false) {
1387
+ return false;
1388
+ }
1389
+
1390
+
1391
+
1392
+ return $this->stat($path);
1393
+ }
1394
+
1395
+ /**
1396
+ * Paste files
1397
+ *
1398
+ * @param Object $volume source volume
1399
+ * @param string $source file hash
1400
+ * @param string $dst destination dir hash
1401
+ * @param bool $rmSrc remove source after copy?
1402
+ * @return array|false
1403
+ * @author Dmitry (dio) Levashov
1404
+ **/
1405
+ public function paste($volume, $src, $dst, $rmSrc = false) {
1406
+ $err = $rmSrc ? elFinder::ERROR_MOVE : elFinder::ERROR_COPY;
1407
+
1408
+ if ($this->commandDisabled('paste')) {
1409
+ return $this->setError($err, '#'.$src, elFinder::ERROR_PERM_DENIED);
1410
+ }
1411
+
1412
+ if (($file = $volume->file($src, $rmSrc)) == false) {
1413
+ return $this->setError($err, '#'.$src, elFinder::ERROR_FILE_NOT_FOUND);
1414
+ }
1415
+
1416
+ $name = $file['name'];
1417
+ $errpath = $volume->path($src);
1418
+
1419
+ if (($dir = $this->dir($dst)) == false) {
1420
+ return $this->setError($err, $errpath, elFinder::ERROR_TRGDIR_NOT_FOUND, '#'.$dst);
1421
+ }
1422
+
1423
+ if (!$dir['write'] || !$file['read']) {
1424
+ return $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
1425
+ }
1426
+
1427
+ $destination = $this->decode($dst);
1428
+
1429
+ if (($test = $volume->closest($src, $rmSrc ? 'locked' : 'read', $rmSrc))) {
1430
+ return $rmSrc
1431
+ ? $this->setError($err, $errpath, elFinder::ERROR_LOCKED, $volume->path($test))
1432
+ : $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
1433
+ }
1434
+
1435
+ $test = $this->_joinPath($destination, $name);
1436
+ $stat = $this->stat($test);
1437
+ $this->clearcache();
1438
+ if ($stat) {
1439
+ if ($this->options['copyOverwrite']) {
1440
+ // do not replace file with dir or dir with file
1441
+ if (!$this->isSameType($file['mime'], $stat['mime'])) {
1442
+ return $this->setError(elFinder::ERROR_NOT_REPLACE, $this->_path($test));
1443
+ }
1444
+ // existed file is not writable
1445
+ if (!$stat['write']) {
1446
+ return $this->setError($err, $errpath, elFinder::ERROR_PERM_DENIED);
1447
+ }
1448
+ // existed file locked or has locked child
1449
+ if (($locked = $this->closestByAttr($test, 'locked', true))) {
1450
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($locked));
1451
+ }
1452
+ // remove existed file
1453
+ if (!$this->remove($test)) {
1454
+ return $this->setError(elFinder::ERROR_REPLACE, $this->_path($test));
1455
+ }
1456
+ } else {
1457
+ $name = $this->uniqueName($destination, $name, ' ', false);
1458
+ }
1459
+ }
1460
+
1461
+ // copy/move inside current volume
1462
+ if ($volume == $this) {
1463
+ $source = $this->decode($src);
1464
+ // do not copy into itself
1465
+ if ($this->_inpath($destination, $source)) {
1466
+ return $this->setError(elFinder::ERROR_COPY_INTO_ITSELF, $path);
1467
+ }
1468
+ $method = $rmSrc ? 'move' : 'copy';
1469
+
1470
+ return ($path = $this->$method($source, $destination, $name)) ? $this->stat($path) : false;
1471
+ }
1472
+
1473
+
1474
+ // copy/move from another volume
1475
+ if (!$this->options['copyTo'] || !$volume->copyFromAllowed()) {
1476
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_PERM_DENIED);
1477
+ }
1478
+
1479
+ if (($path = $this->copyFrom($volume, $src, $destination, $name)) == false) {
1480
+ return false;
1481
+ }
1482
+
1483
+ if ($rmSrc) {
1484
+ if ($volume->rm($src)) {
1485
+ $this->removed[] = $file;
1486
+ } else {
1487
+ return $this->setError(elFinder::ERROR_MOVE, $errpath, elFinder::ERROR_RM_SRC);
1488
+ }
1489
+ }
1490
+ return $this->stat($path);
1491
+ }
1492
+
1493
+ /**
1494
+ * Return file contents
1495
+ *
1496
+ * @param string $hash file hash
1497
+ * @return string|false
1498
+ * @author Dmitry (dio) Levashov
1499
+ **/
1500
+ public function getContents($hash) {
1501
+ $file = $this->file($hash);
1502
+
1503
+ if (!$file) {
1504
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
1505
+ }
1506
+
1507
+ if ($file['mime'] == 'directory') {
1508
+ return $this->setError(elFinder::ERROR_NOT_FILE);
1509
+ }
1510
+
1511
+ if (!$file['read']) {
1512
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1513
+ }
1514
+
1515
+ return $this->_getContents($this->decode($hash));
1516
+ }
1517
+
1518
+ /**
1519
+ * Put content in text file and return file info.
1520
+ *
1521
+ * @param string $hash file hash
1522
+ * @param string $content new file content
1523
+ * @return array
1524
+ * @author Dmitry (dio) Levashov
1525
+ **/
1526
+ public function putContents($hash, $content) {
1527
+ if ($this->commandDisabled('edit')) {
1528
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1529
+ }
1530
+
1531
+ $path = $this->decode($hash);
1532
+
1533
+ if (!($file = $this->file($hash))) {
1534
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
1535
+ }
1536
+
1537
+ if (!$file['write']) {
1538
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1539
+ }
1540
+ $this->clearcache();
1541
+ return $this->_filePutContents($path, $content) ? $this->stat($path) : false;
1542
+ }
1543
+
1544
+ /**
1545
+ * Extract files from archive
1546
+ *
1547
+ * @param string $hash archive hash
1548
+ * @return array|bool
1549
+ * @author Dmitry (dio) Levashov,
1550
+ * @author Alexey Sukhotin
1551
+ **/
1552
+ public function extract($hash) {
1553
+ if ($this->commandDisabled('extract')) {
1554
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1555
+ }
1556
+
1557
+ if (($file = $this->file($hash)) == false) {
1558
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
1559
+ }
1560
+
1561
+ $archiver = isset($this->archivers['extract'][$file['mime']])
1562
+ ? $this->archivers['extract'][$file['mime']]
1563
+ : false;
1564
+
1565
+ if (!$archiver) {
1566
+ return $this->setError(elFinder::ERROR_NOT_ARCHIVE);
1567
+ }
1568
+
1569
+ $path = $this->decode($hash);
1570
+ $parent = $this->stat($this->_dirname($path));
1571
+
1572
+ if (!$file['read'] || !$parent['write']) {
1573
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1574
+ }
1575
+ $this->clearcache();
1576
+ return ($path = $this->_extract($path, $archiver)) ? $this->stat($path) : false;
1577
+ }
1578
+
1579
+ /**
1580
+ * Add files to archive
1581
+ *
1582
+ * @return void
1583
+ **/
1584
+ public function archive($hashes, $mime) {
1585
+ if ($this->commandDisabled('archive')) {
1586
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1587
+ }
1588
+
1589
+ $archiver = isset($this->archivers['create'][$mime])
1590
+ ? $this->archivers['create'][$mime]
1591
+ : false;
1592
+
1593
+ if (!$archiver) {
1594
+ return $this->setError(elFinder::ERROR_ARCHIVE_TYPE);
1595
+ }
1596
+
1597
+ $files = array();
1598
+
1599
+ foreach ($hashes as $hash) {
1600
+ if (($file = $this->file($hash)) == false) {
1601
+ return $this->error(elFinder::ERROR_FILE_NOT_FOUND, '#'+$hash);
1602
+ }
1603
+ if (!$file['read']) {
1604
+ return $this->error(elFinder::ERROR_PERM_DENIED);
1605
+ }
1606
+ $path = $this->decode($hash);
1607
+ if (!isset($dir)) {
1608
+ $dir = $this->_dirname($path);
1609
+ $stat = $this->stat($dir);
1610
+ if (!$stat['write']) {
1611
+ return $this->error(elFinder::ERROR_PERM_DENIED);
1612
+ }
1613
+ }
1614
+
1615
+ $files[] = $this->_basename($path);
1616
+ }
1617
+
1618
+ $name = (count($files) == 1 ? $files[0] : 'Archive').'.'.$archiver['ext'];
1619
+ $name = $this->uniqueName($dir, $name, '');
1620
+ $this->clearcache();
1621
+ return ($path = $this->_archive($dir, $files, $name, $archiver)) ? $this->stat($path) : false;
1622
+ }
1623
+
1624
+ /**
1625
+ * Resize image
1626
+ *
1627
+ * @param string $hash image file
1628
+ * @param int $width new width
1629
+ * @param int $height new height
1630
+ * @param int $x X start poistion for crop
1631
+ * @param int $y Y start poistion for crop
1632
+ * @param string $mode action how to mainpulate image
1633
+ * @return array|false
1634
+ * @author Dmitry (dio) Levashov
1635
+ * @author Alexey Sukhotin
1636
+ * @author nao-pon
1637
+ * @author Troex Nevelin
1638
+ **/
1639
+ public function resize($hash, $width, $height, $x, $y, $mode = 'resize', $bg = '', $degree = 0) {
1640
+ if ($this->commandDisabled('resize')) {
1641
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1642
+ }
1643
+
1644
+ if (($file = $this->file($hash)) == false) {
1645
+ return $this->setError(elFinder::ERROR_FILE_NOT_FOUND);
1646
+ }
1647
+
1648
+ if (!$file['write'] || !$file['read']) {
1649
+ return $this->setError(elFinder::ERROR_PERM_DENIED);
1650
+ }
1651
+
1652
+ $path = $this->decode($hash);
1653
+
1654
+ if (!$this->canResize($path, $file)) {
1655
+ return $this->setError(elFinder::ERROR_UNSUPPORT_TYPE);
1656
+ }
1657
+
1658
+ switch($mode) {
1659
+
1660
+ case 'propresize':
1661
+ $result = $this->imgResize($path, $width, $height, true, true);
1662
+ break;
1663
+
1664
+ case 'crop':
1665
+ $result = $this->imgCrop($path, $width, $height, $x, $y);
1666
+ break;
1667
+
1668
+ case 'fitsquare':
1669
+ $result = $this->imgSquareFit($path, $width, $height, 'center', 'middle', ($bg ? $bg : $this->options['tmbBgColor']));
1670
+ break;
1671
+
1672
+ case 'rotate':
1673
+ $result = $this->imgRotate($path, $degree, ($bg ? $bg : $this->options['tmbBgColor']));
1674
+ break;
1675
+
1676
+ default:
1677
+ $result = $this->imgResize($path, $width, $height, false, true);
1678
+ break;
1679
+ }
1680
+
1681
+ if ($result) {
1682
+ if (!empty($file['tmb']) && $file['tmb'] != "1") {
1683
+ $this->rmTmb($file['tmb']);
1684
+ }
1685
+ $this->clearcache();
1686
+ return $this->stat($path);
1687
+ }
1688
+
1689
+ return false;
1690
+ }
1691
+
1692
+ /**
1693
+ * Remove file/dir
1694
+ *
1695
+ * @param string $hash file hash
1696
+ * @return bool
1697
+ * @author Dmitry (dio) Levashov
1698
+ **/
1699
+ public function rm($hash) {
1700
+ return $this->commandDisabled('rm')
1701
+ ? array(elFinder::ERROR_ACCESS_DENIED)
1702
+ : $this->remove($this->decode($hash));
1703
+ }
1704
+
1705
+ /**
1706
+ * Search files
1707
+ *
1708
+ * @param string $q search string
1709
+ * @param array $mimes
1710
+ * @return array
1711
+ * @author Dmitry (dio) Levashov
1712
+ **/
1713
+ public function search($q, $mimes) {
1714
+ return $this->doSearch($this->root, $q, $mimes);
1715
+ }
1716
+
1717
+ /**
1718
+ * Return image dimensions
1719
+ *
1720
+ * @param string $hash file hash
1721
+ * @return array
1722
+ * @author Dmitry (dio) Levashov
1723
+ **/
1724
+ public function dimensions($hash) {
1725
+ if (($file = $this->file($hash)) == false) {
1726
+ return false;
1727
+ }
1728
+
1729
+ return $this->_dimensions($this->decode($hash), $file['mime']);
1730
+ }
1731
+
1732
+ /**
1733
+ * Save error message
1734
+ *
1735
+ * @param array error
1736
+ * @return false
1737
+ * @author Dmitry(dio) Levashov
1738
+ **/
1739
+ protected function setError($error) {
1740
+
1741
+ $this->error = array();
1742
+
1743
+ foreach (func_get_args() as $err) {
1744
+ if (is_array($err)) {
1745
+ $this->error = array_merge($this->error, $err);
1746
+ } else {
1747
+ $this->error[] = $err;
1748
+ }
1749
+ }
1750
+
1751
+ // $this->error = is_array($error) ? $error : func_get_args();
1752
+ return false;
1753
+ }
1754
+
1755
+ /*********************************************************************/
1756
+ /* FS API */
1757
+ /*********************************************************************/
1758
+
1759
+ /***************** paths *******************/
1760
+
1761
+ /**
1762
+ * Encode path into hash
1763
+ *
1764
+ * @param string file path
1765
+ * @return string
1766
+ * @author Dmitry (dio) Levashov
1767
+ * @author Troex Nevelin
1768
+ **/
1769
+ protected function encode($path) {
1770
+ if ($path !== '') {
1771
+
1772
+ // cut ROOT from $path for security reason, even if hacker decodes the path he will not know the root
1773
+ $p = $this->_relpath($path);
1774
+ // if reqesting root dir $path will be empty, then assign '/' as we cannot leave it blank for crypt
1775
+ if ($p === '') {
1776
+ $p = DIRECTORY_SEPARATOR;
1777
+ }
1778
+
1779
+ // TODO crypt path and return hash
1780
+ $hash = $this->crypt($p);
1781
+ // hash is used as id in HTML that means it must contain vaild chars
1782
+ // make base64 html safe and append prefix in begining
1783
+ $hash = strtr(base64_encode($hash), '+/=', '-_.');
1784
+ // remove dots '.' at the end, before it was '=' in base64
1785
+ $hash = rtrim($hash, '.');
1786
+ // append volume id to make hash unique
1787
+ return $this->id.$hash;
1788
+ }
1789
+ }
1790
+
1791
+ /**
1792
+ * Decode path from hash
1793
+ *
1794
+ * @param string file hash
1795
+ * @return string
1796
+ * @author Dmitry (dio) Levashov
1797
+ * @author Troex Nevelin
1798
+ **/
1799
+ protected function decode($hash) {
1800
+ if (strpos($hash, $this->id) === 0) {
1801
+ // cut volume id after it was prepended in encode
1802
+ $h = substr($hash, strlen($this->id));
1803
+ // replace HTML safe base64 to normal
1804
+ $h = base64_decode(strtr($h, '-_.', '+/='));
1805
+ // TODO uncrypt hash and return path
1806
+ $path = $this->uncrypt($h);
1807
+ // append ROOT to path after it was cut in encode
1808
+ return $this->_abspath($path);//$this->root.($path == DIRECTORY_SEPARATOR ? '' : DIRECTORY_SEPARATOR.$path);
1809
+ }
1810
+ }
1811
+
1812
+ /**
1813
+ * Return crypted path
1814
+ * Not implemented
1815
+ *
1816
+ * @param string path
1817
+ * @return mixed
1818
+ * @author Dmitry (dio) Levashov
1819
+ **/
1820
+ protected function crypt($path) {
1821
+ return $path;
1822
+ }
1823
+
1824
+ /**
1825
+ * Return uncrypted path
1826
+ * Not implemented
1827
+ *
1828
+ * @param mixed hash
1829
+ * @return mixed
1830
+ * @author Dmitry (dio) Levashov
1831
+ **/
1832
+ protected function uncrypt($hash) {
1833
+ return $hash;
1834
+ }
1835
+
1836
+ /**
1837
+ * Validate file name based on $this->options['acceptedName'] regexp
1838
+ *
1839
+ * @param string $name file name
1840
+ * @return bool
1841
+ * @author Dmitry (dio) Levashov
1842
+ **/
1843
+ protected function nameAccepted($name) {
1844
+ if ($this->nameValidator) {
1845
+ if (function_exists($this->nameValidator)) {
1846
+ $f = $this->nameValidator;
1847
+ return $f($name);
1848
+ }
1849
+ return preg_match($this->nameValidator, $name);
1850
+ }
1851
+ return true;
1852
+ }
1853
+
1854
+ /**
1855
+ * Return new unique name based on file name and suffix
1856
+ *
1857
+ * @param string $path file path
1858
+ * @param string $suffix suffix append to name
1859
+ * @return string
1860
+ * @author Dmitry (dio) Levashov
1861
+ **/
1862
+ public function uniqueName($dir, $name, $suffix = ' copy', $checkNum=true) {
1863
+ $ext = '';
1864
+
1865
+ if (preg_match('/\.((tar\.(gz|bz|bz2|z|lzo))|cpio\.gz|ps\.gz|xcf\.(gz|bz2)|[a-z0-9]{1,4})$/i', $name, $m)) {
1866
+ $ext = '.'.$m[1];
1867
+ $name = substr($name, 0, strlen($name)-strlen($m[0]));
1868
+ }
1869
+
1870
+ if ($checkNum && preg_match('/('.$suffix.')(\d*)$/i', $name, $m)) {
1871
+ $i = (int)$m[2];
1872
+ $name = substr($name, 0, strlen($name)-strlen($m[2]));
1873
+ } else {
1874
+ $i = 1;
1875
+ $name .= $suffix;
1876
+ }
1877
+ $max = $i+100000;
1878
+
1879
+ while ($i <= $max) {
1880
+ $n = $name.($i > 0 ? $i : '').$ext;
1881
+
1882
+ if (!$this->stat($this->_joinPath($dir, $n))) {
1883
+ $this->clearcache();
1884
+ return $n;
1885
+ }
1886
+ $i++;
1887
+ }
1888
+ return $name.md5($dir).$ext;
1889
+ }
1890
+
1891
+ /*********************** file stat *********************/
1892
+
1893
+ /**
1894
+ * Check file attribute
1895
+ *
1896
+ * @param string $path file path
1897
+ * @param string $name attribute name (read|write|locked|hidden)
1898
+ * @param bool $val attribute value returned by file system
1899
+ * @return bool
1900
+ * @author Dmitry (dio) Levashov
1901
+ **/
1902
+ protected function attr($path, $name, $val=false) {
1903
+ if (!isset($this->defaults[$name])) {
1904
+ return false;
1905
+ }
1906
+
1907
+
1908
+ $perm = null;
1909
+
1910
+ if ($this->access) {
1911
+ if (is_array($this->access)) {
1912
+ $obj = $this->access[0];
1913
+ $method = $this->access[1];
1914
+ $perm = $obj->{$method}($name, $path, $this->options['accessControlData'], $this);
1915
+ } else {
1916
+ $func = $this->access;
1917
+ $perm = $func($name, $path, $this->options['accessControlData'], $this);
1918
+ }
1919
+
1920
+ if ($perm !== null) {
1921
+ return !!$perm;
1922
+ }
1923
+ }
1924
+
1925
+ for ($i = 0, $c = count($this->attributes); $i < $c; $i++) {
1926
+ $attrs = $this->attributes[$i];
1927
+ $p = $this->separator.$this->_relpath($path);
1928
+ if (isset($attrs[$name]) && isset($attrs['pattern']) && preg_match($attrs['pattern'], $p)) {
1929
+ $perm = $attrs[$name];
1930
+ }
1931
+ }
1932
+
1933
+ return $perm === null ? $this->defaults[$name] : !!$perm;
1934
+ }
1935
+
1936
+ /**
1937
+ * Return fileinfo
1938
+ *
1939
+ * @param string $path file cache
1940
+ * @return array
1941
+ * @author Dmitry (dio) Levashov
1942
+ **/
1943
+ protected function stat($path) {
1944
+ return isset($this->cache[$path])
1945
+ ? $this->cache[$path]
1946
+ : $this->updateCache($path, $this->_stat($path));
1947
+ }
1948
+
1949
+ /**
1950
+ * Put file stat in cache and return it
1951
+ *
1952
+ * @param string $path file path
1953
+ * @param array $stat file stat
1954
+ * @return array
1955
+ * @author Dmitry (dio) Levashov
1956
+ **/
1957
+ protected function updateCache($path, $stat) {
1958
+ if (empty($stat) || !is_array($stat)) {
1959
+ return $this->cache[$path] = array();
1960
+ }
1961
+
1962
+ $stat['hash'] = $this->encode($path);
1963
+
1964
+ $root = $path == $this->root;
1965
+
1966
+ if ($root) {
1967
+ $stat['volumeid'] = $this->id;
1968
+ if ($this->rootName) {
1969
+ $stat['name'] = $this->rootName;
1970
+ }
1971
+ } else {
1972
+ if (empty($stat['name'])) {
1973
+ $stat['name'] = $this->_basename($path);
1974
+ }
1975
+ if (empty($stat['phash'])) {
1976
+ $stat['phash'] = $this->encode($this->_dirname($path));
1977
+ }
1978
+ }
1979
+
1980
+ // fix name if required
1981
+ if ($this->options['utf8fix'] && $this->options['utf8patterns'] && $this->options['utf8replace']) {
1982
+ $stat['name'] = json_decode(str_replace($this->options['utf8patterns'], $this->options['utf8replace'], json_encode($stat['name'])));
1983
+ }
1984
+
1985
+
1986
+ if (empty($stat['mime'])) {
1987
+ $stat['mime'] = $this->mimetype($stat['name']);
1988
+ }
1989
+
1990
+ // @todo move dateformat to client
1991
+ $stat['date'] = isset($stat['ts'])
1992
+ ? $this->formatDate($stat['ts'])
1993
+ : 'unknown';
1994
+
1995
+ if (!isset($stat['size'])) {
1996
+ $stat['size'] = 'unknown';
1997
+ }
1998
+
1999
+ $stat['read'] = intval($this->attr($path, 'read', isset($stat['read']) ? !!$stat['read'] : false));
2000
+ $stat['write'] = intval($this->attr($path, 'write', isset($stat['write']) ? !!$stat['write'] : false));
2001
+ if ($root) {
2002
+ $stat['locked'] = 1;
2003
+ } elseif ($this->attr($path, 'locked', !empty($stat['locked']))) {
2004
+ $stat['locked'] = 1;
2005
+ } else {
2006
+ unset($stat['locked']);
2007
+ }
2008
+
2009
+ if ($root) {
2010
+ unset($stat['hidden']);
2011
+ } elseif ($this->attr($path, 'hidden', !empty($stat['hidden']))
2012
+ || !$this->mimeAccepted($stat['mime'])) {
2013
+ $stat['hidden'] = $root ? 0 : 1;
2014
+ } else {
2015
+ unset($stat['hidden']);
2016
+ }
2017
+
2018
+ if ($stat['read'] && empty($stat['hidden'])) {
2019
+
2020
+ if ($stat['mime'] == 'directory') {
2021
+ // for dir - check for subdirs
2022
+
2023
+ if ($this->options['checkSubfolders']) {
2024
+ if (isset($stat['dirs'])) {
2025
+ if ($stat['dirs']) {
2026
+ $stat['dirs'] = 1;
2027
+ } else {
2028
+ unset($stat['dirs']);
2029
+ }
2030
+ } elseif (!empty($stat['alias']) && !empty($stat['target'])) {
2031
+ $stat['dirs'] = isset($this->cache[$stat['target']])
2032
+ ? intval(isset($this->cache[$stat['target']]['dirs']))
2033
+ : $this->_subdirs($stat['target']);
2034
+
2035
+ } elseif ($this->_subdirs($path)) {
2036
+ $stat['dirs'] = 1;
2037
+ }
2038
+ } else {
2039
+ $stat['dirs'] = 1;
2040
+ }
2041
+ } else {
2042
+ // for files - check for thumbnails
2043
+ $p = isset($stat['target']) ? $stat['target'] : $path;
2044
+ if ($this->tmbURL && !isset($stat['tmb']) && $this->canCreateTmb($p, $stat)) {
2045
+ $tmb = $this->gettmb($p, $stat);
2046
+ $stat['tmb'] = $tmb ? $tmb : 1;
2047
+ }
2048
+
2049
+ }
2050
+ }
2051
+
2052
+ if (!empty($stat['alias']) && !empty($stat['target'])) {
2053
+ $stat['thash'] = $this->encode($stat['target']);
2054
+ unset($stat['target']);
2055
+ }
2056
+
2057
+ return $this->cache[$path] = $stat;
2058
+ }
2059
+
2060
+ /**
2061
+ * Get stat for folder content and put in cache
2062
+ *
2063
+ * @param string $path
2064
+ * @return void
2065
+ * @author Dmitry (dio) Levashov
2066
+ **/
2067
+ protected function cacheDir($path) {
2068
+ $this->dirsCache[$path] = array();
2069
+
2070
+ foreach ($this->_scandir($path) as $p) {
2071
+ if (($stat = $this->stat($p)) && empty($stat['hidden'])) {
2072
+ $this->dirsCache[$path][] = $p;
2073
+ }
2074
+ }
2075
+ }
2076
+
2077
+ /**
2078
+ * Clean cache
2079
+ *
2080
+ * @return void
2081
+ * @author Dmitry (dio) Levashov
2082
+ **/
2083
+ protected function clearcache() {
2084
+ $this->cache = $this->dirsCache = array();
2085
+ }
2086
+
2087
+ /**
2088
+ * Return file mimetype
2089
+ *
2090
+ * @param string $path file path
2091
+ * @return string
2092
+ * @author Dmitry (dio) Levashov
2093
+ **/
2094
+ protected function mimetype($path) {
2095
+ $type = '';
2096
+
2097
+ if ($this->mimeDetect == 'finfo') {
2098
+ $type = @finfo_file($this->finfo, $path);
2099
+ } elseif ($type == 'mime_content_type') {
2100
+ $type = mime_content_type($path);
2101
+ } else {
2102
+ $type = elFinderVolumeDriver::mimetypeInternalDetect($path);
2103
+ }
2104
+
2105
+ $type = explode(';', $type);
2106
+ $type = trim($type[0]);
2107
+
2108
+ if ($type == 'application/x-empty') {
2109
+ // finfo return this mime for empty files
2110
+ $type = 'text/plain';
2111
+ } elseif ($type == 'application/x-zip') {
2112
+ // http://elrte.org/redmine/issues/163
2113
+ $type = 'application/zip';
2114
+ }
2115
+
2116
+ return $type == 'unknown' && $this->mimeDetect != 'internal'
2117
+ ? elFinderVolumeDriver::mimetypeInternalDetect($path)
2118
+ : $type;
2119
+
2120
+ }
2121
+
2122
+ /**
2123
+ * Detect file mimetype using "internal" method
2124
+ *
2125
+ * @param string $path file path
2126
+ * @return string
2127
+ * @author Dmitry (dio) Levashov
2128
+ **/
2129
+ static protected function mimetypeInternalDetect($path) {
2130
+ $pinfo = pathinfo($path);
2131
+ $ext = isset($pinfo['extension']) ? strtolower($pinfo['extension']) : '';
2132
+ return isset(elFinderVolumeDriver::$mimetypes[$ext]) ? elFinderVolumeDriver::$mimetypes[$ext] : 'unknown';
2133
+
2134
+ }
2135
+
2136
+ /**
2137
+ * Return file/total directory size
2138
+ *
2139
+ * @param string $path file path
2140
+ * @return int
2141
+ * @author Dmitry (dio) Levashov
2142
+ **/
2143
+ protected function countSize($path) {
2144
+ $stat = $this->stat($path);
2145
+
2146
+ if (empty($stat) || !$stat['read'] || !empty($stat['hidden'])) {
2147
+ return 'unknown';
2148
+ }
2149
+
2150
+ if ($stat['mime'] != 'directory') {
2151
+ return $stat['size'];
2152
+ }
2153
+
2154
+ $subdirs = $this->options['checkSubfolders'];
2155
+ $this->options['checkSubfolders'] = true;
2156
+ $result = 0;
2157
+ foreach ($this->getScandir($path) as $stat) {
2158
+ $size = $stat['mime'] == 'directory' && $stat['read']
2159
+ ? $this->countSize($this->_joinPath($path, $stat['name']))
2160
+ : $stat['size'];
2161
+ if ($size > 0) {
2162
+ $result += $size;
2163
+ }
2164
+ }
2165
+ $this->options['checkSubfolders'] = $subdirs;
2166
+ return $result;
2167
+ }
2168
+
2169
+ /**
2170
+ * Return true if all mimes is directory or files
2171
+ *
2172
+ * @param string $mime1 mimetype
2173
+ * @param string $mime2 mimetype
2174
+ * @return bool
2175
+ * @author Dmitry (dio) Levashov
2176
+ **/
2177
+ protected function isSameType($mime1, $mime2) {
2178
+ return ($mime1 == 'directory' && $mime1 == $mime2) || ($mime1 != 'directory' && $mime2 != 'directory');
2179
+ }
2180
+
2181
+ /**
2182
+ * If file has required attr == $val - return file path,
2183
+ * If dir has child with has required attr == $val - return child path
2184
+ *
2185
+ * @param string $path file path
2186
+ * @param string $attr attribute name
2187
+ * @param bool $val attribute value
2188
+ * @return string|false
2189
+ * @author Dmitry (dio) Levashov
2190
+ **/
2191
+ protected function closestByAttr($path, $attr, $val) {
2192
+ $stat = $this->stat($path);
2193
+
2194
+ if (empty($stat)) {
2195
+ return false;
2196
+ }
2197
+
2198
+ $v = isset($stat[$attr]) ? $stat[$attr] : false;
2199
+
2200
+ if ($v == $val) {
2201
+ return $path;
2202
+ }
2203
+
2204
+ return $stat['mime'] == 'directory'
2205
+ ? $this->childsByAttr($path, $attr, $val)
2206
+ : false;
2207
+ }
2208
+
2209
+ /**
2210
+ * Return first found children with required attr == $val
2211
+ *
2212
+ * @param string $path file path
2213
+ * @param string $attr attribute name
2214
+ * @param bool $val attribute value
2215
+ * @return string|false
2216
+ * @author Dmitry (dio) Levashov
2217
+ **/
2218
+ protected function childsByAttr($path, $attr, $val) {
2219
+ foreach ($this->_scandir($path) as $p) {
2220
+ if (($_p = $this->closestByAttr($p, $attr, $val)) != false) {
2221
+ return $_p;
2222
+ }
2223
+ }
2224
+ return false;
2225
+ }
2226
+
2227
+ /***************** get content *******************/
2228
+
2229
+ /**
2230
+ * Return required dir's files info.
2231
+ * If onlyMimes is set - return only dirs and files of required mimes
2232
+ *
2233
+ * @param string $path dir path
2234
+ * @return array
2235
+ * @author Dmitry (dio) Levashov
2236
+ **/
2237
+ protected function getScandir($path) {
2238
+ $files = array();
2239
+
2240
+ !isset($this->dirsCache[$path]) && $this->cacheDir($path);
2241
+
2242
+ foreach ($this->dirsCache[$path] as $p) {
2243
+ if (($stat = $this->stat($p)) && empty($stat['hidden'])) {
2244
+ $files[] = $stat;
2245
+ }
2246
+ }
2247
+
2248
+ return $files;
2249
+ }
2250
+
2251
+
2252
+ /**
2253
+ * Return subdirs tree
2254
+ *
2255
+ * @param string $path parent dir path
2256
+ * @param int $deep tree deep
2257
+ * @return array
2258
+ * @author Dmitry (dio) Levashov
2259
+ **/
2260
+ protected function gettree($path, $deep, $exclude='') {
2261
+ $dirs = array();
2262
+
2263
+ !isset($this->dirsCache[$path]) && $this->cacheDir($path);
2264
+
2265
+ foreach ($this->dirsCache[$path] as $p) {
2266
+ $stat = $this->stat($p);
2267
+
2268
+ if ($stat && empty($stat['hidden']) && $path != $exclude && $stat['mime'] == 'directory') {
2269
+ $dirs[] = $stat;
2270
+ if ($deep > 0 && !empty($stat['dirs'])) {
2271
+ $dirs = array_merge($dirs, $this->gettree($p, $deep-1));
2272
+ }
2273
+ }
2274
+ }
2275
+
2276
+ return $dirs;
2277
+ }
2278
+
2279
+ /**
2280
+ * Recursive files search
2281
+ *
2282
+ * @param string $path dir path
2283
+ * @param string $q search string
2284
+ * @param array $mimes
2285
+ * @return array
2286
+ * @author Dmitry (dio) Levashov
2287
+ **/
2288
+ protected function doSearch($path, $q, $mimes) {
2289
+ $result = array();
2290
+
2291
+ foreach($this->_scandir($path) as $p) {
2292
+ $stat = $this->stat($p);
2293
+
2294
+ if (!$stat) { // invalid links
2295
+ continue;
2296
+ }
2297
+
2298
+ if (!empty($stat['hidden']) || !$this->mimeAccepted($stat['mime'])) {
2299
+ continue;
2300
+ }
2301
+
2302
+ $name = $stat['name'];
2303
+
2304
+ if ($this->stripos($name, $q) !== false) {
2305
+ $stat['path'] = $this->_path($p);
2306
+ if ($this->URL && !isset($stat['url'])) {
2307
+ $stat['url'] = $this->URL . str_replace($this->separator, '/', substr($p, strlen($this->root) + 1));
2308
+ }
2309
+
2310
+ $result[] = $stat;
2311
+ }
2312
+ if ($stat['mime'] == 'directory' && $stat['read'] && !isset($stat['alias'])) {
2313
+ $result = array_merge($result, $this->doSearch($p, $q, $mimes));
2314
+ }
2315
+ }
2316
+
2317
+ return $result;
2318
+ }
2319
+
2320
+ /********************** manuipulations ******************/
2321
+
2322
+ /**
2323
+ * Copy file/recursive copy dir only in current volume.
2324
+ * Return new file path or false.
2325
+ *
2326
+ * @param string $src source path
2327
+ * @param string $dst destination dir path
2328
+ * @param string $name new file name (optionaly)
2329
+ * @return string|false
2330
+ * @author Dmitry (dio) Levashov
2331
+ **/
2332
+ protected function copy($src, $dst, $name) {
2333
+ $srcStat = $this->stat($src);
2334
+ $this->clearcache();
2335
+
2336
+ if (!empty($srcStat['thash'])) {
2337
+ $target = $this->decode($srcStat['thash']);
2338
+ $stat = $this->stat($target);
2339
+ $this->clearcache();
2340
+ return $stat && $this->_symlink($target, $dst, $name)
2341
+ ? $this->_joinPath($dst, $name)
2342
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
2343
+ }
2344
+
2345
+ if ($srcStat['mime'] == 'directory') {
2346
+ $test = $this->stat($this->_joinPath($dst, $name));
2347
+
2348
+ if (($test && $test['mime'] != 'directory') || !$this->_mkdir($dst, $name)) {
2349
+ return $this->setError(elFinder::ERROR_COPY, $this->_path($src));
2350
+ }
2351
+
2352
+ $dst = $this->_joinPath($dst, $name);
2353
+
2354
+ foreach ($this->getScandir($src) as $stat) {
2355
+ if (empty($stat['hidden'])) {
2356
+ $name = $stat['name'];
2357
+ if (!$this->copy($this->_joinPath($src, $name), $dst, $name)) {
2358
+ return false;
2359
+ }
2360
+ }
2361
+ }
2362
+ $this->clearcache();
2363
+ return $dst;
2364
+ }
2365
+
2366
+ return $this->_copy($src, $dst, $name)
2367
+ ? $this->_joinPath($dst, $name)
2368
+ : $this->setError(elFinder::ERROR_COPY, $this->_path($src));
2369
+ }
2370
+
2371
+ /**
2372
+ * Move file
2373
+ * Return new file path or false.
2374
+ *
2375
+ * @param string $src source path
2376
+ * @param string $dst destination dir path
2377
+ * @param string $name new file name
2378
+ * @return string|false
2379
+ * @author Dmitry (dio) Levashov
2380
+ **/
2381
+ protected function move($src, $dst, $name) {
2382
+ $stat = $this->stat($src);
2383
+ $stat['realpath'] = $src;
2384
+ $this->clearcache();
2385
+
2386
+ if ($this->_move($src, $dst, $name)) {
2387
+ $this->removed[] = $stat;
2388
+ return $this->_joinPath($dst, $name);
2389
+ }
2390
+
2391
+ return $this->setError(elFinder::ERROR_MOVE, $this->_path($src));
2392
+ }
2393
+
2394
+ /**
2395
+ * Copy file from another volume.
2396
+ * Return new file path or false.
2397
+ *
2398
+ * @param Object $volume source volume
2399
+ * @param string $src source file hash
2400
+ * @param string $destination destination dir path
2401
+ * @param string $name file name
2402
+ * @return string|false
2403
+ * @author Dmitry (dio) Levashov
2404
+ **/
2405
+ protected function copyFrom($volume, $src, $destination, $name) {
2406
+
2407
+ if (($source = $volume->file($src)) == false) {
2408
+ return $this->setError(elFinder::ERROR_COPY, '#'.$src, $volume->error());
2409
+ }
2410
+
2411
+ $errpath = $volume->path($src);
2412
+
2413
+ if (!$this->nameAccepted($source['name'])) {
2414
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_INVALID_NAME);
2415
+ }
2416
+
2417
+ if (!$source['read']) {
2418
+ return $this->setError(elFinder::ERROR_COPY, $errpath, elFinder::ERROR_PERM_DENIED);
2419
+ }
2420
+
2421
+ if ($source['mime'] == 'directory') {
2422
+ $stat = $this->stat($this->_joinPath($destination, $name));
2423
+ $this->clearcache();
2424
+ if ((!$stat || $stat['mime'] != 'directory') && !$this->_mkdir($destination, $name)) {
2425
+ return $this->setError(elFinder::ERROR_COPY, $errpath);
2426
+ }
2427
+
2428
+ $path = $this->_joinPath($destination, $name);
2429
+
2430
+ foreach ($volume->scandir($src) as $entr) {
2431
+ if (!$this->copyFrom($volume, $entr['hash'], $path, $entr['name'])) {
2432
+ return false;
2433
+ }
2434
+ }
2435
+
2436
+ } else {
2437
+ $mime = $source['mime'];
2438
+ $w = $h = 0;
2439
+ if (strpos($mime, 'image') === 0 && ($dim = $volume->dimensions($src))) {
2440
+ $s = explode('x', $dim);
2441
+ $w = $s[0];
2442
+ $h = $s[1];
2443
+ }
2444
+
2445
+ if (($fp = $volume->open($src)) == false
2446
+ || ($path = $this->_save($fp, $destination, $name, $mime, $w, $h)) == false) {
2447
+ $fp && $volume->close($fp, $src);
2448
+ return $this->setError(elFinder::ERROR_COPY, $errpath);
2449
+ }
2450
+ $volume->close($fp, $src);
2451
+ }
2452
+
2453
+ return $path;
2454
+ }
2455
+
2456
+ /**
2457
+ * Remove file/ recursive remove dir
2458
+ *
2459
+ * @param string $path file path
2460
+ * @param bool $force try to remove even if file locked
2461
+ * @return bool
2462
+ * @author Dmitry (dio) Levashov
2463
+ **/
2464
+ protected function remove($path, $force = false) {
2465
+ $stat = $this->stat($path);
2466
+ $stat['realpath'] = $path;
2467
+ if (!empty($stat['tmb']) && $stat['tmb'] != "1") {
2468
+ $this->rmTmb($stat['tmb']);
2469
+ }
2470
+ $this->clearcache();
2471
+
2472
+ if (empty($stat)) {
2473
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path), elFinder::ERROR_FILE_NOT_FOUND);
2474
+ }
2475
+
2476
+ if (!$force && !empty($stat['locked'])) {
2477
+ return $this->setError(elFinder::ERROR_LOCKED, $this->_path($path));
2478
+ }
2479
+
2480
+ if ($stat['mime'] == 'directory') {
2481
+ foreach ($this->_scandir($path) as $p) {
2482
+ $name = $this->_basename($p);
2483
+ if ($name != '.' && $name != '..' && !$this->remove($p)) {
2484
+ return false;
2485
+ }
2486
+ }
2487
+ if (!$this->_rmdir($path)) {
2488
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
2489
+ }
2490
+
2491
+ } else {
2492
+ if (!$this->_unlink($path)) {
2493
+ return $this->setError(elFinder::ERROR_RM, $this->_path($path));
2494
+ }
2495
+ }
2496
+
2497
+ $this->removed[] = $stat;
2498
+ return true;
2499
+ }
2500
+
2501
+
2502
+ /************************* thumbnails **************************/
2503
+
2504
+ /**
2505
+ * Return thumbnail file name for required file
2506
+ *
2507
+ * @param array $stat file stat
2508
+ * @return string
2509
+ * @author Dmitry (dio) Levashov
2510
+ **/
2511
+ protected function tmbname($stat) {
2512
+ return $stat['hash'].$stat['ts'].'.png';
2513
+ }
2514
+
2515
+ /**
2516
+ * Return thumnbnail name if exists
2517
+ *
2518
+ * @param string $path file path
2519
+ * @param array $stat file stat
2520
+ * @return string|false
2521
+ * @author Dmitry (dio) Levashov
2522
+ **/
2523
+ protected function gettmb($path, $stat) {
2524
+ if ($this->tmbURL && $this->tmbPath) {
2525
+ // file itself thumnbnail
2526
+ if (strpos($path, $this->tmbPath) === 0) {
2527
+ return basename($path);
2528
+ }
2529
+
2530
+ $name = $this->tmbname($stat);
2531
+ if (file_exists($this->tmbPath.DIRECTORY_SEPARATOR.$name)) {
2532
+ return $name;
2533
+ }
2534
+ }
2535
+ return false;
2536
+ }
2537
+
2538
+ /**
2539
+ * Return true if thumnbnail for required file can be created
2540
+ *
2541
+ * @param string $path thumnbnail path
2542
+ * @param array $stat file stat
2543
+ * @return string|bool
2544
+ * @author Dmitry (dio) Levashov
2545
+ **/
2546
+ protected function canCreateTmb($path, $stat) {
2547
+ return $this->tmbPathWritable
2548
+ && strpos($path, $this->tmbPath) === false // do not create thumnbnail for thumnbnail
2549
+ && $this->imgLib
2550
+ && strpos($stat['mime'], 'image') === 0
2551
+ && ($this->imgLib == 'gd' ? $stat['mime'] == 'image/jpeg' || $stat['mime'] == 'image/png' || $stat['mime'] == 'image/gif' : true);
2552
+ }
2553
+
2554
+ /**
2555
+ * Return true if required file can be resized.
2556
+ * By default - the same as canCreateTmb
2557
+ *
2558
+ * @param string $path thumnbnail path
2559
+ * @param array $stat file stat
2560
+ * @return string|bool
2561
+ * @author Dmitry (dio) Levashov
2562
+ **/
2563
+ protected function canResize($path, $stat) {
2564
+ return $this->canCreateTmb($path, $stat);
2565
+ }
2566
+
2567
+ /**
2568
+ * Create thumnbnail and return it's URL on success
2569
+ *
2570
+ * @param string $path file path
2571
+ * @param string $mime file mime type
2572
+ * @return string|false
2573
+ * @author Dmitry (dio) Levashov
2574
+ **/
2575
+ protected function createTmb($path, $stat) {
2576
+ if (!$stat || !$this->canCreateTmb($path, $stat)) {
2577
+ return false;
2578
+ }
2579
+
2580
+ $name = $this->tmbname($stat);
2581
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$name;
2582
+
2583
+ // copy image into tmbPath so some drivers does not store files on local fs
2584
+ if (($src = $this->_fopen($path, 'rb')) == false) {
2585
+ return false;
2586
+ }
2587
+
2588
+ if (($trg = fopen($tmb, 'wb')) == false) {
2589
+ $this->_fclose($src, $path);
2590
+ return false;
2591
+ }
2592
+
2593
+ while (!feof($src)) {
2594
+ fwrite($trg, fread($src, 8192));
2595
+ }
2596
+
2597
+ $this->_fclose($src, $path);
2598
+ fclose($trg);
2599
+
2600
+ $result = false;
2601
+
2602
+ $tmbSize = $this->tmbSize;
2603
+
2604
+ if (($s = getimagesize($tmb)) == false) {
2605
+ return false;
2606
+ }
2607
+
2608
+ /* If image smaller or equal thumbnail size - just fitting to thumbnail square */
2609
+ if ($s[0] <= $tmbSize && $s[1] <= $tmbSize) {
2610
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
2611
+
2612
+ } else {
2613
+
2614
+ if ($this->options['tmbCrop']) {
2615
+
2616
+ /* Resize and crop if image bigger than thumbnail */
2617
+ if (!(($s[0] > $tmbSize && $s[1] <= $tmbSize) || ($s[0] <= $tmbSize && $s[1] > $tmbSize) ) || ($s[0] > $tmbSize && $s[1] > $tmbSize)) {
2618
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, false, 'png');
2619
+ }
2620
+
2621
+ if (($s = getimagesize($tmb)) != false) {
2622
+ $x = $s[0] > $tmbSize ? intval(($s[0] - $tmbSize)/2) : 0;
2623
+ $y = $s[1] > $tmbSize ? intval(($s[1] - $tmbSize)/2) : 0;
2624
+ $result = $this->imgCrop($tmb, $tmbSize, $tmbSize, $x, $y, 'png');
2625
+ }
2626
+
2627
+ } else {
2628
+ $result = $this->imgResize($tmb, $tmbSize, $tmbSize, true, true, $this->imgLib, 'png');
2629
+ $result = $this->imgSquareFit($tmb, $tmbSize, $tmbSize, 'center', 'middle', $this->options['tmbBgColor'], 'png' );
2630
+ }
2631
+
2632
+ }
2633
+ if (!$result) {
2634
+ unlink($tmb);
2635
+ return false;
2636
+ }
2637
+
2638
+ return $name;
2639
+ }
2640
+
2641
+ /**
2642
+ * Resize image
2643
+ *
2644
+ * @param string $path image file
2645
+ * @param int $width new width
2646
+ * @param int $height new height
2647
+ * @param bool $keepProportions crop image
2648
+ * @param bool $resizeByBiggerSide resize image based on bigger side if true
2649
+ * @param string $destformat image destination format
2650
+ * @return string|false
2651
+ * @author Dmitry (dio) Levashov
2652
+ * @author Alexey Sukhotin
2653
+ **/
2654
+ protected function imgResize($path, $width, $height, $keepProportions = false, $resizeByBiggerSide = true, $destformat = null) {
2655
+ if (($s = @getimagesize($path)) == false) {
2656
+ return false;
2657
+ }
2658
+
2659
+ $result = false;
2660
+
2661
+ list($size_w, $size_h) = array($width, $height);
2662
+
2663
+ if ($keepProportions == true) {
2664
+
2665
+ list($orig_w, $orig_h, $new_w, $new_h) = array($s[0], $s[1], $width, $height);
2666
+
2667
+ /* Calculating image scale width and height */
2668
+ $xscale = $orig_w / $new_w;
2669
+ $yscale = $orig_h / $new_h;
2670
+
2671
+ /* Resizing by biggest side */
2672
+
2673
+ if ($resizeByBiggerSide) {
2674
+
2675
+ if ($orig_w > $orig_h) {
2676
+ $size_h = $orig_h * $width / $orig_w;
2677
+ $size_w = $width;
2678
+ } else {
2679
+ $size_w = $orig_w * $height / $orig_h;
2680
+ $size_h = $height;
2681
+ }
2682
+
2683
+ } else {
2684
+ if ($orig_w > $orig_h) {
2685
+ $size_w = $orig_w * $height / $orig_h;
2686
+ $size_h = $height;
2687
+ } else {
2688
+ $size_h = $orig_h * $width / $orig_w;
2689
+ $size_w = $width;
2690
+ }
2691
+ }
2692
+ }
2693
+
2694
+ switch ($this->imgLib) {
2695
+ case 'imagick':
2696
+
2697
+ try {
2698
+ $img = new imagick($path);
2699
+ } catch (Exception $e) {
2700
+
2701
+ return false;
2702
+ }
2703
+
2704
+ $img->resizeImage($size_w, $size_h, Imagick::FILTER_LANCZOS, true);
2705
+
2706
+ $result = $img->writeImage($path);
2707
+
2708
+ return $result ? $path : false;
2709
+
2710
+ break;
2711
+
2712
+ case 'gd':
2713
+ if ($s['mime'] == 'image/jpeg') {
2714
+ $img = imagecreatefromjpeg($path);
2715
+ } elseif ($s['mime'] == 'image/png') {
2716
+ $img = imagecreatefrompng($path);
2717
+ } elseif ($s['mime'] == 'image/gif') {
2718
+ $img = imagecreatefromgif($path);
2719
+ } elseif ($s['mime'] == 'image/xbm') {
2720
+ $img = imagecreatefromxbm($path);
2721
+ }
2722
+
2723
+ if ($img && false != ($tmp = imagecreatetruecolor($size_w, $size_h))) {
2724
+ if (!imagecopyresampled($tmp, $img, 0, 0, 0, 0, $size_w, $size_h, $s[0], $s[1])) {
2725
+ return false;
2726
+ }
2727
+
2728
+ if ($destformat == 'jpg' || ($destformat == null && $s['mime'] == 'image/jpeg')) {
2729
+ $result = imagejpeg($tmp, $path, 100);
2730
+ } else if ($destformat == 'gif' || ($destformat == null && $s['mime'] == 'image/gif')) {
2731
+ $result = imagegif($tmp, $path, 7);
2732
+ } else {
2733
+ $result = imagepng($tmp, $path, 7);
2734
+ }
2735
+
2736
+ imagedestroy($img);
2737
+ imagedestroy($tmp);
2738
+
2739
+ return $result ? $path : false;
2740
+
2741
+ }
2742
+ break;
2743
+ }
2744
+
2745
+ return false;
2746
+ }
2747
+
2748
+ /**
2749
+ * Crop image
2750
+ *
2751
+ * @param string $path image file
2752
+ * @param int $width crop width
2753
+ * @param int $height crop height
2754
+ * @param bool $x crop left offset
2755
+ * @param bool $y crop top offset
2756
+ * @param string $destformat image destination format
2757
+ * @return string|false
2758
+ * @author Dmitry (dio) Levashov
2759
+ * @author Alexey Sukhotin
2760
+ **/
2761
+ protected function imgCrop($path, $width, $height, $x, $y, $destformat = null) {
2762
+ if (($s = @getimagesize($path)) == false) {
2763
+ return false;
2764
+ }
2765
+
2766
+ $result = false;
2767
+
2768
+ switch ($this->imgLib) {
2769
+ case 'imagick':
2770
+
2771
+ try {
2772
+ $img = new imagick($path);
2773
+ } catch (Exception $e) {
2774
+
2775
+ return false;
2776
+ }
2777
+
2778
+ $img->cropImage($width, $height, $x, $y);
2779
+
2780
+ $result = $img->writeImage($path);
2781
+
2782
+ return $result ? $path : false;
2783
+
2784
+ break;
2785
+
2786
+ case 'gd':
2787
+ if ($s['mime'] == 'image/jpeg') {
2788
+ $img = imagecreatefromjpeg($path);
2789
+ } elseif ($s['mime'] == 'image/png') {
2790
+ $img = imagecreatefrompng($path);
2791
+ } elseif ($s['mime'] == 'image/gif') {
2792
+ $img = imagecreatefromgif($path);
2793
+ } elseif ($s['mime'] == 'image/xbm') {
2794
+ $img = imagecreatefromxbm($path);
2795
+ }
2796
+
2797
+ if ($img && false != ($tmp = imagecreatetruecolor($width, $height))) {
2798
+
2799
+ if (!imagecopy($tmp, $img, 0, 0, $x, $y, $width, $height)) {
2800
+ return false;
2801
+ }
2802
+
2803
+ if ($destformat == 'jpg' || ($destformat == null && $s['mime'] == 'image/jpeg')) {
2804
+ $result = imagejpeg($tmp, $path, 100);
2805
+ } else if ($destformat == 'gif' || ($destformat == null && $s['mime'] == 'image/gif')) {
2806
+ $result = imagegif($tmp, $path, 7);
2807
+ } else {
2808
+ $result = imagepng($tmp, $path, 7);
2809
+ }
2810
+
2811
+ imagedestroy($img);
2812
+ imagedestroy($tmp);
2813
+
2814
+ return $result ? $path : false;
2815
+
2816
+ }
2817
+ break;
2818
+ }
2819
+
2820
+ return false;
2821
+ }
2822
+
2823
+ /**
2824
+ * Put image to square
2825
+ *
2826
+ * @param string $path image file
2827
+ * @param int $width square width
2828
+ * @param int $height square height
2829
+ * @param int $align reserved
2830
+ * @param int $valign reserved
2831
+ * @param string $bgcolor square background color in #rrggbb format
2832
+ * @param string $destformat image destination format
2833
+ * @return string|false
2834
+ * @author Dmitry (dio) Levashov
2835
+ * @author Alexey Sukhotin
2836
+ **/
2837
+ protected function imgSquareFit($path, $width, $height, $align = 'center', $valign = 'middle', $bgcolor = '#0000ff', $destformat = null) {
2838
+ if (($s = @getimagesize($path)) == false) {
2839
+ return false;
2840
+ }
2841
+
2842
+ $result = false;
2843
+
2844
+ /* Coordinates for image over square aligning */
2845
+ $y = ceil(abs($height - $s[1]) / 2);
2846
+ $x = ceil(abs($width - $s[0]) / 2);
2847
+
2848
+ switch ($this->imgLib) {
2849
+ case 'imagick':
2850
+ try {
2851
+ $img = new imagick($path);
2852
+ } catch (Exception $e) {
2853
+ return false;
2854
+ }
2855
+
2856
+ $img1 = new Imagick();
2857
+ $img1->newImage($width, $height, new ImagickPixel($bgcolor));
2858
+ $img1->setImageColorspace($img->getImageColorspace());
2859
+ $img1->setImageFormat($destformat != null ? $destformat : $img->getFormat());
2860
+ $img1->compositeImage( $img, imagick::COMPOSITE_OVER, $x, $y );
2861
+ $result = $img1->writeImage($path);
2862
+ return $result ? $path : false;
2863
+
2864
+ break;
2865
+
2866
+ case 'gd':
2867
+ if ($s['mime'] == 'image/jpeg') {
2868
+ $img = imagecreatefromjpeg($path);
2869
+ } elseif ($s['mime'] == 'image/png') {
2870
+ $img = imagecreatefrompng($path);
2871
+ } elseif ($s['mime'] == 'image/gif') {
2872
+ $img = imagecreatefromgif($path);
2873
+ } elseif ($s['mime'] == 'image/xbm') {
2874
+ $img = imagecreatefromxbm($path);
2875
+ }
2876
+
2877
+ if ($img && false != ($tmp = imagecreatetruecolor($width, $height))) {
2878
+
2879
+ if ($bgcolor == 'transparent') {
2880
+ list($r, $g, $b) = array(0, 0, 255);
2881
+ } else {
2882
+ list($r, $g, $b) = sscanf($bgcolor, "#%02x%02x%02x");
2883
+ }
2884
+
2885
+ $bgcolor1 = imagecolorallocate($tmp, $r, $g, $b);
2886
+
2887
+ if ($bgcolor == 'transparent') {
2888
+ $bgcolor1 = imagecolortransparent($tmp, $bgcolor1);
2889
+ }
2890
+
2891
+ imagefill($tmp, 0, 0, $bgcolor1);
2892
+
2893
+ if (!imagecopy($tmp, $img, $x, $y, 0, 0, $s[0], $s[1])) {
2894
+ return false;
2895
+ }
2896
+
2897
+ if ($destformat == 'jpg' || ($destformat == null && $s['mime'] == 'image/jpeg')) {
2898
+ $result = imagejpeg($tmp, $path, 100);
2899
+ } else if ($destformat == 'gif' || ($destformat == null && $s['mime'] == 'image/gif')) {
2900
+ $result = imagegif($tmp, $path, 7);
2901
+ } else {
2902
+ $result = imagepng($tmp, $path, 7);
2903
+ }
2904
+
2905
+ imagedestroy($img);
2906
+ imagedestroy($tmp);
2907
+
2908
+ return $result ? $path : false;
2909
+ }
2910
+ break;
2911
+ }
2912
+
2913
+ return false;
2914
+ }
2915
+
2916
+ /**
2917
+ * Rotate image
2918
+ *
2919
+ * @param string $path image file
2920
+ * @param int $degree rotete degrees
2921
+ * @param string $bgcolor square background color in #rrggbb format
2922
+ * @param string $destformat image destination format
2923
+ * @return string|false
2924
+ * @author nao-pon
2925
+ * @author Troex Nevelin
2926
+ **/
2927
+ protected function imgRotate($path, $degree, $bgcolor = '#ffffff', $destformat = null) {
2928
+ if (($s = @getimagesize($path)) == false) {
2929
+ return false;
2930
+ }
2931
+
2932
+ $result = false;
2933
+
2934
+ switch ($this->imgLib) {
2935
+ case 'imagick':
2936
+ try {
2937
+ $img = new imagick($path);
2938
+ } catch (Exception $e) {
2939
+ return false;
2940
+ }
2941
+
2942
+ $img->rotateImage(new ImagickPixel($bgcolor), $degree);
2943
+ $result = $img->writeImage($path);
2944
+ return $result ? $path : false;
2945
+
2946
+ break;
2947
+
2948
+ case 'gd':
2949
+ if ($s['mime'] == 'image/jpeg') {
2950
+ $img = imagecreatefromjpeg($path);
2951
+ } elseif ($s['mime'] == 'image/png') {
2952
+ $img = imagecreatefrompng($path);
2953
+ } elseif ($s['mime'] == 'image/gif') {
2954
+ $img = imagecreatefromgif($path);
2955
+ } elseif ($s['mime'] == 'image/xbm') {
2956
+ $img = imagecreatefromxbm($path);
2957
+ }
2958
+
2959
+ $degree = 360 - $degree;
2960
+ list($r, $g, $b) = sscanf($bgcolor, "#%02x%02x%02x");
2961
+ $bgcolor = imagecolorallocate($img, $r, $g, $b);
2962
+ $tmp = imageRotate($img, $degree, (int)$bgcolor);
2963
+
2964
+ if ($destformat == 'jpg' || ($destformat == null && $s['mime'] == 'image/jpeg')) {
2965
+ $result = imagejpeg($tmp, $path, 100);
2966
+ } else if ($destformat == 'gif' || ($destformat == null && $s['mime'] == 'image/gif')) {
2967
+ $result = imagegif($tmp, $path, 7);
2968
+ } else {
2969
+ $result = imagepng($tmp, $path, 7);
2970
+ }
2971
+
2972
+ imageDestroy($img);
2973
+ imageDestroy($tmp);
2974
+
2975
+ return $result ? $path : false;
2976
+
2977
+ break;
2978
+ }
2979
+
2980
+ return false;
2981
+ }
2982
+
2983
+ /**
2984
+ * Execute shell command
2985
+ *
2986
+ * @param string $command command line
2987
+ * @param array $output stdout strings
2988
+ * @param array $return_var process exit code
2989
+ * @param array $error_output stderr strings
2990
+ * @return int exit code
2991
+ * @author Alexey Sukhotin
2992
+ **/
2993
+ protected function procExec($command , array &$output = null, &$return_var = -1, array &$error_output = null) {
2994
+
2995
+ $descriptorspec = array(
2996
+ 0 => array("pipe", "r"), // stdin
2997
+ 1 => array("pipe", "w"), // stdout
2998
+ 2 => array("pipe", "w") // stderr
2999
+ );
3000
+
3001
+ $process = proc_open($command, $descriptorspec, $pipes, null, null);
3002
+
3003
+ if (is_resource($process)) {
3004
+
3005
+ fclose($pipes[0]);
3006
+
3007
+ $tmpout = '';
3008
+ $tmperr = '';
3009
+
3010
+ $output = stream_get_contents($pipes[1]);
3011
+ $error_output = stream_get_contents($pipes[2]);
3012
+
3013
+ fclose($pipes[1]);
3014
+ fclose($pipes[2]);
3015
+ $return_var = proc_close($process);
3016
+
3017
+
3018
+ }
3019
+
3020
+ return $return_var;
3021
+
3022
+ }
3023
+
3024
+ /**
3025
+ * Remove thumbnail
3026
+ *
3027
+ * @param string $path file path
3028
+ * @return void
3029
+ * @author Dmitry (dio) Levashov
3030
+ **/
3031
+ protected function rmTmb($tmb) {
3032
+ $tmb = $this->tmbPath.DIRECTORY_SEPARATOR.$tmb;
3033
+ file_exists($tmb) && @unlink($tmb);
3034
+ clearstatcache();
3035
+ }
3036
+
3037
+ /*********************** misc *************************/
3038
+
3039
+ /**
3040
+ * Return smart formatted date
3041
+ *
3042
+ * @param int $ts file timestamp
3043
+ * @return string
3044
+ * @author Dmitry (dio) Levashov
3045
+ **/
3046
+ protected function formatDate($ts) {
3047
+ if ($ts > $this->today) {
3048
+ return 'Today '.date($this->options['timeFormat'], $ts);
3049
+ }
3050
+
3051
+ if ($ts > $this->yesterday) {
3052
+ return 'Yesterday '.date($this->options['timeFormat'], $ts);
3053
+ }
3054
+
3055
+ return date($this->options['dateFormat'], $ts);
3056
+ }
3057
+
3058
+ /**
3059
+ * Find position of first occurrence of string in a string with multibyte support
3060
+ *
3061
+ * @param string $haystack The string being checked.
3062
+ * @param string $needle The string to find in haystack.
3063
+ * @param int $offset The search offset. If it is not specified, 0 is used.
3064
+ * @return int|bool
3065
+ * @author Alexey Sukhotin
3066
+ **/
3067
+ protected function stripos($haystack , $needle , $offset = 0) {
3068
+ if (function_exists('mb_stripos')) {
3069
+ return mb_stripos($haystack , $needle , $offset);
3070
+ } else if (function_exists('mb_strtolower') && function_exists('mb_strpos')) {
3071
+ return mb_strpos(mb_strtolower($haystack), mb_strtolower($needle), $offset);
3072
+ }
3073
+ return stripos($haystack , $needle , $offset);
3074
+ }
3075
+
3076
+ /**==================================* abstract methods *====================================**/
3077
+
3078
+ /*********************** paths/urls *************************/
3079
+
3080
+ /**
3081
+ * Return parent directory path
3082
+ *
3083
+ * @param string $path file path
3084
+ * @return string
3085
+ * @author Dmitry (dio) Levashov
3086
+ **/
3087
+ abstract protected function _dirname($path);
3088
+
3089
+ /**
3090
+ * Return file name
3091
+ *
3092
+ * @param string $path file path
3093
+ * @return string
3094
+ * @author Dmitry (dio) Levashov
3095
+ **/
3096
+ abstract protected function _basename($path);
3097
+
3098
+ /**
3099
+ * Join dir name and file name and return full path.
3100
+ * Some drivers (db) use int as path - so we give to concat path to driver itself
3101
+ *
3102
+ * @param string $dir dir path
3103
+ * @param string $name file name
3104
+ * @return string
3105
+ * @author Dmitry (dio) Levashov
3106
+ **/
3107
+ abstract protected function _joinPath($dir, $name);
3108
+
3109
+ /**
3110
+ * Return normalized path
3111
+ *
3112
+ * @param string $path file path
3113
+ * @return string
3114
+ * @author Dmitry (dio) Levashov
3115
+ **/
3116
+ abstract protected function _normpath($path);
3117
+
3118
+ /**
3119
+ * Return file path related to root dir
3120
+ *
3121
+ * @param string $path file path
3122
+ * @return string
3123
+ * @author Dmitry (dio) Levashov
3124
+ **/
3125
+ abstract protected function _relpath($path);
3126
+
3127
+ /**
3128
+ * Convert path related to root dir into real path
3129
+ *
3130
+ * @param string $path rel file path
3131
+ * @return string
3132
+ * @author Dmitry (dio) Levashov
3133
+ **/
3134
+ abstract protected function _abspath($path);
3135
+
3136
+ /**
3137
+ * Return fake path started from root dir.
3138
+ * Required to show path on client side.
3139
+ *
3140
+ * @param string $path file path
3141
+ * @return string
3142
+ * @author Dmitry (dio) Levashov
3143
+ **/
3144
+ abstract protected function _path($path);
3145
+
3146
+ /**
3147
+ * Return true if $path is children of $parent
3148
+ *
3149
+ * @param string $path path to check
3150
+ * @param string $parent parent path
3151
+ * @return bool
3152
+ * @author Dmitry (dio) Levashov
3153
+ **/
3154
+ abstract protected function _inpath($path, $parent);
3155
+
3156
+ /**
3157
+ * Return stat for given path.
3158
+ * Stat contains following fields:
3159
+ * - (int) size file size in b. required
3160
+ * - (int) ts file modification time in unix time. required
3161
+ * - (string) mime mimetype. required for folders, others - optionally
3162
+ * - (bool) read read permissions. required
3163
+ * - (bool) write write permissions. required
3164
+ * - (bool) locked is object locked. optionally
3165
+ * - (bool) hidden is object hidden. optionally
3166
+ * - (string) alias for symlinks - link target path relative to root path. optionally
3167
+ * - (string) target for symlinks - link target path. optionally
3168
+ *
3169
+ * If file does not exists - returns empty array or false.
3170
+ *
3171
+ * @param string $path file path
3172
+ * @return array|false
3173
+ * @author Dmitry (dio) Levashov
3174
+ **/
3175
+ abstract protected function _stat($path);
3176
+
3177
+
3178
+ /***************** file stat ********************/
3179
+
3180
+
3181
+ /**
3182
+ * Return true if path is dir and has at least one childs directory
3183
+ *
3184
+ * @param string $path dir path
3185
+ * @return bool
3186
+ * @author Dmitry (dio) Levashov
3187
+ **/
3188
+ abstract protected function _subdirs($path);
3189
+
3190
+ /**
3191
+ * Return object width and height
3192
+ * Ususaly used for images, but can be realize for video etc...
3193
+ *
3194
+ * @param string $path file path
3195
+ * @param string $mime file mime type
3196
+ * @return string
3197
+ * @author Dmitry (dio) Levashov
3198
+ **/
3199
+ abstract protected function _dimensions($path, $mime);
3200
+
3201
+ /******************** file/dir content *********************/
3202
+
3203
+ /**
3204
+ * Return files list in directory
3205
+ *
3206
+ * @param string $path dir path
3207
+ * @return array
3208
+ * @author Dmitry (dio) Levashov
3209
+ **/
3210
+ abstract protected function _scandir($path);
3211
+
3212
+ /**
3213
+ * Open file and return file pointer
3214
+ *
3215
+ * @param string $path file path
3216
+ * @param bool $write open file for writing
3217
+ * @return resource|false
3218
+ * @author Dmitry (dio) Levashov
3219
+ **/
3220
+ abstract protected function _fopen($path, $mode="rb");
3221
+
3222
+ /**
3223
+ * Close opened file
3224
+ *
3225
+ * @param resource $fp file pointer
3226
+ * @param string $path file path
3227
+ * @return bool
3228
+ * @author Dmitry (dio) Levashov
3229
+ **/
3230
+ abstract protected function _fclose($fp, $path='');
3231
+
3232
+ /******************** file/dir manipulations *************************/
3233
+
3234
+ /**
3235
+ * Create dir and return created dir path or false on failed
3236
+ *
3237
+ * @param string $path parent dir path
3238
+ * @param string $name new directory name
3239
+ * @return string|bool
3240
+ * @author Dmitry (dio) Levashov
3241
+ **/
3242
+ abstract protected function _mkdir($path, $name);
3243
+
3244
+ /**
3245
+ * Create file and return it's path or false on failed
3246
+ *
3247
+ * @param string $path parent dir path
3248
+ * @param string $name new file name
3249
+ * @return string|bool
3250
+ * @author Dmitry (dio) Levashov
3251
+ **/
3252
+ abstract protected function _mkfile($path, $name);
3253
+
3254
+ /**
3255
+ * Create symlink
3256
+ *
3257
+ * @param string $source file to link to
3258
+ * @param string $targetDir folder to create link in
3259
+ * @param string $name symlink name
3260
+ * @return bool
3261
+ * @author Dmitry (dio) Levashov
3262
+ **/
3263
+ abstract protected function _symlink($source, $targetDir, $name);
3264
+
3265
+ /**
3266
+ * Copy file into another file (only inside one volume)
3267
+ *
3268
+ * @param string $source source file path
3269
+ * @param string $target target dir path
3270
+ * @param string $name file name
3271
+ * @return bool
3272
+ * @author Dmitry (dio) Levashov
3273
+ **/
3274
+ abstract protected function _copy($source, $targetDir, $name);
3275
+
3276
+ /**
3277
+ * Move file into another parent dir.
3278
+ * Return new file path or false.
3279
+ *
3280
+ * @param string $source source file path
3281
+ * @param string $target target dir path
3282
+ * @param string $name file name
3283
+ * @return string|bool
3284
+ * @author Dmitry (dio) Levashov
3285
+ **/
3286
+ abstract protected function _move($source, $targetDir, $name);
3287
+
3288
+ /**
3289
+ * Remove file
3290
+ *
3291
+ * @param string $path file path
3292
+ * @return bool
3293
+ * @author Dmitry (dio) Levashov
3294
+ **/
3295
+ abstract protected function _unlink($path);
3296
+
3297
+ /**
3298
+ * Remove dir
3299
+ *
3300
+ * @param string $path dir path
3301
+ * @return bool
3302
+ * @author Dmitry (dio) Levashov
3303
+ **/
3304
+ abstract protected function _rmdir($path);
3305
+
3306
+ /**
3307
+ * Create new file and write into it from file pointer.
3308
+ * Return new file path or false on error.
3309
+ *
3310
+ * @param resource $fp file pointer
3311
+ * @param string $dir target dir path
3312
+ * @param string $name file name
3313
+ * @return bool|string
3314
+ * @author Dmitry (dio) Levashov
3315
+ **/
3316
+ abstract protected function _save($fp, $dir, $name, $mime, $w, $h);
3317
+
3318
+ /**
3319
+ * Get file contents
3320
+ *
3321
+ * @param string $path file path
3322
+ * @return string|false
3323
+ * @author Dmitry (dio) Levashov
3324
+ **/
3325
+ abstract protected function _getContents($path);
3326
+
3327
+ /**
3328
+ * Write a string to a file
3329
+ *
3330
+ * @param string $path file path
3331
+ * @param string $content new file content
3332
+ * @return bool
3333
+ * @author Dmitry (dio) Levashov
3334
+ **/
3335
+ abstract protected function _filePutContents($path, $content);
3336
+
3337
+ /**
3338
+ * Extract files from archive
3339
+ *
3340
+ * @param string $path file path
3341
+ * @param array $arc archiver options
3342
+ * @return bool
3343
+ * @author Dmitry (dio) Levashov,
3344
+ * @author Alexey Sukhotin
3345
+ **/
3346
+ abstract protected function _extract($path, $arc);
3347
+
3348
+ /**
3349
+ * Create archive and return its path
3350
+ *
3351
+ * @param string $dir target dir
3352
+ * @param array $files files names list
3353
+ * @param string $name archive name
3354
+ * @param array $arc archiver options
3355
+ * @return string|bool
3356
+ * @author Dmitry (dio) Levashov,
3357
+ * @author Alexey Sukhotin
3358
+ **/
3359
+ abstract protected function _archive($dir, $files, $name, $arc);
3360
+
3361
+ /**
3362
+ * Detect available archivers
3363
+ *
3364
+ * @return void
3365
+ * @author Dmitry (dio) Levashov,
3366
+ * @author Alexey Sukhotin
3367
+ **/
3368
+ abstract protected function _checkArchivers();
3369
+
3370
+ } // END class