Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Tagging plugins for 0.8-beta

  • Loading branch information...
commit 884add1419729cb8eb5ed8fb47ea68e5f6ce6682 1 parent 10ac356
@thomascube thomascube authored
Showing with 26,230 additions and 0 deletions.
  1. +351 −0 plugins/acl/acl.js
  2. +714 −0 plugins/acl/acl.php
  3. +19 −0 plugins/acl/config.inc.php.dist
  4. +83 −0 plugins/acl/localization/de_DE.inc
  5. +83 −0 plugins/acl/localization/en_US.inc
  6. +83 −0 plugins/acl/localization/pl_PL.inc
  7. +59 −0 plugins/acl/package.xml
  8. +100 −0 plugins/acl/skins/default/acl.css
  9. BIN  plugins/acl/skins/default/images/enabled.png
  10. BIN  plugins/acl/skins/default/images/partial.png
  11. +54 −0 plugins/acl/skins/default/templates/table.html
  12. +43 −0 plugins/additional_message_headers/additional_message_headers.php
  13. +14 −0 plugins/additional_message_headers/config.inc.php.dist
  14. +48 −0 plugins/additional_message_headers/package.xml
  15. +34 −0 plugins/archive/archive.js
  16. +128 −0 plugins/archive/archive.php
  17. +25 −0 plugins/archive/localization/cs_CZ.inc
  18. +8 −0 plugins/archive/localization/de_CH.inc
  19. +8 −0 plugins/archive/localization/de_DE.inc
  20. +9 −0 plugins/archive/localization/en_US.inc
  21. +10 −0 plugins/archive/localization/es_AR.inc
  22. +10 −0 plugins/archive/localization/es_ES.inc
  23. +8 −0 plugins/archive/localization/et_EE.inc
  24. +8 −0 plugins/archive/localization/fr_FR.inc
  25. +10 −0 plugins/archive/localization/gl_ES.inc
  26. +10 −0 plugins/archive/localization/ja_JP.inc
  27. +8 −0 plugins/archive/localization/nl_NL.inc
  28. +8 −0 plugins/archive/localization/pl_PL.inc
  29. +8 −0 plugins/archive/localization/pt_BR.inc
  30. +8 −0 plugins/archive/localization/ru_RU.inc
  31. +8 −0 plugins/archive/localization/sv_SE.inc
  32. +8 −0 plugins/archive/localization/zh_TW.inc
  33. +70 −0 plugins/archive/package.xml
  34. +10 −0 plugins/archive/skins/default/archive.css
  35. BIN  plugins/archive/skins/default/archive_act.png
  36. BIN  plugins/archive/skins/default/archive_pas.png
  37. BIN  plugins/archive/skins/default/foldericon.png
  38. +50 −0 plugins/autologon/autologon.php
  39. +169 −0 plugins/database_attachments/database_attachments.php
  40. +62 −0 plugins/database_attachments/package.xml
  41. +149 −0 plugins/debug_logger/debug_logger.php
  42. +55 −0 plugins/debug_logger/package.xml
  43. +227 −0 plugins/debug_logger/runlog/runlog.php
  44. +78 −0 plugins/emoticons/emoticons.php
  45. +53 −0 plugins/emoticons/package.xml
  46. +35 −0 plugins/enigma/README
  47. +14 −0 plugins/enigma/config.inc.php.dist
  48. +206 −0 plugins/enigma/enigma.js
  49. +475 −0 plugins/enigma/enigma.php
  50. +2 −0  plugins/enigma/home/.htaccess
  51. +2,542 −0 plugins/enigma/lib/Crypt/GPG.php
  52. +336 −0 plugins/enigma/lib/Crypt/GPG/DecryptStatusHandler.php
  53. +1,758 −0 plugins/enigma/lib/Crypt/GPG/Engine.php
  54. +473 −0 plugins/enigma/lib/Crypt/GPG/Exceptions.php
  55. +223 −0 plugins/enigma/lib/Crypt/GPG/Key.php
  56. +428 −0 plugins/enigma/lib/Crypt/GPG/Signature.php
  57. +649 −0 plugins/enigma/lib/Crypt/GPG/SubKey.php
  58. +373 −0 plugins/enigma/lib/Crypt/GPG/UserId.php
  59. +216 −0 plugins/enigma/lib/Crypt/GPG/VerifyStatusHandler.php
  60. +106 −0 plugins/enigma/lib/enigma_driver.php
  61. +305 −0 plugins/enigma/lib/enigma_driver_gnupg.php
  62. +547 −0 plugins/enigma/lib/enigma_engine.php
  63. +62 −0 plugins/enigma/lib/enigma_error.php
  64. +129 −0 plugins/enigma/lib/enigma_key.php
  65. +34 −0 plugins/enigma/lib/enigma_signature.php
  66. +57 −0 plugins/enigma/lib/enigma_subkey.php
  67. +456 −0 plugins/enigma/lib/enigma_ui.php
  68. +31 −0 plugins/enigma/lib/enigma_userid.php
  69. +53 −0 plugins/enigma/localization/en_US.inc
  70. +55 −0 plugins/enigma/localization/ja_JP.inc
  71. +65 −0 plugins/enigma/localization/ru_RU.inc
  72. +182 −0 plugins/enigma/skins/default/enigma.css
  73. BIN  plugins/enigma/skins/default/enigma.png
  74. BIN  plugins/enigma/skins/default/enigma_error.png
  75. BIN  plugins/enigma/skins/default/key.png
  76. BIN  plugins/enigma/skins/default/key_add.png
  77. BIN  plugins/enigma/skins/default/keys_toolbar.png
  78. +20 −0 plugins/enigma/skins/default/templates/keyimport.html
  79. +17 −0 plugins/enigma/skins/default/templates/keyinfo.html
  80. +76 −0 plugins/enigma/skins/default/templates/keys.html
  81. +50 −0 plugins/example_addressbook/example_addressbook.php
  82. +116 −0 plugins/example_addressbook/example_addressbook_backend.php
  83. +51 −0 plugins/example_addressbook/package.xml
  84. +161 −0 plugins/filesystem_attachments/filesystem_attachments.php
  85. +59 −0 plugins/filesystem_attachments/package.xml
  86. +5 −0 plugins/help/config.inc.php.dist
  87. +28 −0 plugins/help/content/about.html
  88. +689 −0 plugins/help/content/license.html
  89. +98 −0 plugins/help/help.php
  90. +25 −0 plugins/help/localization/cs_CZ.inc
  91. +8 −0 plugins/help/localization/da_DK.inc
  92. +8 −0 plugins/help/localization/de_DE.inc
  93. +8 −0 plugins/help/localization/en_GB.inc
  94. +8 −0 plugins/help/localization/en_US.inc
  95. +8 −0 plugins/help/localization/es_ES.inc
  96. +8 −0 plugins/help/localization/et_EE.inc
  97. +8 −0 plugins/help/localization/gl_ES.inc
  98. +8 −0 plugins/help/localization/hu_HU.inc
  99. +10 −0 plugins/help/localization/ja_JP.inc
  100. +8 −0 plugins/help/localization/pl_PL.inc
  101. +8 −0 plugins/help/localization/pt_BR.inc
  102. +23 −0 plugins/help/localization/ru_RU.inc
  103. +8 −0 plugins/help/localization/sv_SE.inc
  104. +8 −0 plugins/help/localization/zh_TW.inc
  105. +67 −0 plugins/help/package.xml
  106. +29 −0 plugins/help/skins/default/help.css
  107. BIN  plugins/help/skins/default/help.gif
  108. +37 −0 plugins/help/skins/default/templates/help.html
  109. +19 −0 plugins/help/skins/larry/help.css
  110. +30 −0 plugins/help/skins/larry/templates/help.html
  111. +67 −0 plugins/http_authentication/http_authentication.php
  112. +29 −0 plugins/http_authentication/logout.html
  113. +48 −0 plugins/http_authentication/package.xml
  114. +29 −0 plugins/jqueryui/README
  115. +12 −0 plugins/jqueryui/config.inc.php.dist
  116. +67 −0 plugins/jqueryui/jqueryui.php
  117. +1,242 −0 plugins/jqueryui/js/i18n/jquery-ui-i18n.js
  118. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-af.js
  119. +24 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ar.js
  120. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-az.js
  121. +24 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-bg.js
  122. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-bs.js
  123. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ca.js
  124. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-cs.js
  125. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-da.js
  126. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-de-CH.js
  127. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-de.js
  128. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-el.js
  129. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-en-GB.js
  130. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-eo.js
  131. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-es.js
  132. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-et.js
  133. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-eu.js
  134. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fa.js
  135. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fi.js
  136. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fo.js
  137. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fr-CH.js
  138. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-fr.js
  139. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-gl.js
  140. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-he.js
  141. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hr.js
  142. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hu.js
  143. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-hy.js
  144. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-id.js
  145. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-is.js
  146. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-it.js
  147. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ja.js
  148. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ko.js
  149. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-kz.js
  150. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-lt.js
  151. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-lv.js
  152. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ms.js
  153. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-nl-BE.js
  154. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-nl.js
  155. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-no.js
  156. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pl.js
  157. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pt-BR.js
  158. +22 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-pt.js
  159. +26 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ro.js
  160. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ru.js
  161. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sk.js
  162. +24 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sl.js
  163. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sq.js
  164. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sr-SR.js
  165. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sr.js
  166. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-sv.js
  167. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-ta.js
  168. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-th.js
  169. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-tr.js
  170. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-uk.js
  171. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-vi.js
  172. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-CN.js
  173. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-HK.js
  174. +23 −0 plugins/jqueryui/js/i18n/jquery.ui.datepicker-zh-TW.js
  175. +356 −0 plugins/jqueryui/js/jquery-ui-1.8.18.custom.min.js
  176. +149 −0 plugins/jqueryui/package.xml
  177. BIN  plugins/jqueryui/themes/default/images/buttongradient.png
  178. BIN  plugins/jqueryui/themes/default/images/listheader.png
  179. BIN  plugins/jqueryui/themes/default/images/ui-bg_flat_0_aaaaaa_40x100.png
  180. BIN  plugins/jqueryui/themes/default/images/ui-bg_flat_75_ffffff_40x100.png
  181. BIN  plugins/jqueryui/themes/default/images/ui-bg_flat_90_cc3333_40x100.png
  182. BIN  plugins/jqueryui/themes/default/images/ui-bg_glass_95_fef1ec_1x400.png
  183. BIN  plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_a3a3a3_1x100.png
  184. BIN  plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_e6e6e7_1x100.png
  185. BIN  plugins/jqueryui/themes/default/images/ui-bg_highlight-hard_90_f4f4f4_1x100.png
  186. BIN  plugins/jqueryui/themes/default/images/ui-icons_000000_256x240.png
  187. BIN  plugins/jqueryui/themes/default/images/ui-icons_333333_256x240.png
  188. BIN  plugins/jqueryui/themes/default/images/ui-icons_666666_256x240.png
  189. BIN  plugins/jqueryui/themes/default/images/ui-icons_cc3333_256x240.png
  190. BIN  plugins/jqueryui/themes/default/images/ui-icons_dddddd_256x240.png
  191. +577 −0 plugins/jqueryui/themes/default/jquery-ui-1.8.18.custom.css
  192. +118 −0 plugins/jqueryui/themes/default/roundcube-custom.diff
  193. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-hard_55_b0ccd7_1x100.png
  194. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-hard_65_ffffff_1x100.png
  195. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-hard_75_eaeaea_1x100.png
  196. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-hard_75_f8f8f8_1x100.png
  197. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-soft_75_fafafa_1x100.png
  198. BIN  plugins/jqueryui/themes/larry/images/ui-bg_highlight-soft_90_e4e4e4_1x100.png
  199. BIN  plugins/jqueryui/themes/larry/images/ui-dialog-close.png
  200. BIN  plugins/jqueryui/themes/larry/images/ui-icons-datepicker.png
  201. BIN  plugins/jqueryui/themes/larry/images/ui-icons_004458_256x240.png
  202. BIN  plugins/jqueryui/themes/larry/images/ui-icons_d7211e_256x240.png
  203. BIN  plugins/jqueryui/themes/larry/images/ui-icons_ffffff_256x240.png
  204. +656 −0 plugins/jqueryui/themes/larry/jquery-ui-1.8.18.custom.css
  205. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png
  206. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_flat_55_fbec88_40x100.png
  207. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png
  208. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_glass_85_dfeffc_1x400.png
  209. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_glass_95_fef1ec_1x400.png
  210. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png
  211. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png
  212. BIN  plugins/jqueryui/themes/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png
  213. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_217bc0_256x240.png
  214. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_2e83ff_256x240.png
  215. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_469bdd_256x240.png
  216. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_6da8d5_256x240.png
  217. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_cd0a0a_256x240.png
  218. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_d8e7f3_256x240.png
  219. BIN  plugins/jqueryui/themes/redmond/images/ui-icons_f9bd01_256x240.png
  220. +565 −0 plugins/jqueryui/themes/redmond/jquery-ui-1.8.18.custom.css
  221. +234 −0 plugins/managesieve/Changelog
  222. +67 −0 plugins/managesieve/config.inc.php.dist
  223. +1,274 −0 plugins/managesieve/lib/Net/Sieve.php
  224. +387 −0 plugins/managesieve/lib/rcube_sieve.php
  225. +1,069 −0 plugins/managesieve/lib/rcube_sieve_script.php
  226. +61 −0 plugins/managesieve/localization/bg_BG.inc
  227. +65 −0 plugins/managesieve/localization/cs_CZ.inc
  228. +150 −0 plugins/managesieve/localization/de_CH.inc
  229. +150 −0 plugins/managesieve/localization/de_DE.inc
  230. +64 −0 plugins/managesieve/localization/el_GR.inc
  231. +150 −0 plugins/managesieve/localization/en_GB.inc
  232. +138 −0 plugins/managesieve/localization/en_US.inc
  233. +90 −0 plugins/managesieve/localization/es_AR.inc
  234. +124 −0 plugins/managesieve/localization/es_ES.inc
  235. +140 −0 plugins/managesieve/localization/et_EE.inc
  236. +90 −0 plugins/managesieve/localization/fi_FI.inc
  237. +139 −0 plugins/managesieve/localization/fr_FR.inc
  238. +90 −0 plugins/managesieve/localization/gl_ES.inc
  239. +115 −0 plugins/managesieve/localization/hr_HR.inc
  240. +71 −0 plugins/managesieve/localization/hu_HU.inc
  241. +150 −0 plugins/managesieve/localization/it_IT.inc
  242. +137 −0 plugins/managesieve/localization/ja_JP.inc
  243. +140 −0 plugins/managesieve/localization/lv_LV.inc
  244. +85 −0 plugins/managesieve/localization/nb_NO.inc
  245. +150 −0 plugins/managesieve/localization/nl_NL.inc
  246. +150 −0 plugins/managesieve/localization/pl_PL.inc
  247. +150 −0 plugins/managesieve/localization/pt_BR.inc
  248. +150 −0 plugins/managesieve/localization/pt_PT.inc
  249. +128 −0 plugins/managesieve/localization/ru_RU.inc
  250. +134 −0 plugins/managesieve/localization/sk_SK.inc
  251. +65 −0 plugins/managesieve/localization/sl_SI.inc
  252. +140 −0 plugins/managesieve/localization/sv_SE.inc
  253. +85 −0 plugins/managesieve/localization/uk_UA.inc
  254. +130 −0 plugins/managesieve/localization/zh_CN.inc
  255. +129 −0 plugins/managesieve/localization/zh_TW.inc
