1<?php 2 3/** 4 +-----------------------------------------------------------------------+ 5 | This file is part of the Roundcube Webmail client | 6 | | 7 | Copyright (C) The Roundcube Dev Team | 8 | Copyright (C) Kolab Systems AG | 9 | | 10 | Licensed under the GNU General Public License version 3 or | 11 | any later version with exceptions for skins & plugins. | 12 | See the README file for a full license statement. | 13 | | 14 | PURPOSE: | 15 | Mail Storage Engine | 16 +-----------------------------------------------------------------------+ 17 | Author: Thomas Bruederli <roundcube@gmail.com> | 18 | Author: Aleksander Machniak <alec@alec.pl> | 19 +-----------------------------------------------------------------------+ 20*/ 21 22/** 23 * Abstract class for accessing mail messages storage server 24 * 25 * @package Framework 26 * @subpackage Storage 27 */ 28abstract class rcube_storage 29{ 30 /** 31 * Instance of connection object e.g. rcube_imap_generic 32 * 33 * @var mixed 34 */ 35 public $conn; 36 37 /** 38 * List of supported special folder types 39 * 40 * @var array 41 */ 42 public static $folder_types = ['drafts', 'sent', 'junk', 'trash']; 43 44 protected $folder = 'INBOX'; 45 protected $default_charset = 'ISO-8859-1'; 46 protected $options = ['auth_type' => 'check', 'language' => 'en_US']; 47 protected $page_size = 10; 48 protected $list_page = 1; 49 protected $threading = false; 50 protected $search_set; 51 52 /** 53 * Internal (in-memory) cache 54 * 55 * @var array 56 */ 57 protected $icache = []; 58 59 /** 60 * All (additional) headers used (in any way) by Roundcube 61 * Not listed here: DATE, FROM, TO, CC, REPLY-TO, SUBJECT, CONTENT-TYPE, LIST-POST 62 * (used for messages listing) are hardcoded in rcube_imap_generic::fetchHeaders() 63 * 64 * @var array 65 */ 66 protected $all_headers = [ 67 'CONTENT-TRANSFER-ENCODING', 68 'BCC', 69 'IN-REPLY-TO', 70 'MAIL-FOLLOWUP-TO', 71 'MAIL-REPLY-TO', 72 'MESSAGE-ID', 73 'REFERENCES', 74 'RESENT-BCC', 75 'RETURN-PATH', 76 'SENDER', 77 'X-DRAFT-INFO', 78 ]; 79 80 const UNKNOWN = 0; 81 const NOPERM = 1; 82 const READONLY = 2; 83 const TRYCREATE = 3; 84 const INUSE = 4; 85 const OVERQUOTA = 5; 86 const ALREADYEXISTS = 6; 87 const NONEXISTENT = 7; 88 const CONTACTADMIN = 8; 89 90 const DUAL_USE_FOLDERS = 'X-DUAL-USE-FOLDERS'; 91 92 93 /** 94 * Connect to the server 95 * 96 * @param string $host Host to connect 97 * @param string $user Username for IMAP account 98 * @param string $pass Password for IMAP account 99 * @param integer $port Port to connect to 100 * @param string $use_ssl SSL schema (either ssl or tls) or null if plain connection 101 * 102 * @return bool True on success, False on failure 103 */ 104 abstract function connect($host, $user, $pass, $port = 143, $use_ssl = null); 105 106 /** 107 * Close connection. Usually done on script shutdown 108 */ 109 abstract function close(); 110 111 /** 112 * Checks connection state. 113 * 114 * @return bool True on success, False on failure 115 */ 116 abstract function is_connected(); 117 118 /** 119 * Check connection state, connect if not connected. 120 * 121 * @return bool Connection state. 122 */ 123 abstract function check_connection(); 124 125 /** 126 * Returns code of last error 127 * 128 * @return int Error code 129 */ 130 abstract function get_error_code(); 131 132 /** 133 * Returns message of last error 134 * 135 * @return string Error message 136 */ 137 abstract function get_error_str(); 138 139 /** 140 * Returns code of last command response 141 * 142 * @return int Response code (class constant) 143 */ 144 abstract function get_response_code(); 145 146 /** 147 * Set connection and class options 148 * 149 * @param array $opt Options array 150 */ 151 public function set_options($opt) 152 { 153 $this->options = array_merge($this->options, (array) $opt); 154 } 155 156 /** 157 * Get connection/class option 158 * 159 * @param string $name Option name 160 * 161 * @param mixed Option value 162 */ 163 public function get_option($name) 164 { 165 return $this->options[$name]; 166 } 167 168 /** 169 * Activate/deactivate debug mode. 170 * 171 * @param bool $dbg True if conversation with the server should be logged 172 */ 173 abstract function set_debug($dbg = true); 174 175 /** 176 * Set default message charset. 177 * 178 * This will be used for message decoding if a charset specification is not available 179 * 180 * @param string $cs Charset string 181 */ 182 public function set_charset($cs) 183 { 184 $this->default_charset = $cs; 185 } 186 187 /** 188 * Set internal folder reference. 189 * All operations will be performed on this folder. 190 * 191 * @param string $folder Folder name 192 */ 193 public function set_folder($folder) 194 { 195 if ($this->folder === $folder) { 196 return; 197 } 198 199 $this->folder = $folder; 200 } 201 202 /** 203 * Returns the currently used folder name 204 * 205 * @return string Name of the folder 206 */ 207 public function get_folder() 208 { 209 return $this->folder; 210 } 211 212 /** 213 * Set internal list page number. 214 * 215 * @param int $page Page number to list 216 */ 217 public function set_page($page) 218 { 219 if ($page = intval($page)) { 220 $this->list_page = $page; 221 } 222 } 223 224 /** 225 * Gets internal list page number. 226 * 227 * @return int Page number 228 */ 229 public function get_page() 230 { 231 return $this->list_page; 232 } 233 234 /** 235 * Set internal page size 236 * 237 * @param int $size Number of messages to display on one page 238 */ 239 public function set_pagesize($size) 240 { 241 $this->page_size = (int) $size; 242 } 243 244 /** 245 * Get internal page size 246 * 247 * @return int Number of messages to display on one page 248 */ 249 public function get_pagesize() 250 { 251 return $this->page_size; 252 } 253 254 /** 255 * Save a search result for future message listing methods. 256 * 257 * @param mixed $set Search set in driver specific format 258 */ 259 abstract function set_search_set($set); 260 261 /** 262 * Return the saved search set. 263 * 264 * @return array Search set in driver specific format, NULL if search wasn't initialized 265 */ 266 abstract function get_search_set(); 267 268 /** 269 * Returns the storage server's (IMAP) capability 270 * 271 * @param string $cap Capability name 272 * 273 * @return mixed Capability value or True if supported, False if not 274 */ 275 abstract function get_capability($cap); 276 277 /** 278 * Sets threading flag to the best supported THREAD algorithm. 279 * Enable/Disable threaded mode. 280 * 281 * @param bool $enable True to enable threading 282 * 283 * @return mixed Threading algorithm or False if THREAD is not supported 284 */ 285 public function set_threading($enable = false) 286 { 287 $this->threading = false; 288 289 if ($enable && ($caps = $this->get_capability('THREAD'))) { 290 $methods = ['REFS', 'REFERENCES', 'ORDEREDSUBJECT']; 291 $methods = array_intersect($methods, $caps); 292 293 $this->threading = array_first($methods); 294 } 295 296 return $this->threading; 297 } 298 299 /** 300 * Get current threading flag. 301 * 302 * @return mixed Threading algorithm or False if THREAD is not supported or disabled 303 */ 304 public function get_threading() 305 { 306 return $this->threading; 307 } 308 309 /** 310 * Checks the PERMANENTFLAGS capability of the current folder 311 * and returns true if the given flag is supported by the server. 312 * 313 * @param string $flag Permanentflag name 314 * 315 * @return bool True if this flag is supported 316 */ 317 abstract function check_permflag($flag); 318 319 /** 320 * Returns the delimiter that is used by the server 321 * for folder hierarchy separation. 322 * 323 * @return string Delimiter string 324 */ 325 abstract function get_hierarchy_delimiter(); 326 327 /** 328 * Get namespace 329 * 330 * @param string $name Namespace array index: personal, other, shared, prefix 331 * 332 * @return array Namespace data 333 */ 334 abstract function get_namespace($name = null); 335 336 /** 337 * Get messages count for a specific folder. 338 * 339 * @param string $folder Folder name 340 * @param string $mode Mode for count [ALL|THREADS|UNSEEN|RECENT|EXISTS] 341 * @param bool $force Force reading from server and update cache 342 * @param bool $status Enables storing folder status info (max UID/count), 343 * required for folder_status() 344 * 345 * @return int Number of messages 346 */ 347 abstract function count($folder = null, $mode = 'ALL', $force = false, $status = true); 348 349 /** 350 * Public method for listing message flags 351 * 352 * @param string $folder Folder name 353 * @param array $uids Message UIDs 354 * @param int $mod_seq Optional MODSEQ value 355 * 356 * @return array Indexed array with message flags 357 */ 358 abstract function list_flags($folder, $uids, $mod_seq = null); 359 360 /** 361 * Public method for listing headers. 362 * 363 * @param string $folder Folder name 364 * @param int $page Current page to list 365 * @param string $sort_field Header field to sort by 366 * @param string $sort_order Sort order [ASC|DESC] 367 * @param int $slice Number of slice items to extract from result array 368 * 369 * @return array Indexed array with message header objects 370 */ 371 abstract function list_messages($folder = null, $page = null, $sort_field = null, $sort_order = null, $slice = 0); 372 373 /** 374 * Return sorted list of message UIDs 375 * 376 * @param string $folder Folder to get index from 377 * @param string $sort_field Sort column 378 * @param string $sort_order Sort order [ASC, DESC] 379 * 380 * @return rcube_result_index|rcube_result_thread List of messages (UIDs) 381 */ 382 abstract function index($folder = null, $sort_field = null, $sort_order = null); 383 384 /** 385 * Invoke search request to the server. 386 * 387 * @param string $folder Folder name to search in 388 * @param string $str Search criteria 389 * @param string $charset Search charset 390 * @param string $sort_field Header field to sort by 391 * 392 * @todo: Search criteria should be provided in non-IMAP format, e.g. array 393 */ 394 abstract function search($folder = null, $str = 'ALL', $charset = null, $sort_field = null); 395 396 /** 397 * Direct (real and simple) search request (without result sorting and caching). 398 * 399 * @param string $folder Folder name to search in 400 * @param string $str Search string 401 * 402 * @return rcube_result_index Search result (UIDs) 403 */ 404 abstract function search_once($folder = null, $str = 'ALL'); 405 406 /** 407 * Refresh saved search set 408 * 409 * @return array Current search set 410 */ 411 abstract function refresh_search(); 412 413 414 /* -------------------------------- 415 * messages management 416 * --------------------------------*/ 417 418 /** 419 * Fetch message headers and body structure from the server and build 420 * an object structure. 421 * 422 * @param int $uid Message UID to fetch 423 * @param string $folder Folder to read from 424 * 425 * @return object rcube_message_header Message data 426 */ 427 abstract function get_message($uid, $folder = null); 428 429 /** 430 * Return message headers object of a specific message 431 * 432 * @param int $id Message sequence ID or UID 433 * @param string $folder Folder to read from 434 * @param bool $force True to skip cache 435 * 436 * @return rcube_message_header Message headers 437 */ 438 abstract function get_message_headers($uid, $folder = null, $force = false); 439 440 /** 441 * Fetch message body of a specific message from the server 442 * 443 * @param int $uid Message UID 444 * @param string $part Part number 445 * @param rcube_message_part $o_part Part object created by get_structure() 446 * @param mixed $print True to print part, resource to write part contents in 447 * @param resource $fp File pointer to save the message part 448 * @param bool $skip_charset_conv Disables charset conversion 449 * 450 * @return string Message/part body if not printed 451 */ 452 abstract function get_message_part($uid, $part = 1, $o_part = null, $print = null, $fp = null, $skip_charset_conv = false); 453 454 /** 455 * Fetch message body of a specific message from the server 456 * 457 * @param int $uid Message UID 458 * 459 * @return string $part Message/part body 460 * @see rcube_imap::get_message_part() 461 */ 462 public function get_body($uid, $part = 1) 463 { 464 $headers = $this->get_message_headers($uid); 465 return rcube_charset::convert($this->get_message_part($uid, $part, null), 466 $headers->charset ?: $this->default_charset); 467 } 468 469 /** 470 * Returns the whole message source as string (or saves to a file) 471 * 472 * @param int $uid Message UID 473 * @param resource $fp File pointer to save the message 474 * @param string $part Optional message part ID 475 * 476 * @return string Message source string 477 */ 478 abstract function get_raw_body($uid, $fp = null, $part = null); 479 480 /** 481 * Returns the message headers as string 482 * 483 * @param int $uid Message UID 484 * @param string $part Optional message part ID 485 * 486 * @return string Message headers string 487 */ 488 abstract function get_raw_headers($uid, $part = null); 489 490 /** 491 * Sends the whole message source to stdout 492 * 493 * @param int $uid Message UID 494 * @param bool $formatted Enables line-ending formatting 495 */ 496 abstract function print_raw_body($uid, $formatted = true); 497 498 /** 499 * Set message flag to one or several messages 500 * 501 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 502 * @param string $flag Flag to set: SEEN, UNDELETED, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT 503 * @param string $folder Folder name 504 * @param bool $skip_cache True to skip message cache clean up 505 * 506 * @return bool Operation status 507 */ 508 abstract function set_flag($uids, $flag, $folder = null, $skip_cache = false); 509 510 /** 511 * Remove message flag for one or several messages 512 * 513 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 514 * @param string $flag Flag to unset: SEEN, DELETED, RECENT, ANSWERED, DRAFT, MDNSENT 515 * @param string $folder Folder name 516 * 517 * @return bool Operation status 518 * @see set_flag 519 */ 520 public function unset_flag($uids, $flag, $folder = null) 521 { 522 return $this->set_flag($uids, 'UN'.$flag, $folder); 523 } 524 525 /** 526 * Append a mail message (source) to a specific folder. 527 * 528 * @param string $folder Target folder 529 * @param string|array $message The message source string or filename 530 * or array (of strings and file pointers) 531 * @param string $headers Headers string if $message contains only the body 532 * @param bool $is_file True if $message is a filename 533 * @param array $flags Message flags 534 * @param mixed $date Message internal date 535 * 536 * @return int|bool Appended message UID or True on success, False on error 537 */ 538 abstract function save_message($folder, &$message, $headers = '', $is_file = false, $flags = [], $date = null); 539 540 /** 541 * Move message(s) from one folder to another. 542 * 543 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 544 * @param string $to Target folder 545 * @param string $from Source folder 546 * 547 * @return bool True on success, False on error 548 */ 549 abstract function move_message($uids, $to, $from = null); 550 551 /** 552 * Copy message(s) from one mailbox to another. 553 * 554 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 555 * @param string $to Target folder 556 * @param string $from Source folder 557 * 558 * @return bool True on success, False on error 559 */ 560 abstract function copy_message($uids, $to, $from = null); 561 562 /** 563 * Mark message(s) as deleted and expunge. 564 * 565 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 566 * @param string $folder Source folder 567 * 568 * @return bool True on success, False on error 569 */ 570 abstract function delete_message($uids, $folder = null); 571 572 /** 573 * Expunge message(s) and clear the cache. 574 * 575 * @param mixed $uids Message UIDs as array or comma-separated string, or '*' 576 * @param string $folder Folder name 577 * @param bool $clear_cache False if cache should not be cleared 578 * 579 * @return bool True on success, False on error 580 */ 581 abstract function expunge_message($uids, $folder = null, $clear_cache = true); 582 583 /** 584 * Parse message UIDs input 585 * 586 * @param mixed $uids UIDs array or comma-separated list or '*' or '1:*' 587 * 588 * @return array Two elements array with UIDs converted to list and ALL flag 589 */ 590 protected function parse_uids($uids) 591 { 592 $all = false; 593 594 if ($uids === '*' || $uids === '1:*') { 595 if (empty($this->search_set)) { 596 $uids = '1:*'; 597 $all = true; 598 } 599 // get UIDs from current search set 600 else { 601 $uids = implode(',', $this->search_set->get()); 602 } 603 } 604 else { 605 if (is_array($uids)) { 606 $uids = implode(',', $uids); 607 } 608 else if (strpos($uids, ':')) { 609 $uids = implode(',', rcube_imap_generic::uncompressMessageSet($uids)); 610 } 611 612 if (preg_match('/[^0-9,]/', $uids)) { 613 $uids = ''; 614 } 615 } 616 617 return [$uids, $all]; 618 } 619 620 621 /* -------------------------------- 622 * folder management 623 * --------------------------------*/ 624 625 /** 626 * Get a list of subscribed folders. 627 * 628 * @param string $root Optional root folder 629 * @param string $name Optional name pattern 630 * @param string $filter Optional filter 631 * @param string $rights Optional ACL requirements 632 * @param bool $skip_sort Enable to return unsorted list (for better performance) 633 * 634 * @return array List of folders 635 */ 636 abstract function list_folders_subscribed($root = '', $name = '*', $filter = null, $rights = null, $skip_sort = false); 637 638 /** 639 * Get a list of all folders available on the server. 640 * 641 * @param string $root IMAP root dir 642 * @param string $name Optional name pattern 643 * @param mixed $filter Optional filter 644 * @param string $rights Optional ACL requirements 645 * @param bool $skip_sort Enable to return unsorted list (for better performance) 646 * 647 * @return array Indexed array with folder names 648 */ 649 abstract function list_folders($root = '', $name = '*', $filter = null, $rights = null, $skip_sort = false); 650 651 /** 652 * Subscribe to a specific folder(s) 653 * 654 * @param array $folders Folder name(s) 655 * 656 * @return bool True on success 657 */ 658 abstract function subscribe($folders); 659 660 /** 661 * Unsubscribe folder(s) 662 * 663 * @param array $folders Folder name(s) 664 * 665 * @return bool True on success 666 */ 667 abstract function unsubscribe($folders); 668 669 /** 670 * Create a new folder on the server. 671 * 672 * @param string $folder New folder name 673 * @param bool $subscribe True if the new folder should be subscribed 674 * @param string $type Optional folder type (junk, trash, drafts, sent, archive) 675 * @param bool $noselect Make the folder \NoSelect folder by adding hierarchy 676 * separator at the end (useful for server that do not support 677 * both folders and messages as folder children) 678 * 679 * @return bool True on success, False on error 680 */ 681 abstract function create_folder($folder, $subscribe = false, $type = null, $noselect = false); 682 683 /** 684 * Set a new name to an existing folder 685 * 686 * @param string $folder Folder to rename 687 * @param string $new_name New folder name 688 * 689 * @return bool True on success, False on error 690 */ 691 abstract function rename_folder($folder, $new_name); 692 693 /** 694 * Remove a folder from the server. 695 * 696 * @param string $folder Folder name 697 * 698 * @return bool True on success, False on error 699 */ 700 abstract function delete_folder($folder); 701 702 /** 703 * Send expunge command and clear the cache. 704 * 705 * @param string $folder Folder name 706 * @param bool $clear_cache False if cache should not be cleared 707 * 708 * @return bool True on success, False on error 709 */ 710 public function expunge_folder($folder = null, $clear_cache = true) 711 { 712 return $this->expunge_message('*', $folder, $clear_cache); 713 } 714 715 /** 716 * Remove all messages in a folder.. 717 * 718 * @param string $folder Folder name 719 * 720 * @return bool True on success, False on error 721 */ 722 public function clear_folder($folder = null) 723 { 724 return $this->delete_message('*', $folder); 725 } 726 727 /** 728 * Checks if folder exists and is subscribed 729 * 730 * @param string $folder Folder name 731 * @param bool $subscription Enable subscription checking 732 * 733 * @return bool True if folder exists, False otherwise 734 */ 735 abstract function folder_exists($folder, $subscription = false); 736 737 /** 738 * Get folder size (size of all messages in a folder) 739 * 740 * @param string $folder Folder name 741 * 742 * @return int Folder size in bytes, False on error 743 */ 744 abstract function folder_size($folder); 745 746 /** 747 * Returns the namespace where the folder is in 748 * 749 * @param string $folder Folder name 750 * 751 * @return string One of 'personal', 'other' or 'shared' 752 */ 753 abstract function folder_namespace($folder); 754 755 /** 756 * Gets folder attributes (from LIST response, e.g. \Noselect, \Noinferiors). 757 * 758 * @param string $folder Folder name 759 * @param bool $force Set to True if attributes should be refreshed 760 * 761 * @return array Options list 762 */ 763 abstract function folder_attributes($folder, $force = false); 764 765 /** 766 * Gets connection (and current folder) data: UIDVALIDITY, EXISTS, RECENT, 767 * PERMANENTFLAGS, UIDNEXT, UNSEEN 768 * 769 * @param string $folder Folder name 770 * 771 * @return array Data 772 */ 773 abstract function folder_data($folder); 774 775 /** 776 * Returns extended information about the folder. 777 * 778 * @param string $folder Folder name 779 * 780 * @return array Data 781 */ 782 abstract function folder_info($folder); 783 784 /** 785 * Returns current status of a folder (compared to the last time use) 786 * 787 * @param string $folder Folder name 788 * @param array $diff Difference data 789 * 790 * @return int Folder status 791 */ 792 abstract function folder_status($folder = null, &$diff = []); 793 794 /** 795 * Synchronizes messages cache. 796 * 797 * @param string $folder Folder name 798 */ 799 abstract function folder_sync($folder); 800 801 /** 802 * Modify folder name according to namespace. 803 * For output it removes prefix of the personal namespace if it's possible. 804 * For input it adds the prefix. Use it before creating a folder in root 805 * of the folders tree. 806 * 807 * @param string $folder Folder name 808 * @param string $mode Mode name (out/in) 809 * 810 * @return string Folder name 811 */ 812 abstract function mod_folder($folder, $mode = 'out'); 813 814 /** 815 * Check if the folder name is valid 816 * 817 * @param string $folder Folder name (UTF-8) 818 * @param string &$char First forbidden character found 819 * 820 * @return bool True if the name is valid, False otherwise 821 */ 822 public function folder_validate($folder, &$char = null) 823 { 824 $delim = $this->get_hierarchy_delimiter(); 825 826 if (strpos($folder, $delim) !== false) { 827 $char = $delim; 828 return false; 829 } 830 831 return true; 832 } 833 834 /** 835 * Create all folders specified as default 836 */ 837 public function create_default_folders() 838 { 839 $rcube = rcube::get_instance(); 840 841 // create default folders if they do not exist 842 foreach (self::$folder_types as $type) { 843 if ($folder = $rcube->config->get($type . '_mbox')) { 844 if (!$this->folder_exists($folder)) { 845 $this->create_folder($folder, true, $type); 846 } 847 else if (!$this->folder_exists($folder, true)) { 848 $this->subscribe($folder); 849 } 850 } 851 } 852 } 853 854 /** 855 * Check if specified folder is a special folder 856 */ 857 public function is_special_folder($name) 858 { 859 return $name == 'INBOX' || in_array($name, $this->get_special_folders()); 860 } 861 862 /** 863 * Return configured special folders 864 */ 865 public function get_special_folders($forced = false) 866 { 867 // getting config might be expensive, store special folders in memory 868 if (!isset($this->icache['special-folders'])) { 869 $rcube = rcube::get_instance(); 870 $this->icache['special-folders'] = []; 871 872 foreach (self::$folder_types as $type) { 873 if ($folder = $rcube->config->get($type . '_mbox')) { 874 $this->icache['special-folders'][$type] = $folder; 875 } 876 } 877 } 878 879 return $this->icache['special-folders']; 880 } 881 882 /** 883 * Set special folder associations stored in backend 884 */ 885 public function set_special_folders($specials) 886 { 887 // should be overridden by storage class if backend supports special folders (SPECIAL-USE) 888 unset($this->icache['special-folders']); 889 } 890 891 /** 892 * Get mailbox quota information. 893 * 894 * @param string $folder Folder name 895 * 896 * @return mixed Quota info or False if not supported 897 */ 898 abstract function get_quota($folder = null); 899 900 901 /* ----------------------------------------- 902 * ACL and METADATA methods 903 * ----------------------------------------*/ 904 905 /** 906 * Changes the ACL on the specified folder (SETACL) 907 * 908 * @param string $folder Folder name 909 * @param string $user User name 910 * @param string $acl ACL string 911 * 912 * @return bool True on success, False on failure 913 */ 914 abstract function set_acl($folder, $user, $acl); 915 916 /** 917 * Removes any <identifier,rights> pair for the 918 * specified user from the ACL for the specified 919 * folder (DELETEACL). 920 * 921 * @param string $folder Folder name 922 * @param string $user User name 923 * 924 * @return bool True on success, False on failure 925 */ 926 abstract function delete_acl($folder, $user); 927 928 /** 929 * Returns the access control list for a folder (GETACL). 930 * 931 * @param string $folder Folder name 932 * 933 * @return array User-rights array on success, NULL on error 934 */ 935 abstract function get_acl($folder); 936 937 /** 938 * Returns information about what rights can be granted to the 939 * user (identifier) in the ACL for the folder (LISTRIGHTS). 940 * 941 * @param string $folder Folder name 942 * @param string $user User name 943 * 944 * @return array List of user rights 945 */ 946 abstract function list_rights($folder, $user); 947 948 /** 949 * Returns the set of rights that the current user has to a folder (MYRIGHTS). 950 * 951 * @param string $folder Folder name 952 * 953 * @return array MYRIGHTS response on success, NULL on error 954 */ 955 abstract function my_rights($folder); 956 957 /** 958 * Sets metadata/annotations (SETMETADATA/SETANNOTATION) 959 * 960 * @param string $folder Folder name (empty for server metadata) 961 * @param array $entries Entry-value array (use NULL value as NIL) 962 * 963 * @return bool True on success, False on failure 964 */ 965 abstract function set_metadata($folder, $entries); 966 967 /** 968 * Unsets metadata/annotations (SETMETADATA/SETANNOTATION) 969 * 970 * @param string $folder Folder name (empty for server metadata) 971 * @param array $entries Entry names array 972 * 973 * @return bool True on success, False on failure 974 */ 975 abstract function delete_metadata($folder, $entries); 976 977 /** 978 * Returns folder metadata/annotations (GETMETADATA/GETANNOTATION). 979 * 980 * @param string $folder Folder name (empty for server metadata) 981 * @param array $entries Entries 982 * @param array $options Command options (with MAXSIZE and DEPTH keys) 983 * @param bool $force Disables cache use 984 * 985 * @return array Metadata entry-value hash array on success, NULL on error 986 */ 987 abstract function get_metadata($folder, $entries, $options = [], $force = false); 988 989 /* ----------------------------------------- 990 * Cache related functions 991 * ----------------------------------------*/ 992 993 /** 994 * Clears the cache. 995 * 996 * @param string $key Cache key name or pattern 997 * @param bool $prefix_mode Enable it to clear all keys starting 998 * with prefix specified in $key 999 */ 1000 abstract function clear_cache($key = null, $prefix_mode = false); 1001 1002 /** 1003 * Returns cached value 1004 * 1005 * @param string $key Cache key 1006 * 1007 * @return mixed Cached value 1008 */ 1009 abstract function get_cache($key); 1010 1011 /** 1012 * Delete outdated cache entries 1013 */ 1014 abstract function cache_gc(); 1015} 1016