drg_default_html_editor 0.4.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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