Sorry, we could not display the entire diff because too many files (456) changed.
View
351 plugins/acl/acl.js
@@ -0,0 +1,351 @@
+/**
+ * ACL plugin script
+ *
+ * @version @package_version@
+ * @author Aleksander Machniak <alec@alec.pl>
+ */
+
+if (window.rcmail) {
+ rcmail.addEventListener('init', function() {
+ if (rcmail.gui_objects.acltable) {
+ rcmail.acl_list_init();
+ // enable autocomplete on user input
+ if (rcmail.env.acl_users_source) {
+ rcmail.init_address_input_events($('#acluser'), {action:'settings/plugin.acl-autocomplete'});
+ // fix inserted value
+ rcmail.addEventListener('autocomplete_insert', function(e) {
+ if (e.field.id != 'acluser')
+ return;
+
+ var value = e.insert;
+ // get UID from the entry value
+ if (value.match(/\s*\(([^)]+)\)[, ]*$/))
+ value = RegExp.$1;
+ e.field.value = value;
+ });
+ }
+ }
+
+ rcmail.enable_command('acl-create', 'acl-save', 'acl-cancel', 'acl-mode-switch', true);
+ rcmail.enable_command('acl-delete', 'acl-edit', false);
+ });
+}
+
+// Display new-entry form
+rcube_webmail.prototype.acl_create = function()
+{
+ this.acl_init_form();
+}
+
+// Display ACL edit form
+rcube_webmail.prototype.acl_edit = function()
+{
+ // @TODO: multi-row edition
+ var id = this.acl_list.get_single_selection();
+ if (id)
+ this.acl_init_form(id);
+}
+
+// ACL entry delete
+rcube_webmail.prototype.acl_delete = function()
+{
+ var users = this.acl_get_usernames();
+
+ if (users && users.length && confirm(this.get_label('acl.deleteconfirm'))) {
+ this.http_request('settings/plugin.acl', '_act=delete&_user='+urlencode(users.join(','))
+ + '&_mbox='+urlencode(this.env.mailbox),
+ this.set_busy(true, 'acl.deleting'));
+ }
+}
+
+// Save ACL data
+rcube_webmail.prototype.acl_save = function()
+{
+ var user = $('#acluser').val(), rights = '', type;
+
+ $(':checkbox', this.env.acl_advanced ? $('#advancedrights') : sim_ul = $('#simplerights')).map(function() {
+ if (this.checked)
+ rights += this.value;
+ });
+
+ if (type = $('input:checked[name=usertype]').val()) {
+ if (type != 'user')
+ user = type;
+ }
+
+ if (!user) {
+ alert(this.get_label('acl.nouser'));
+ return;
+ }
+ if (!rights) {
+ alert(this.get_label('acl.norights'));
+ return;
+ }
+
+ this.http_request('settings/plugin.acl', '_act=save'
+ + '&_user='+urlencode(user)
+ + '&_acl=' +rights
+ + '&_mbox='+urlencode(this.env.mailbox)
+ + (this.acl_id ? '&_old='+this.acl_id : ''),
+ this.set_busy(true, 'acl.saving'));
+}
+
+// Cancel/Hide form
+rcube_webmail.prototype.acl_cancel = function()
+{
+ this.ksearch_blur();
+ this.acl_form.hide();
+}
+
+// Update data after save (and hide form)
+rcube_webmail.prototype.acl_update = function(o)
+{
+ // delete old row
+ if (o.old)
+ this.acl_remove_row(o.old);
+ // make sure the same ID doesn't exist
+ else if (this.env.acl[o.id])
+ this.acl_remove_row(o.id);
+
+ // add new row
+ this.acl_add_row(o, true);
+ // hide autocomplete popup
+ this.ksearch_blur();
+ // hide form
+ this.acl_form.hide();
+}
+
+// Switch table display mode
+rcube_webmail.prototype.acl_mode_switch = function(elem)
+{
+ this.env.acl_advanced = !this.env.acl_advanced;
+ this.enable_command('acl-delete', 'acl-edit', false);
+ this.http_request('settings/plugin.acl', '_act=list'
+ + '&_mode='+(this.env.acl_advanced ? 'advanced' : 'simple')
+ + '&_mbox='+urlencode(this.env.mailbox),
+ this.set_busy(true, 'loading'));
+}
+
+// ACL table initialization
+rcube_webmail.prototype.acl_list_init = function()
+{
+ this.acl_list = new rcube_list_widget(this.gui_objects.acltable,
+ {multiselect:true, draggable:false, keyboard:true, toggleselect:true});
+ this.acl_list.addEventListener('select', function(o) { rcmail.acl_list_select(o); });
+ this.acl_list.addEventListener('dblclick', function(o) { rcmail.acl_list_dblclick(o); });
+ this.acl_list.addEventListener('keypress', function(o) { rcmail.acl_list_keypress(o); });
+ this.acl_list.init();
+}
+
+// ACL table row selection handler
+rcube_webmail.prototype.acl_list_select = function(list)
+{
+ rcmail.enable_command('acl-delete', list.selection.length > 0);
+ rcmail.enable_command('acl-edit', list.selection.length == 1);
+ list.focus();
+}
+
+// ACL table double-click handler
+rcube_webmail.prototype.acl_list_dblclick = function(list)
+{
+ this.acl_edit();
+}
+
+// ACL table keypress handler
+rcube_webmail.prototype.acl_list_keypress = function(list)
+{
+ if (list.key_pressed == list.ENTER_KEY)
+ this.command('acl-edit');
+ else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
+ if (!this.acl_form || !this.acl_form.is(':visible'))
+ this.command('acl-delete');
+}
+
+// Reloads ACL table
+rcube_webmail.prototype.acl_list_update = function(html)
+{
+ $(this.gui_objects.acltable).html(html);
+ this.acl_list_init();
+}
+
+// Returns names of users in selected rows
+rcube_webmail.prototype.acl_get_usernames = function()
+{
+ var users = [], n, len, cell, row,
+ list = this.acl_list,
+ selection = list.get_selection();
+
+ for (n=0, len=selection.length; n<len; n++) {
+ if (this.env.acl_specials.length && $.inArray(selection[n], this.env.acl_specials) >= 0) {
+ users.push(selection[n]);
+ }
+ else if (row = list.rows[selection[n]]) {
+ cell = $('td.user', row.obj);
+ if (cell.length == 1)
+ users.push(cell.text());
+ }
+ }
+
+ return users;
+}
+
+// Removes ACL table row
+rcube_webmail.prototype.acl_remove_row = function(id)
+{
+ var list = this.acl_list;
+
+ list.remove_row(id);
+ list.clear_selection();
+
+ // we don't need it anymore (remove id conflict)
+ $('#rcmrow'+id).remove();
+ this.env.acl[id] = null;
+
+ this.enable_command('acl-delete', list.selection.length > 0);
+ this.enable_command('acl-edit', list.selection.length == 1);
+}
+
+// Adds ACL table row
+rcube_webmail.prototype.acl_add_row = function(o, sel)
+{
+ var n, len, ids = [], spec = [], id = o.id, list = this.acl_list,
+ items = this.env.acl_advanced ? [] : this.env.acl_items,
+ table = this.gui_objects.acltable,
+ row = $('thead > tr', table).clone();
+
+ // Update new row
+ $('td', row).map(function() {
+ var r, cl = this.className.replace(/^acl/, '');
+
+ if (items && items[cl])
+ cl = items[cl];
+
+ if (cl == 'user')
+ $(this).text(o.username);
+ else
+ $(this).addClass(rcmail.acl_class(o.acl, cl)).text('');
+ });
+
+ row.attr('id', 'rcmrow'+id);
+ row = row.get(0);
+
+ this.env.acl[id] = o.acl;
+
+ // sorting... (create an array of user identifiers, then sort it)
+ for (n in this.env.acl) {
+ if (this.env.acl[n]) {
+ if (this.env.acl_specials.length && $.inArray(n, this.env.acl_specials) >= 0)
+ spec.push(n);
+ else
+ ids.push(n);
+ }
+ }
+ ids.sort();
+ // specials on the top
+ ids = spec.concat(ids);
+
+ // find current id
+ for (n=0, len=ids.length; n<len; n++)
+ if (ids[n] == id)
+ break;
+
+ // add row
+ if (n && n < len) {
+ $('#rcmrow'+ids[n-1]).after(row);
+ list.init_row(row);
+ list.rowcount++;
+ }
+ else
+ list.insert_row(row);
+
+ if (sel)
+ list.select_row(o.id);
+}
+
+// Initializes and shows ACL create/edit form
+rcube_webmail.prototype.acl_init_form = function(id)
+{
+ var ul, row, td, val = '', type = 'user', li_elements, body = $('body'),
+ adv_ul = $('#advancedrights'), sim_ul = $('#simplerights'),
+ name_input = $('#acluser');
+
+ if (!this.acl_form) {
+ var fn = function () { $('input[value=user]').prop('checked', true); };
+ name_input.click(fn).keypress(fn);
+ }
+
+ this.acl_form = $('#aclform');
+
+ // Hide unused items
+ if (this.env.acl_advanced) {
+ adv_ul.show();
+ sim_ul.hide();
+ ul = adv_ul;
+ }
+ else {
+ sim_ul.show();
+ adv_ul.hide();
+ ul = sim_ul;
+ }
+
+ // initialize form fields
+ li_elements = $(':checkbox', ul);
+ li_elements.attr('checked', false);
+
+ if (id && (row = this.acl_list.rows[id])) {
+ row = row.obj;
+ li_elements.map(function() {
+ val = this.value;
+ td = $('td.'+this.id, row);
+ if (td && td.hasClass('enabled'))
+ this.checked = true;
+ });
+
+ if (!this.env.acl_specials.length || $.inArray(id, this.env.acl_specials) < 0)
+ val = $('td.user', row).text();
+ else
+ type = id;
+ }
+ // mark read (lrs) rights by default
+ else
+ li_elements.filter(function() { return this.id.match(/^acl([lrs]|read)$/); }).prop('checked', true);
+
+ name_input.val(val);
+ $('input[value='+type+']').prop('checked', true);
+
+ this.acl_id = id;
+
+ // position the form horizontally
+ var bw = body.width(), mw = this.acl_form.width();
+
+ if (bw >= mw)
+ this.acl_form.css({left: parseInt((bw - mw)/2)+'px'});
+
+ // display it
+ this.acl_form.show();
+ if (type == 'user')
+ name_input.focus();
+
+ // unfocus the list, make backspace key in name input field working
+ this.acl_list.blur();
+}
+
+// Returns class name according to ACL comparision result
+rcube_webmail.prototype.acl_class = function(acl1, acl2)
+{
+ var i, len, found = 0;
+
+ acl1 = String(acl1);
+ acl2 = String(acl2);
+
+ for (i=0, len=acl2.length; i<len; i++)
+ if (acl1.indexOf(acl2[i]) > -1)
+ found++;
+
+ if (found == len)
+ return 'enabled';
+ else if (found)
+ return 'partial';
+
+ return 'disabled';
+}
View
714 plugins/acl/acl.php
@@ -0,0 +1,714 @@
+<?php
+
+/**
+ * Folders Access Control Lists Management (RFC4314, RFC2086)
+ *
+ * @version @package_version@
+ * @author Aleksander Machniak <alec@alec.pl>
+ *
+ *
+ * Copyright (C) 2011, Kolab Systems AG
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+class acl extends rcube_plugin
+{
+ public $task = 'settings|addressbook|calendar';
+
+ private $rc;
+ private $supported = null;
+ private $mbox;
+ private $ldap;
+ private $specials = array('anyone', 'anonymous');
+
+ /**
+ * Plugin initialization
+ */
+ function init()
+ {
+ $this->rc = rcmail::get_instance();
+
+ // Register hooks
+ $this->add_hook('folder_form', array($this, 'folder_form'));
+ // kolab_addressbook plugin
+ $this->add_hook('addressbook_form', array($this, 'folder_form'));
+ $this->add_hook('calendar_form_kolab', array($this, 'folder_form'));
+ // Plugin actions
+ $this->register_action('plugin.acl', array($this, 'acl_actions'));
+ $this->register_action('plugin.acl-autocomplete', array($this, 'acl_autocomplete'));
+ }
+
+ /**
+ * Handler for plugin actions (AJAX)
+ */
+ function acl_actions()
+ {
+ $action = trim(get_input_value('_act', RCUBE_INPUT_GPC));
+
+ // Connect to IMAP
+ $this->rc->storage_init();
+
+ // Load localization and configuration
+ $this->add_texts('localization/');
+ $this->load_config();
+
+ if ($action == 'save') {
+ $this->action_save();
+ }
+ else if ($action == 'delete') {
+ $this->action_delete();
+ }
+ else if ($action == 'list') {
+ $this->action_list();
+ }
+
+ // Only AJAX actions
+ $this->rc->output->send();
+ }
+
+ /**
+ * Handler for user login autocomplete request
+ */
+ function acl_autocomplete()
+ {
+ $this->load_config();
+
+ $search = get_input_value('_search', RCUBE_INPUT_GPC, true);
+ $sid = get_input_value('_id', RCUBE_INPUT_GPC);
+ $users = array();
+
+ if ($this->init_ldap()) {
+ $max = (int) $this->rc->config->get('autocomplete_max', 15);
+ $mode = (int) $this->rc->config->get('addressbook_search_mode');
+
+ $this->ldap->set_pagesize($max);
+ $result = $this->ldap->search('*', $search, $mode);
+
+ foreach ($result->records as $record) {
+ $user = $record['uid'];
+
+ if (is_array($user)) {
+ $user = array_filter($user);
+ $user = $user[0];
+ }
+
+ if ($user) {
+ if ($record['name'])
+ $user = $record['name'] . ' (' . $user . ')';
+
+ $users[] = $user;
+ }
+ }
+ }
+
+ sort($users, SORT_LOCALE_STRING);
+
+ $this->rc->output->command('ksearch_query_results', $users, $search, $sid);
+ $this->rc->output->send();
+ }
+
+ /**
+ * Handler for 'folder_form' hook
+ *
+ * @param array $args Hook arguments array (form data)
+ *
+ * @return array Hook arguments array
+ */
+ function folder_form($args)
+ {
+ // Edited folder name (empty in create-folder mode)
+ $mbox_imap = $args['options']['name'];
+ if (!strlen($mbox_imap)) {
+ return $args;
+ }
+/*
+ // Do nothing on protected folders (?)
+ if ($args['options']['protected']) {
+ return $args;
+ }
+*/
+ // Namespace root
+ if ($args['options']['is_root']) {
+ return $args;
+ }
+
+ // Get MYRIGHTS
+ if (!($myrights = $args['options']['rights'])) {
+ return $args;
+ }
+
+ // Do nothing if no ACL support
+ if (!$this->rc->storage->get_capability('ACL')) {
+ return $args;
+ }
+
+ // Load localization and include scripts
+ $this->load_config();
+ $this->add_texts('localization/', array('deleteconfirm', 'norights',
+ 'nouser', 'deleting', 'saving'));
+ $this->include_script('acl.js');
+ $this->rc->output->include_script('list.js');
+ $this->include_stylesheet($this->local_skin_path().'/acl.css');
+
+ // add Info fieldset if it doesn't exist
+ if (!isset($args['form']['props']['fieldsets']['info']))
+ $args['form']['props']['fieldsets']['info'] = array(
+ 'name' => rcube_label('info'),
+ 'content' => array());
+
+ // Display folder rights to 'Info' fieldset
+ $args['form']['props']['fieldsets']['info']['content']['myrights'] = array(
+ 'label' => Q($this->gettext('myrights')),
+ 'value' => $this->acl2text($myrights)
+ );
+
+ // Return if not folder admin
+ if (!in_array('a', $myrights)) {
+ return $args;
+ }
+
+ // The 'Sharing' tab
+ $this->mbox = $mbox_imap;
+ $this->rc->output->set_env('acl_users_source', (bool) $this->rc->config->get('acl_users_source'));
+ $this->rc->output->set_env('mailbox', $mbox_imap);
+ $this->rc->output->add_handlers(array(
+ 'acltable' => array($this, 'templ_table'),
+ 'acluser' => array($this, 'templ_user'),
+ 'aclrights' => array($this, 'templ_rights'),
+ ));
+
+ $this->rc->output->set_env('autocomplete_max', (int)$this->rc->config->get('autocomplete_max', 15));
+ $this->rc->output->set_env('autocomplete_min_length', $this->rc->config->get('autocomplete_min_length'));
+ $this->rc->output->add_label('autocompletechars', 'autocompletemore');
+
+ $args['form']['sharing'] = array(
+ 'name' => Q($this->gettext('sharing')),
+ 'content' => $this->rc->output->parse('acl.table', false, false),
+ );
+
+ return $args;
+ }
+
+ /**
+ * Creates ACL rights table
+ *
+ * @param array $attrib Template object attributes
+ *
+ * @return string HTML Content
+ */
+ function templ_table($attrib)
+ {
+ if (empty($attrib['id']))
+ $attrib['id'] = 'acl-table';
+
+ $out = $this->list_rights($attrib);
+
+ $this->rc->output->add_gui_object('acltable', $attrib['id']);
+
+ return $out;
+ }
+
+ /**
+ * Creates ACL rights form (rights list part)
+ *
+ * @param array $attrib Template object attributes
+ *
+ * @return string HTML Content
+ */
+ function templ_rights($attrib)
+ {
+ // Get supported rights
+ $supported = $this->rights_supported();
+
+ // depending on server capability either use 'te' or 'd' for deleting msgs
+ $deleteright = implode(array_intersect(str_split('ted'), $supported));
+
+ $out = '';
+ $ul = '';
+ $input = new html_checkbox();
+
+ // Advanced rights
+ $attrib['id'] = 'advancedrights';
+ foreach ($supported as $val) {
+ $id = "acl$val";
+ $ul .= html::tag('li', null,
+ $input->show('', array(
+ 'name' => "acl[$val]", 'value' => $val, 'id' => $id))
+ . html::label(array('for' => $id, 'title' => $this->gettext('longacl'.$val)),
+ $this->gettext('acl'.$val)));
+ }
+
+ $out = html::tag('ul', $attrib, $ul, html::$common_attrib);
+
+ // Simple rights
+ $ul = '';
+ $attrib['id'] = 'simplerights';
+ $items = array(
+ 'read' => 'lrs',
+ 'write' => 'wi',
+ 'delete' => $deleteright,
+ 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)),
+ );
+
+ foreach ($items as $key => $val) {
+ $id = "acl$key";
+ $ul .= html::tag('li', null,
+ $input->show('', array(
+ 'name' => "acl[$val]", 'value' => $val, 'id' => $id))
+ . html::label(array('for' => $id, 'title' => $this->gettext('longacl'.$key)),
+ $this->gettext('acl'.$key)));
+ }
+
+ $out .= "\n" . html::tag('ul', $attrib, $ul, html::$common_attrib);
+
+ $this->rc->output->set_env('acl_items', $items);
+
+ return $out;
+ }
+
+ /**
+ * Creates ACL rights form (user part)
+ *
+ * @param array $attrib Template object attributes
+ *
+ * @return string HTML Content
+ */
+ function templ_user($attrib)
+ {
+ // Create username input
+ $attrib['name'] = 'acluser';
+
+ $textfield = new html_inputfield($attrib);
+
+ $fields['user'] = html::label(array('for' => 'iduser'), $this->gettext('username'))
+ . ' ' . $textfield->show();
+
+ // Add special entries
+ if (!empty($this->specials)) {
+ foreach ($this->specials as $key) {
+ $fields[$key] = html::label(array('for' => 'id'.$key), $this->gettext($key));
+ }
+ }
+
+ $this->rc->output->set_env('acl_specials', $this->specials);
+
+ // Create list with radio buttons
+ if (count($fields) > 1) {
+ $ul = '';
+ $radio = new html_radiobutton(array('name' => 'usertype'));
+ foreach ($fields as $key => $val) {
+ $ul .= html::tag('li', null, $radio->show($key == 'user' ? 'user' : '',
+ array('value' => $key, 'id' => 'id'.$key))
+ . $val);
+ }
+
+ $out = html::tag('ul', array('id' => 'usertype'), $ul, html::$common_attrib);
+ }
+ // Display text input alone
+ else {
+ $out = $fields['user'];
+ }
+
+ return $out;
+ }
+
+ /**
+ * Creates ACL rights table
+ *
+ * @param array $attrib Template object attributes
+ *
+ * @return string HTML Content
+ */
+ private function list_rights($attrib=array())
+ {
+ // Get ACL for the folder
+ $acl = $this->rc->storage->get_acl($this->mbox);
+
+ if (!is_array($acl)) {
+ $acl = array();
+ }
+
+ // Keep special entries (anyone/anonymous) on top of the list
+ if (!empty($this->specials) && !empty($acl)) {
+ foreach ($this->specials as $key) {
+ if (isset($acl[$key])) {
+ $acl_special[$key] = $acl[$key];
+ unset($acl[$key]);
+ }
+ }
+ }
+
+ // Sort the list by username
+ uksort($acl, 'strnatcasecmp');
+
+ if (!empty($acl_special)) {
+ $acl = array_merge($acl_special, $acl);
+ }
+
+ // Get supported rights and build column names
+ $supported = $this->rights_supported();
+
+ // depending on server capability either use 'te' or 'd' for deleting msgs
+ $deleteright = implode(array_intersect(str_split('ted'), $supported));
+
+ // Use advanced or simple (grouped) rights
+ $advanced = $this->rc->config->get('acl_advanced_mode');
+
+ if ($advanced) {
+ $items = array();
+ foreach ($supported as $sup) {
+ $items[$sup] = $sup;
+ }
+ }
+ else {
+ $items = array(
+ 'read' => 'lrs',
+ 'write' => 'wi',
+ 'delete' => $deleteright,
+ 'other' => preg_replace('/[lrswi'.$deleteright.']/', '', implode($supported)),
+ );
+ }
+
+ // Create the table
+ $attrib['noheader'] = true;
+ $table = new html_table($attrib);
+
+ // Create table header
+ $table->add_header('user', $this->gettext('identifier'));
+ foreach (array_keys($items) as $key) {
+ $table->add_header('acl'.$key, $this->gettext('shortacl'.$key));
+ }
+
+ $i = 1;
+ $js_table = array();
+ foreach ($acl as $user => $rights) {
+ if ($this->rc->storage->conn->user == $user) {
+ continue;
+ }
+
+ // filter out virtual rights (c or d) the server may return
+ $userrights = array_intersect($rights, $supported);
+ $userid = html_identifier($user);
+
+ if (!empty($this->specials) && in_array($user, $this->specials)) {
+ $user = $this->gettext($user);
+ }
+
+ $table->add_row(array('id' => 'rcmrow'.$userid));
+ $table->add('user', Q($user));
+
+ foreach ($items as $key => $right) {
+ $in = $this->acl_compare($userrights, $right);
+ switch ($in) {
+ case 2: $class = 'enabled'; break;
+ case 1: $class = 'partial'; break;
+ default: $class = 'disabled'; break;
+ }
+ $table->add('acl' . $key . ' ' . $class, '');
+ }
+
+ $js_table[$userid] = implode($userrights);
+ }
+
+ $this->rc->output->set_env('acl', $js_table);
+ $this->rc->output->set_env('acl_advanced', $advanced);
+
+ $out = $table->show();
+
+ return $out;
+ }
+
+ /**
+ * Handler for ACL update/create action
+ */
+ private function action_save()
+ {
+ $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); // UTF7-IMAP
+ $user = trim(get_input_value('_user', RCUBE_INPUT_GPC));
+ $acl = trim(get_input_value('_acl', RCUBE_INPUT_GPC));
+ $oldid = trim(get_input_value('_old', RCUBE_INPUT_GPC));
+
+ $acl = array_intersect(str_split($acl), $this->rights_supported());
+ $users = $oldid ? array($user) : explode(',', $user);
+
+ foreach ($users as $user) {
+ $user = trim($user);
+
+ if (!empty($this->specials) && in_array($user, $this->specials)) {
+ $username = $this->gettext($user);
+ }
+ else {
+ if (!strpos($user, '@') && ($realm = $this->get_realm())) {
+ $user .= '@' . rcube_idn_to_ascii(preg_replace('/^@/', '', $realm));
+ }
+ $username = $user;
+ }
+
+ if (!$acl || !$user || !strlen($mbox)) {
+ continue;
+ }
+
+ if ($user != $_SESSION['username'] && $username != $_SESSION['username']) {
+ if ($this->rc->storage->set_acl($mbox, $user, $acl)) {
+ $ret = array('id' => html_identifier($user),
+ 'username' => $username, 'acl' => implode($acl), 'old' => $oldid);
+ $this->rc->output->command('acl_update', $ret);
+ $result++;
+ }
+ }
+ }
+
+ if ($result) {
+ $this->rc->output->show_message($oldid ? 'acl.updatesuccess' : 'acl.createsuccess', 'confirmation');
+ }
+ else {
+ $this->rc->output->show_message($oldid ? 'acl.updateerror' : 'acl.createerror', 'error');
+ }
+ }
+
+ /**
+ * Handler for ACL delete action
+ */
+ private function action_delete()
+ {
+ $mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); //UTF7-IMAP
+ $user = trim(get_input_value('_user', RCUBE_INPUT_GPC));
+
+ $user = explode(',', $user);
+
+ foreach ($user as $u) {
+ $u = trim($u);
+ if ($this->rc->storage->delete_acl($mbox, $u)) {
+ $this->rc->output->command('acl_remove_row', html_identifier($u));
+ }
+ else {
+ $error = true;
+ }
+ }
+
+ if (!$error) {
+ $this->rc->output->show_message('acl.deletesuccess', 'confirmation');
+ }
+ else {
+ $this->rc->output->show_message('acl.deleteerror', 'error');
+ }
+ }
+
+ /**
+ * Handler for ACL list update action (with display mode change)
+ */
+ private function action_list()
+ {
+ if (in_array('acl_advanced_mode', (array)$this->rc->config->get('dont_override'))) {
+ return;
+ }
+
+ $this->mbox = trim(get_input_value('_mbox', RCUBE_INPUT_GPC, true)); // UTF7-IMAP
+ $advanced = trim(get_input_value('_mode', RCUBE_INPUT_GPC));
+ $advanced = $advanced == 'advanced' ? true : false;
+
+ // Save state in user preferences
+ $this->rc->user->save_prefs(array('acl_advanced_mode' => $advanced));
+
+ $out = $this->list_rights();
+
+ $out = preg_replace(array('/^<table[^>]+>/', '/<\/table>$/'), '', $out);
+
+ $this->rc->output->command('acl_list_update', $out);
+ }
+
+ /**
+ * Creates <UL> list with descriptive access rights
+ *
+ * @param array $rights MYRIGHTS result
+ *
+ * @return string HTML content
+ */
+ function acl2text($rights)
+ {
+ if (empty($rights)) {
+ return '';
+ }
+
+ $supported = $this->rights_supported();
+ $list = array();
+ $attrib = array(
+ 'name' => 'rcmyrights',
+ 'style' => 'margin:0; padding:0 15px;',
+ );
+
+ foreach ($supported as $right) {
+ if (in_array($right, $rights)) {
+ $list[] = html::tag('li', null, Q($this->gettext('acl' . $right)));
+ }
+ }
+
+ if (count($list) == count($supported))
+ return Q($this->gettext('aclfull'));
+
+ return html::tag('ul', $attrib, implode("\n", $list));
+ }
+
+ /**
+ * Compares two ACLs (according to supported rights)
+ *
+ * @param array $acl1 ACL rights array (or string)
+ * @param array $acl2 ACL rights array (or string)
+ *
+ * @param int Comparision result, 2 - full match, 1 - partial match, 0 - no match
+ */
+ function acl_compare($acl1, $acl2)
+ {
+ if (!is_array($acl1)) $acl1 = str_split($acl1);
+ if (!is_array($acl2)) $acl2 = str_split($acl2);
+
+ $rights = $this->rights_supported();
+
+ $acl1 = array_intersect($acl1, $rights);
+ $acl2 = array_intersect($acl2, $rights);
+ $res = array_intersect($acl1, $acl2);
+
+ $cnt1 = count($res);
+ $cnt2 = count($acl2);
+
+ if ($cnt1 == $cnt2)
+ return 2;
+ else if ($cnt1)
+ return 1;
+ else
+ return 0;
+ }
+
+ /**
+ * Get list of supported access rights (according to RIGHTS capability)
+ *
+ * @return array List of supported access rights abbreviations
+ */
+ function rights_supported()
+ {
+ if ($this->supported !== null) {
+ return $this->supported;
+ }
+
+ $capa = $this->rc->storage->get_capability('RIGHTS');
+
+ if (is_array($capa)) {
+ $rights = strtolower($capa[0]);
+ }
+ else {
+ $rights = 'cd';
+ }
+
+ return $this->supported = str_split('lrswi' . $rights . 'pa');
+ }
+
+ /**
+ * Username realm detection.
+ *
+ * @return string Username realm (domain)
+ */
+ private function get_realm()
+ {
+ // When user enters a username without domain part, realm
+ // alows to add it to the username (and display correct username in the table)
+
+ if (isset($_SESSION['acl_username_realm'])) {
+ return $_SESSION['acl_username_realm'];
+ }
+
+ // find realm in username of logged user (?)
+ list($name, $domain) = explode('@', $_SESSION['username']);
+
+ // Use (always existent) ACL entry on the INBOX for the user to determine
+ // whether or not the user ID in ACL entries need to be qualified and how
+ // they would need to be qualified.
+ if (empty($domain)) {
+ $acl = $this->rc->storage->get_acl('INBOX');
+ if (is_array($acl)) {
+ $regexp = '/^' . preg_quote($_SESSION['username'], '/') . '@(.*)$/';
+ foreach (array_keys($acl) as $name) {
+ if (preg_match($regexp, $name, $matches)) {
+ $domain = $matches[1];
+ break;
+ }
+ }
+ }
+ }
+
+ return $_SESSION['acl_username_realm'] = $domain;
+ }
+
+ /**
+ * Initializes autocomplete LDAP backend
+ */
+ private function init_ldap()
+ {
+ if ($this->ldap)
+ return $this->ldap->ready;
+
+ // get LDAP config
+ $config = $this->rc->config->get('acl_users_source');
+
+ if (empty($config)) {
+ return false;
+ }
+
+ // not an array, use configured ldap_public source
+ if (!is_array($config)) {
+ $ldap_config = (array) $this->rc->config->get('ldap_public');
+ $config = $ldap_config[$config];
+ }
+
+ $uid_field = $this->rc->config->get('acl_users_field', 'mail');
+ $filter = $this->rc->config->get('acl_users_filter');
+
+ if (empty($uid_field) || empty($config)) {
+ return false;
+ }
+
+ // get name attribute
+ if (!empty($config['fieldmap'])) {
+ $name_field = $config['fieldmap']['name'];
+ }
+ // ... no fieldmap, use the old method
+ if (empty($name_field)) {
+ $name_field = $config['name_field'];
+ }
+
+ // add UID field to fieldmap, so it will be returned in a record with name
+ $config['fieldmap'] = array(
+ 'name' => $name_field,
+ 'uid' => $uid_field,
+ );
+
+ // search in UID and name fields
+ $config['search_fields'] = array_values($config['fieldmap']);
+ $config['required_fields'] = array($uid_field);
+
+ // set search filter
+ if ($filter)
+ $config['filter'] = $filter;
+
+ // disable vlv
+ $config['vlv'] = false;
+
+ // Initialize LDAP connection
+ $this->ldap = new rcube_ldap($config,
+ $this->rc->config->get('ldap_debug'),
+ $this->rc->config->mail_domain($_SESSION['imap_host']));
+
+ return $this->ldap->ready;
+ }
+}
View
19 plugins/acl/config.inc.php.dist
@@ -0,0 +1,19 @@
+<?php
+
+// Default look of access rights table
+// In advanced mode all access rights are displayed separately
+// In simple mode access rights are grouped into four groups: read, write, delete, full
+$rcmail_config['acl_advanced_mode'] = false;
+
+// LDAP addressbook that would be searched for user names autocomplete.
+// That should be an array refering to the $rcmail_config['ldap_public'] array key
+// or complete addressbook configuration array.
+$rcmail_config['acl_users_source'] = '';
+
+// The LDAP attribute which will be used as ACL user identifier
+$rcmail_config['acl_users_field'] = 'mail';
+
+// The LDAP search filter will be &'d with search queries
+$rcmail_config['acl_users_filter'] = '';
+
+?>
View
83 plugins/acl/localization/de_DE.inc
@@ -0,0 +1,83 @@
+<?php
+
+$labels['sharing'] = 'Freigabe';
+$labels['myrights'] = 'Zugriffsrechte';
+$labels['username'] = 'Benutzer:';
+$labels['advanced'] = 'erweiterter Modus';
+$labels['newuser'] = 'Eintrag hinzufügen';
+$labels['actions'] = 'Zugriffsrechte Aktionen...';
+$labels['anyone'] = 'Alle Benutzer (anyone)';
+$labels['anonymous'] = 'Gäste (anonymous)';
+$labels['identifier'] = 'Bezeichnung';
+
+$labels['acll'] = 'Ordner sichtbar';
+$labels['aclr'] = 'Nachrichten lesen';
+$labels['acls'] = 'Lesestatus ändern';
+$labels['aclw'] = 'Flags schreiben';
+$labels['acli'] = 'Nachrichten Hinzufügen';
+$labels['aclp'] = 'Nachrichten Senden an';
+$labels['aclc'] = 'Unterordner erstellen';
+$labels['aclk'] = 'Unterordner erstellen';
+$labels['acld'] = 'Nachrichten als gelöscht markieren';
+$labels['aclt'] = 'Nachrichten als gelöscht markieren';
+$labels['acle'] = 'Nachrichten endgültig Löschen';
+$labels['aclx'] = 'Ordner löschen';
+$labels['acla'] = 'Zugriffsrechte Verwalten';
+
+$labels['aclfull'] = 'Vollzugriff';
+$labels['aclother'] = 'Andere';
+$labels['aclread'] = 'Lesen';
+$labels['aclwrite'] = 'Schreiben';
+$labels['acldelete'] = 'Löschen';
+
+$labels['shortacll'] = 'Sichtbar';
+$labels['shortaclr'] = 'Lesen';
+$labels['shortacls'] = 'Lesestatus';
+$labels['shortaclw'] = 'Flags ändern';
+$labels['shortacli'] = 'Hinzufügen';
+$labels['shortaclp'] = 'Senden an';
+$labels['shortaclc'] = 'Erstellen';
+$labels['shortaclk'] = 'Erstellen';
+$labels['shortacld'] = 'Löschen';
+$labels['shortaclt'] = 'Löschen';
+$labels['shortacle'] = 'endgültig löschen';
+$labels['shortaclx'] = 'Ordner löschen';
+$labels['shortacla'] = 'Verwalten';
+
+$labels['shortaclother'] = 'Andere';
+$labels['shortaclread'] = 'Lesen';
+$labels['shortaclwrite'] = 'Schreiben';
+$labels['shortacldelete'] = 'Löschen';
+
+$labels['longacll'] = 'Der Ordner ist sichtbar und kann abonniert werden';
+$labels['longaclr'] = 'Nachrichten im Ordner können gelesen werden';
+$labels['longacls'] = 'Der Lesestatus von Nachrichten kann geändert werden';
+$labels['longaclw'] = 'Alle Nachrichten-Flags und Schlüsselwörter außer "Gelesen" und "Gelöscht" können geändert werden';
+$labels['longacli'] = 'Nachrichten können in diesen Ordner kopiert oder verschoben werden';
+$labels['longaclp'] = 'Nachrichten können an diesen Ordner gesendet werden';
+$labels['longaclc'] = 'Unterordner können in diesem Ordner erstellt oder umbenannt werden';
+$labels['longaclk'] = 'Unterordner können in diesem Ordner erstellt oder umbenannt werden';
+$labels['longacld'] = 'Der "gelöscht" Status von Nachrichten kann geändert werden';
+$labels['longaclt'] = 'Der "gelöscht" Status von Nachrichten kann geändert werden';
+$labels['longacle'] = 'Als "gelöscht" markiert Nachrichten können gelöscht werden.';
+$labels['longaclx'] = 'Der Ordner kann gelöscht oder umbenannt werden';
+$labels['longacla'] = 'Die Zugriffsrechte des Ordners können geändert werden';
+
+$labels['longaclfull'] = 'Vollzugriff inklusive Ordner-Verwaltung';
+$labels['longaclread'] = 'Der Ordnerinhalt kann gelesen werden';
+$labels['longaclwrite'] = 'Nachrichten können markiert, an den Ordner gesendet und in den Ordner kopiert oder verschoben werden';
+$labels['longacldelete'] = 'Nachrichten können gelöscht werden';
+
+$messages['deleting'] = 'Zugriffsrechte werden entzogen...';
+$messages['saving'] = 'Zugriffsrechte werden gewährt...';
+$messages['updatesuccess'] = 'Zugriffsrechte erfolgreich geändert';
+$messages['deletesuccess'] = 'Zugriffsrechte erfolgreich entzogen';
+$messages['createsuccess'] = 'Zugriffsrechte erfolgreich gewährt';
+$messages['updateerror'] = 'Zugriffsrechte konnten nicht geändert werden';
+$messages['deleteerror'] = 'Zugriffsrechte konnten nicht entzogen werden';
+$messages['createerror'] = 'Zugriffsrechte konnten nicht gewährt werden';
+$messages['deleteconfirm'] = 'Sind Sie sicher, daß Sie die Zugriffsrechte den ausgewählten Benutzern entziehen möchten?';
+$messages['norights'] = 'Es wurden keine Zugriffsrechte ausgewählt!';
+$messages['nouser'] = 'Es wurde kein Benutzer ausgewählt!';
+
+?>
View
83 plugins/acl/localization/en_US.inc
@@ -0,0 +1,83 @@
+<?php
+
+$labels['sharing'] = 'Sharing';
+$labels['myrights'] = 'Access Rights';
+$labels['username'] = 'User:';
+$labels['advanced'] = 'advanced mode';
+$labels['newuser'] = 'Add entry';
+$labels['actions'] = 'Access right actions...';
+$labels['anyone'] = 'All users (anyone)';
+$labels['anonymous'] = 'Guests (anonymous)';
+$labels['identifier'] = 'Identifier';
+
+$labels['acll'] = 'Lookup';
+$labels['aclr'] = 'Read messages';
+$labels['acls'] = 'Keep Seen state';
+$labels['aclw'] = 'Write flags';
+$labels['acli'] = 'Insert (Copy into)';
+$labels['aclp'] = 'Post';
+$labels['aclc'] = 'Create subfolders';
+$labels['aclk'] = 'Create subfolders';
+$labels['acld'] = 'Delete messages';
+$labels['aclt'] = 'Delete messages';
+$labels['acle'] = 'Expunge';
+$labels['aclx'] = 'Delete folder';
+$labels['acla'] = 'Administer';
+
+$labels['aclfull'] = 'Full control';
+$labels['aclother'] = 'Other';
+$labels['aclread'] = 'Read';
+$labels['aclwrite'] = 'Write';
+$labels['acldelete'] = 'Delete';
+
+$labels['shortacll'] = 'Lookup';
+$labels['shortaclr'] = 'Read';
+$labels['shortacls'] = 'Keep';
+$labels['shortaclw'] = 'Write';
+$labels['shortacli'] = 'Insert';
+$labels['shortaclp'] = 'Post';
+$labels['shortaclc'] = 'Create';
+$labels['shortaclk'] = 'Create';
+$labels['shortacld'] = 'Delete';
+$labels['shortaclt'] = 'Delete';
+$labels['shortacle'] = 'Expunge';
+$labels['shortaclx'] = 'Folder delete';
+$labels['shortacla'] = 'Administer';
+
+$labels['shortaclother'] = 'Other';
+$labels['shortaclread'] = 'Read';
+$labels['shortaclwrite'] = 'Write';
+$labels['shortacldelete'] = 'Delete';
+
+$labels['longacll'] = 'The folder is visible on lists and can be subscribed to';
+$labels['longaclr'] = 'The folder can be opened for reading';
+$labels['longacls'] = 'Messages Seen flag can be changed';
+$labels['longaclw'] = 'Messages flags and keywords can be changed, except Seen and Deleted';
+$labels['longacli'] = 'Messages can be written or copied to the folder';
+$labels['longaclp'] = 'Messages can be posted to this folder';
+$labels['longaclc'] = 'Folders can be created (or renamed) directly under this folder';
+$labels['longaclk'] = 'Folders can be created (or renamed) directly under this folder';
+$labels['longacld'] = 'Messages Delete flag can be changed';
+$labels['longaclt'] = 'Messages Delete flag can be changed';
+$labels['longacle'] = 'Messages can be expunged';
+$labels['longaclx'] = 'The folder can be deleted or renamed';
+$labels['longacla'] = 'The folder access rights can be changed';
+
+$labels['longaclfull'] = 'Full control including folder administration';
+$labels['longaclread'] = 'The folder can be opened for reading';
+$labels['longaclwrite'] = 'Messages can be marked, written or copied to the folder';
+$labels['longacldelete'] = 'Messages can be deleted';
+
+$messages['deleting'] = 'Deleting access rights...';
+$messages['saving'] = 'Saving access rights...';
+$messages['updatesuccess'] = 'Successfully changed access rights';
+$messages['deletesuccess'] = 'Successfully deleted access rights';
+$messages['createsuccess'] = 'Successfully added access rights';
+$messages['updateerror'] = 'Ubable to update access rights';
+$messages['deleteerror'] = 'Unable to delete access rights';
+$messages['createerror'] = 'Unable to add access rights';
+$messages['deleteconfirm'] = 'Are you sure, you want to remove access rights of selected user(s)?';
+$messages['norights'] = 'No rights has been specified!';
+$messages['nouser'] = 'No username has been specified!';
+
+?>
View
83 plugins/acl/localization/pl_PL.inc
@@ -0,0 +1,83 @@
+<?php
+
+$labels['sharing'] = 'Udostępnianie';
+$labels['myrights'] = 'Prawa dostępu';
+$labels['username'] = 'Użytkownik:';
+$labels['advanced'] = 'tryb zaawansowany';
+$labels['newuser'] = 'Dodaj rekord';
+$labels['actions'] = 'Akcje na prawach...';
+$labels['anyone'] = 'Wszyscy (anyone)';
+$labels['anonymous'] = 'Goście (anonymous)';
+$labels['identifier'] = 'Identyfikator';
+
+$labels['acll'] = 'Podgląd (Lookup)';
+$labels['aclr'] = 'Odczyt (Read)';
+$labels['acls'] = 'Zmiana stanu wiadomości (Keep)';
+$labels['aclw'] = 'Zmiana flag wiadomości (Write)';
+$labels['acli'] = 'Dodawanie/Kopiowanie do (Insert)';
+$labels['aclp'] = 'Wysyłanie (Post)';
+$labels['aclc'] = 'Tworzenie podfolderów (Create)';
+$labels['aclk'] = 'Tworzenie podfolderów (Create)';
+$labels['acld'] = 'Usuwanie wiadomości (Delete)';
+$labels['aclt'] = 'Usuwanie wiadomości (Delete)';
+$labels['acle'] = 'Porządkowanie folderu (Expunge)';
+$labels['aclx'] = 'Usuwanie folderu (Delete)';
+$labels['acla'] = 'Administracja (Administer)';
+
+$labels['aclfull'] = 'Wszystkie';
+$labels['aclother'] = 'Inne';
+$labels['aclread'] = 'Odczyt';
+$labels['aclwrite'] = 'Zapis';
+$labels['acldelete'] = 'Usuwanie';
+
+$labels['shortacll'] = 'Podgląd';
+$labels['shortaclr'] = 'Odczyt';
+$labels['shortacls'] = 'Zmiana';
+$labels['shortaclw'] = 'Zmiana flag';
+$labels['shortacli'] = 'Dodawanie';
+$labels['shortaclp'] = 'Wysyłanie';
+$labels['shortaclc'] = 'Tworzenie';
+$labels['shortaclk'] = 'Tworzenie';
+$labels['shortacld'] = 'Usuwanie';
+$labels['shortaclt'] = 'Usuwanie';
+$labels['shortacle'] = 'Porządkowanie';
+$labels['shortaclx'] = 'Usuwanie folderu';
+$labels['shortacla'] = 'Administracja';
+
+$labels['shortaclother'] = 'Pozostałe';
+$labels['shortaclread'] = 'Odczyt';
+$labels['shortaclwrite'] = 'Zapis';
+$labels['shortacldelete'] = 'Usuwanie';
+
+$labels['longacll'] = 'Pozwala na subskrybowanie folderu i powoduje, że jest on widoczny na liście';
+$labels['longaclr'] = 'Pozwala na otwarcie folderu w trybie do odczytu';
+$labels['longacls'] = 'Pozwala na zmienę stanu wiadomości';
+$labels['longaclw'] = 'Pozwala zmieniać wszystkie flagi wiadomości, oprócz "Przeczytano" i "Usunięto"';
+$labels['longacli'] = 'Pozwala zapisywać wiadomości i kopiować do folderu';
+$labels['longaclp'] = 'Pozwala wysyłać wiadomości do folderu';
+$labels['longaclc'] = 'Pozwala tworzyć (lub zmieniać nazwę) podfoldery';
+$labels['longaclk'] = 'Pozwala tworzyć (lub zmieniać nazwę) podfoldery';
+$labels['longacld'] = 'Pozwala zmianiać flagę "Usunięto" wiadomości';
+$labels['longaclt'] = 'Pozwala zmianiać flagę "Usunięto" wiadomości';
+$labels['longacle'] = 'Pozwala na usuwanie wiadomości oznaczonych do usunięcia';
+$labels['longaclx'] = 'Pozwala na zmianę nazwy lub usunięcie folderu';
+$labels['longacla'] = 'Pozwala na zmiane praw dostępu do folderu';
+
+$labels['longaclfull'] = 'Pełna kontrola włącznie z administrowaniem folderem';
+$labels['longaclread'] = 'Folder może być otwarty w trybie do odczytu';
+$labels['longaclwrite'] = 'Wiadomości mogą być oznaczane, zapisywane i kopiowane do folderu';
+$labels['longacldelete'] = 'Wiadomości mogą być usuwane';
+
+$messages['deleting'] = 'Usuwanie praw dostępu...';
+$messages['saving'] = 'Zapisywanie praw dostępu...';
+$messages['updatesuccess'] = 'Pomyślnie zmieniono prawa dostępu';
+$messages['deletesuccess'] = 'Pomyślnie usunięto prawa dostępu';
+$messages['createsuccess'] = 'Pomyślnie dodano prawa dostępu';
+$messages['updateerror'] = 'Nie udało się zmienić praw dostępu';
+$messages['deleteerror'] = 'Nie udało się usunąć praw dostępu';
+$messages['createerror'] = 'Nie udało się dodać praw dostępu';
+$messages['deleteconfirm'] = 'Czy na pewno chcesz usunąć prawa wybranym użytkownikom?';
+$messages['norights'] = 'Nie wybrano praw dostępu!';
+$messages['nouser'] = 'Nie podano nazwy użytkownika!';
+
+?>
View
59 plugins/acl/package.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" packagerversion="1.9.0" version="2.0" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+ http://pear.php.net/dtd/tasks-1.0.xsd
+ http://pear.php.net/dtd/package-2.0
+ http://pear.php.net/dtd/package-2.0.xsd">
+ <name>acl</name>
+ <channel>pear.roundcube.net</channel>
+ <summary>Folders Access Control Lists</summary>
+ <description>IMAP Folders Access Control Lists Management (RFC4314, RFC2086).</description>
+ <lead>
+ <name>Aleksander Machniak</name>
+ <user>alec</user>
+ <email>alec@alec.pl</email>
+ <active>yes</active>
+ </lead>
+ <date>2012-01-10</date>
+ <version>
+ <release>0.7</release>
+ <api>0.7</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPLv2</license>
+ <notes>-</notes>
+ <contents>
+ <dir baseinstalldir="/" name="/">
+ <file name="acl.php" role="php">
+ <tasks:replace from="@name@" to="name" type="package-info"/>
+ <tasks:replace from="@package_version@" to="version" type="package-info"/>
+ </file>
+ <file name="acl.js" role="data">
+ <tasks:replace from="@name@" to="name" type="package-info"/>
+ <tasks:replace from="@package_version@" to="version" type="package-info"/>
+ </file>
+ <file name="config.inc.php.dist" role="data"></file>
+ <file name="localization/de_DE.inc" role="data"></file>
+ <file name="localization/en_US.inc" role="data"></file>
+ <file name="localization/pl_PL.inc" role="data"></file>
+ <file name="skins/default/acl.css" role="data"></file>
+ <file name="skins/default/images/enabled.png" role="data"></file>
+ <file name="skins/default/images/partial.png" role="data"></file>
+ <file name="skins/default/templates/table.html" role="data"></file>
+ </dir>
+ <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.2.1</min>
+ </php>
+ <pearinstaller>
+ <min>1.7.0</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <phprelease/>
+</package>
View
100 plugins/acl/skins/default/acl.css
@@ -0,0 +1,100 @@
+#aclmanager
+{
+ position: relative;
+ border: 1px solid #999;
+ min-height: 302px;
+}
+
+#aclcontainer
+{
+ overflow-x: auto;
+}
+
+#acltable
+{
+ width: 100%;
+ border-collapse: collapse;
+ background-color: #F9F9F9;
+}
+
+#acltable td
+{
+ width: 1%;
+ white-space: nowrap;
+}
+
+#acltable thead td
+{
+ padding: 0 4px 0 2px;
+}
+
+#acltable tbody td
+{
+ text-align: center;
+ padding: 2px;
+ border-bottom: 1px solid #999999;
+ cursor: default;
+}
+
+#acltable tbody td.user
+{
+ width: 96%;
+ text-align: left;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -o-text-overflow: ellipsis;
+}
+
+#acltable tbody td.partial
+{
+ background: url(images/partial.png) center no-repeat;
+}
+
+#acltable tbody td.enabled
+{
+ background: url(images/enabled.png) center no-repeat;
+}
+
+#acltable tr.selected td
+{
+ color: #FFFFFF;
+ background-color: #CC3333;
+}
+
+#acltable tr.unfocused td
+{
+ color: #FFFFFF;
+ background-color: #929292;
+}
+
+#acladvswitch
+{
+ position: absolute;
+ right: 4px;
+ text-align: right;
+ line-height: 22px;
+}
+
+#acladvswitch input
+{
+ vertical-align: middle;
+}
+
+#acladvswitch span
+{
+ display: block;
+}
+
+#aclform
+{
+ top: 80px;
+ width: 480px;
+ padding: 10px;
+}
+
+#aclform div
+{
+ padding: 0;
+ text-align: center;
+ clear: both;
+}
View
BIN  plugins/acl/skins/default/images/enabled.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  plugins/acl/skins/default/images/partial.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
54 plugins/acl/skins/default/templates/table.html
@@ -0,0 +1,54 @@
+<!--[if lte IE 6]>
+ <style type="text/css">
+ #aclmanager { height: expression(Math.min(302, parseInt(document.documentElement.clientHeight))+'px'); }
+ </style>
+<![endif]-->
+
+<div id="aclmanager">
+<div id="aclcontainer" class="boxlistcontent" style="top:0">
+ <roundcube:object name="acltable" id="acltable" class="records-table" />
+</div>
+<div class="boxfooter">
+ <roundcube:button command="acl-create" id="aclcreatelink" type="link" title="acl.newuser" class="buttonPas addgroup" classAct="button addgroup" content=" " />
+ <roundcube:button name="aclmenulink" id="aclmenulink" type="link" title="acl.actions" class="button groupactions" onclick="show_aclmenu(); return false" content=" " />
+ <roundcube:if condition="!in_array('acl_advanced_mode', (array)config:dont_override)" />
+ <div id="acladvswitch" class="pagenav">
+ <span><label for="acl-switch"><roundcube:label name="acl.advanced" /></label>
+ <input type="checkbox" id="acl-switch" onclick="rcmail.command('acl-mode-switch')"<roundcube:exp expression="config:acl_advanced_mode == true ? ' checked=checked' : ''" /> />
+ </span>
+ </div>
+ <roundcube:endif />
+</div>
+</div>
+
+<div id="aclmenu" class="popupmenu">
+ <ul>
+ <li><roundcube:button command="acl-edit" label="edit" classAct="active" /></li>
+ <li><roundcube:button command="acl-delete" label="delete" classAct="active" /></li>
+ </ul>
+</div>
+
+<div id="aclform" class="popupmenu">
+ <fieldset class="thinbordered"><legend><roundcube:label name="acl.identifier" /></legend>
+ <roundcube:object name="acluser" class="toolbarmenu" id="acluser" size="35" />
+ </fieldset>
+ <fieldset class="thinbordered"><legend><roundcube:label name="acl.myrights" /></legend>
+ <roundcube:object name="aclrights" class="toolbarmenu" />
+ </fieldset>
+ <div>
+ <roundcube:button command="acl-cancel" type="input" class="button" label="cancel" />
+ <roundcube:button command="acl-save" type="input" class="button mainaction" label="save" />
+ </div>
+</div>
+
+<script type="text/javascript">
+function show_aclmenu()
+{
+ if (!rcmail_ui) {
+ rcube_init_mail_ui();
+ rcmail_ui.popups.aclmenu = {id:'aclmenu', above:1, obj: $('#aclmenu')};
+ }
+
+ rcmail_ui.show_popup('aclmenu');
+}
+</script>
View
43 plugins/additional_message_headers/additional_message_headers.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Additional Message Headers
+ *
+ * Very simple plugin which will add additional headers
+ * to or remove them from outgoing messages.
+ *
+ * Enable the plugin in config/main.inc.php and add your desired headers:
+ * $rcmail_config['additional_message_headers'] = array('User-Agent');
+ *
+ * @version @package_version@
+ * @author Ziba Scott
+ * @website http://roundcube.net
+ */
+class additional_message_headers extends rcube_plugin
+{
+ public $task = 'mail';
+
+ function init()
+ {
+ $this->add_hook('message_outgoing_headers', array($this, 'message_headers'));
+ }
+
+ function message_headers($args)
+ {
+ $this->load_config();
+
+ // additional email headers
+ $additional_headers = rcmail::get_instance()->config->get('additional_message_headers',array());
+ foreach($additional_headers as $header=>$value){
+ if (null === $value) {
+ unset($args['headers'][$header]);
+ } else {
+ $args['headers'][$header] = $value;
+ }
+ }
+
+ return $args;
+ }
+}
+
+?>
View
14 plugins/additional_message_headers/config.inc.php.dist
@@ -0,0 +1,14 @@
+<?php
+
+// $rcmail_config['additional_message_headers']['X-Remote-Browser'] = $_SERVER['HTTP_USER_AGENT'];
+// $rcmail_config['additional_message_headers']['X-Originating-IP'] = $_SERVER['REMOTE_ADDR'];
+// $rcmail_config['additional_message_headers']['X-RoundCube-Server'] = $_SERVER['SERVER_ADDR'];
+
+// if( isset( $_SERVER['MACHINE_NAME'] )) {
+// $rcmail_config['additional_message_headers']['X-RoundCube-Server'] .= ' (' . $_SERVER['MACHINE_NAME'] . ')';
+// }
+
+// To remove (e.g. X-Sender) message header use null value
+// $rcmail_config['additional_message_headers']['X-Sender'] = null;
+
+?>
View
48 plugins/additional_message_headers/package.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.9.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+ http://pear.php.net/dtd/tasks-1.0.xsd
+ http://pear.php.net/dtd/package-2.0
+ http://pear.php.net/dtd/package-2.0.xsd">
+ <name>additional_message_headers</name>
+ <channel>pear.roundcube.net</channel>
+ <summary>Additional message headers for Roundcube</summary>
+ <description>Very simple plugin which will add additional headers to or remove them from outgoing messages.</description>
+ <lead>
+ <name>Ziba Scott</name>
+ <user>ziba</user>
+ <email>email@example.org</email>
+ <active>yes</active>
+ </lead>
+ <date>2010-01-16</date>
+ <time>18:19:33</time>
+ <version>
+ <release>1.1.0</release>
+ <api>1.1.0</api>
+ </version>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <license uri="http://www.gnu.org/licenses/gpl-2.0.html">GNU GPL v2</license>
+ <notes>-</notes>
+ <contents>
+ <dir baseinstalldir="/" name="/">
+ <file name="additional_message_headers.php" role="php">
+ <tasks:replace from="@name@" to="name" type="package-info" />
+ <tasks:replace from="@package_version@" to="version" type="package-info" />
+ </file>
+ <file name="config.inc.php.dist" role="data"></file>
+ </dir> <!-- / -->
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>5.2.1</min>
+ </php>
+ <pearinstaller>
+ <min>1.7.0</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <phprelease />
+</package>
View
34 plugins/archive/archive.js
@@ -0,0 +1,34 @@
+/*
+ * Archive plugin script
+ * @version @package_version@
+ */
+
+function rcmail_archive(prop)
+{
+ if (!rcmail.env.uid && (!rcmail.message_list || !rcmail.message_list.get_selection().length))
+ return;
+
+ if (rcmail.env.mailbox != rcmail.env.archive_folder)
+ rcmail.command('moveto', rcmail.env.archive_folder);
+}
+
+// callback for app-onload event
+if (window.rcmail) {
+ rcmail.addEventListener('init', function(evt) {
+
+ // register command (directly enable in message view mode)
+ rcmail.register_command('plugin.archive', rcmail_archive, (rcmail.env.uid && rcmail.env.mailbox != rcmail.env.archive_folder));
+
+ // add event-listener to message list
+ if (rcmail.message_list)
+ rcmail.message_list.addEventListener('select', function(list){
+ rcmail.enable_command('plugin.archive', (list.get_selection().length > 0 && rcmail.env.mailbox != rcmail.env.archive_folder));
+ });
+
+ // set css style for archive folder
+ var li;
+ if (rcmail.env.archive_folder && (li = rcmail.get_folder_li(rcmail.env.archive_folder, '', true)))
+ $(li).addClass('archive');
+ })
+}
+
View
128 plugins/archive/archive.php
@@ -0,0 +1,128 @@
+<?php
+
+/**
+ * Archive
+ *
+ * Plugin that adds a new button to the mailbox toolbar
+ * to move messages to a (user selectable) archive folder.
+ *
+ * @version @package_version@
+ * @license GNU GPLv3+
+ * @author Andre Rodier, Thomas Bruederli
+ */
+class archive extends rcube_plugin
+{
+ public $task = 'mail|settings';
+
+ function init()
+ {
+ $rcmail = rcmail::get_instance();
+
+ // There is no "Archived flags"
+ // $GLOBALS['IMAP_FLAGS']['ARCHIVED'] = 'Archive';
+ if ($rcmail->task == 'mail' && ($rcmail->action == '' || $rcmail->action == 'show')
+ && ($archive_folder = $rcmail->config->get('archive_mbox'))) {
+ $skin_path = $this->local_skin_path();
+ if (is_file($this->home . "/$skin_path/archive.css"))
+ $this->include_stylesheet("$skin_path/archive.css");
+
+ $this->include_script('archive.js');
+ $this->add_texts('localization', true);
+ $this->add_button(
+ array(
+ 'type' => 'link',
+ 'label' => 'buttontext',
+ 'command' => 'plugin.archive',
+ 'class' => 'button buttonPas archive disabled',
+ 'classact' => 'button archive',
+ 'width' => 32,
+ 'height' => 32,
+ 'title' => 'buttontitle',
+ 'domain' => $this->ID,
+ ),
+ 'toolbar');
+
+ // register hook to localize the archive folder
+ $this->add_hook('render_mailboxlist', array($this, 'render_mailboxlist'));
+
+ // set env variable for client
+ $rcmail->output->set_env('archive_folder', $archive_folder);
+
+ // add archive folder to the list of default mailboxes
+ if (($default_folders = $rcmail->config->get('default_folders')) && !in_array($archive_folder, $default_folders)) {
+ $default_folders[] = $archive_folder;
+ $rcmail->config->set('default_folders', $default_folders);
+ }
+ }
+ else if ($rcmail->task == 'settings') {
+ $dont_override = $rcmail->config->get('dont_override', array());
+ if (!in_array('archive_mbox', $dont_override)) {
+ $this->add_hook('preferences_list', array($this, 'prefs_table'));
+ $this->add_hook('preferences_save', array($this, 'save_prefs'));
+ }
+ }
+ }
+
+ function render_mailboxlist($p)
+ {
+ $rcmail = rcmail::get_instance();
+ $archive_folder = $rcmail->config->get('archive_mbox');
+
+ // set localized name for the configured archive folder
+ if ($archive_folder) {
+ if (isset($p['list'][$archive_folder]))
+ $p['list'][$archive_folder]['name'] = $this->gettext('archivefolder');
+ else // search in subfolders
+ $this->_mod_folder_name($p['list'], $archive_folder, $this->gettext('archivefolder'));
+ }
+
+ return $p;
+ }
+
+ function _mod_folder_name(&$list, $folder, $new_name)
+ {
+ foreach ($list as $idx => $item) {
+ if ($item['id'] == $folder) {
+ $list[$idx]['name'] = $new_name;
+ return true;
+ } else if (!empty($item['folders']))
+ if ($this->_mod_folder_name($list[$idx]['folders'], $folder, $new_name))
+ return true;
+ }
+ return false;
+ }
+
+ function prefs_table($args)
+ {
+ global $CURR_SECTION;
+
+ if ($args['section'] == 'folders') {
+ $this->add_texts('localization');
+
+ $rcmail = rcmail::get_instance();
+
+ // load folders list when needed
+ if ($CURR_SECTION)
+ $select = rcmail_mailbox_select(array('noselection' => '---', 'realnames' => true,
+ 'maxlength' => 30, 'exceptions' => array('INBOX'), 'folder_filter' => 'mail', 'folder_rights' => 'w'));
+ else
+ $select = new html_select();
+
+ $args['blocks']['main']['options']['archive_mbox'] = array(
+ 'title' => $this->gettext('archivefolder'),
+ 'content' => $select->show($rcmail->config->get('archive_mbox'), array('name' => "_archive_mbox"))
+ );
+ }
+
+ return $args;
+ }
+
+ function save_prefs($args)
+ {
+ if ($args['section'] == 'folders') {
+ $args['prefs']['archive_mbox'] = get_input_value('_archive_mbox', RCUBE_INPUT_POST);
+ return $args;
+ }
+ }
+
+}
View
25 plugins/archive/localization/cs_CZ.inc
@@ -0,0 +1,25 @@
+<?php
+
+/*
+
++-----------------------------------------------------------------------+
+| language/cs_CZ/labels.inc |
+| |
+| Language file of the Roundcube archive plugin |
+| Copyright (C) 2005-2009, The Roundcube Dev Team |
+| Licensed under the GNU GPL |
+| |
++-----------------------------------------------------------------------+
+| Author: Milan Kozak <hodza@hodza.net> |
++-----------------------------------------------------------------------+
+
+@version $Id: labels.inc 2993 2009-09-26 18:32:07Z alec $
+
+*/
+
+$labels = array();
+$labels['buttontitle'] = 'Archivovat zprávu';
+$labels['archived'] = 'Úspěšně vloženo do archivu';
+$labels['archivefolder'] = 'Archiv';
+
+?>
View
8 plugins/archive/localization/de_CH.inc
@@ -0,0 +1,8 @@
+<?php
+
+$labels = array();
+$labels['buttontitle'] = 'Nachricht archivieren';
+$labels['archived'] = 'Nachricht erfolgreich archiviert';
+$labels['archivefolder'] = 'Archiv';
+
+?>
View
8 plugins/archive/localization/de_DE.inc
@@ -0,0 +1,8 @@
+<?php
+
+$labels = array();
+$labels['buttontitle'] = 'Nachricht archivieren';
+$labels['archived'] = 'Nachricht erfolgreich archiviert';
+$labels['archivefolder'] = 'Archiv';
+
+?>
View
9 plugins/archive/localization/en_US.inc
@@ -0,0 +1,9 @@
+<?php
+
+$labels = array();
+$labels['buttontext'] = 'Archive';
+$labels['buttontitle'] = 'Archive this message';
+$labels['archived'] = 'Successfully archived';
+$labels['archivefolder'] = 'Archive';
+
+?>
View
10 plugins/archive/localization/es_AR.inc
@@ -0,0 +1,10 @@
+<?php
+
+// MPBAUPGRADE
+
+$labels = array();
+$labels['buttontitle'] = 'Archivar este mensaje';
+$labels['archived'] = 'Mensaje Archivado';
+$labels['archivefolder'] = 'Archivo';
+
+?>
View
10 plugins/archive/localization/es_ES.inc
@@ -0,0 +1,10 @@
+<?php
+
+// MPBAUPGRADE
+
+$labels = array();
+$labels['buttontitle'] = 'Archivar este mensaje';
+$labels['archived'] = 'Mensaje Archivado';
+$labels['archivefolder'] = 'Archivo';
+
+?>
View
8 plugins/archive/localization/et_EE.inc
@@ -0,0 +1,8 @@