├── CHANGELOG ├── LICENSE ├── LICENSE.txt ├── README.md ├── attachment.php ├── cache └── index.html ├── data └── index.html ├── details.php ├── inc ├── HTTP │ └── WebDAV │ │ ├── Server.php │ │ ├── Server │ │ └── Filesystem.php │ │ └── Tools │ │ ├── _parse_lockinfo.php │ │ ├── _parse_propfind.php │ │ └── _parse_proppatch.php ├── PEAR.php ├── PEAR │ ├── Autoloader.php │ ├── Builder.php │ ├── Command.php │ ├── Command │ │ ├── Auth.php │ │ ├── Build.php │ │ ├── Common.php │ │ ├── Config.php │ │ ├── Install.php │ │ ├── Mirror.php │ │ ├── Package.php │ │ ├── Registry.php │ │ └── Remote.php │ ├── Common.php │ ├── Config.php │ ├── Dependency.php │ ├── Downloader.php │ ├── ErrorStack.php │ ├── Exception.php │ ├── Frontend │ │ └── CLI.php │ ├── Installer.php │ ├── Packager.php │ ├── Registry.php │ ├── Remote.php │ └── RunTest.php ├── System.php ├── css.css ├── header.php ├── include.php └── libZotero.php ├── index.php ├── settings.php └── webdav_server.php /CHANGELOG: -------------------------------------------------------------------------------- 1 | 2013-05-29 2 | - Add support for storing attachments outside the phpZoteroWebDAV directory 3 | 4 | 2012-11-23 5 | - Add support for browsing by Collection 6 | 7 | 2012-11-04 8 | - Replace phpZotero library with proper official libZotero client 9 | - Add support for nginx and PHP as CGI 10 | - Add support for viewing web snapshots over HTTPS 11 | 12 | 2012-02-17 version 2.0m4 13 | - removed reference to unused (and thus missing) PEAR module 14 | 15 | 2011-11-28 version 2.0m3 16 | - attachment view was broken for attchments with linkMode=0 (i.e. most) since 2.0m3 - fixed 17 | 18 | 2011-11-23 version 2.0m2 19 | - added setting for timezone for servers that complain about it 20 | - detail view now observes the linkMode information, e.g. we now differentiate between stored websnapshots and web links 21 | 22 | 2011-11-03 version 2.0m1 23 | - added automatic delayed (5s) redirect to confidently identified web snapshot main page 24 | 25 | 2011-11-02 version 2.0 26 | first release of phpZoteroWebDAV 2.0. Major Changes since version 1.0 27 | - library view using Zotero Server API 28 | - attachment view from WebDAV data directory via server side cache 29 | - web snapshot view from WebDAV data directory via server side cache 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | phpZoteroWebDAV 2 | =============== 3 | 4 | Store your Zotero attachments on your own site, even on shared hosting. 5 | 6 | Features 7 | -------- 8 | 9 | - Sync library attachment to any webhosting space that supports PHP (including freely available ones). 10 | This means your attachment data is never stored on computers (clients or servers) that you do not control yourself. 11 | - Access your Zotero library on your own webspace through the zotero.org server API, including sorting, detail view, custom number of items per page etc 12 | - Browse your Zotero collections from any web browser 13 | - View your synced attachments (incl. web snapshots) from any web browser without having to use zotero.org's storage server 14 | - Enjoy complete security with support for HTTPS connections 15 | 16 | Installation and Configuration Instructions 17 | ------------------------------------------- 18 | http://blog.holz.ca/2011/11/phpzoterowebdav-installation/ 19 | http://blog.holz.ca/2011/10/proudly-presenting/ 20 | 21 | 22 | License 23 | ------- 24 | 25 | phpZoteroWebDAV was originally written by Christian Holz and is licensed under the AGPLv3 license. 26 | Significant updates have been made by: 27 | * fishburn (Real name unknown - https://github.com/fishburn) 28 | * David Dean 29 | 30 | phpZoteroWebDAV includes the following third party components: 31 | - The WebDAV server PEAR module written by Hartmut Holzgraefe as well as the PEAR base module, both licensed under the PHP license (http://www.php.net/license/3_01.txt) 32 | - The libZotero class for zotero API connection, released under an unknown open source license (https://github.com/fcheslack/libZotero) 33 | - The zotero.org css style sheet, apparently released under the AGPLv3 license (http://www.gnu.org/licenses/agpl.html)) 34 | 35 | -------------------------------------------------------------------------------- /attachment.php: -------------------------------------------------------------------------------- 1 |
\n"; 37 | $scriptpath = realpath(substr($_SERVER['SCRIPT_FILENAME'],0,strrpos($_SERVER['SCRIPT_FILENAME'],"/"))); 38 | if ($scriptpath == substr( get_real_path( $cache_dir ), 0, strlen($scriptpath) ) ) { 39 | $cacheURL = ( isset( $_SERVER['HTTPS'] ) ? 'https' : 'http' ) . '://' . $_SERVER['HTTP_HOST'] . substr($_SERVER['PHP_SELF'],0,strrpos($_SERVER['PHP_SELF'],"/")) . substr($abs_output,strlen($scriptpath)); 40 | } else { 41 | $cacheURL = $cache_base_URL; 42 | } 43 | if(strlen($cacheURL)>0) { 44 | $html_output .= "However, the websnap shot has been written to the cache directory and can be accessed there.
\n"; 45 | $webfilename=findwebfile($abs_output); 46 | if (strlen($webfilename)>0) { 47 | $html_output .= "Click here to access the file that looks most like the main file for the websnapshot (or wait 5 seconds to be redirected there).
\n"; 48 | $html_output .= "If that doens't work, check out the entire websnapshot folder and look for the main file yourself."; 49 | $html_output = "\n\n\n\n\n" . $html_output . "\n"; 50 | } else { 51 | $html_output .= "I didn't find a file that looks most like the main file for the websnapshot, "; 52 | $html_output .= "so you might want to check out the entire websnapshot folder and look for the main file yourself."; 53 | $html_output = "\n\n\n\n" . $html_output . "\n"; 54 | } 55 | } else { 56 | $html_output .= "However, if you use a cache directory which is located in the same directory as this script "; 57 | $html_output .= "($scriptpath) or you provide the base URL to whichever cache directory in the settings.php, "; 58 | $html_output .= "you would be able to use the workaround provided by this script."; 59 | $html_output = "\n\n\n\n" . $html_output . "\n"; 60 | } 61 | 62 | if( empty( $cache_base_URL ) ) { 63 | 64 | $output = file_get_contents($abs_output . '/' . $webfilename); 65 | 66 | // Add a as a hack to include CSS files 67 | if( preg_match('/\)/i', $output, $matches, PREG_OFFSET_CAPTURE ) ) { 68 | 69 | $head_start = $matches[0][1]; 70 | $head_end = $matches[2][1]; 71 | $output = substr( $output, 0, $head_end + 1 ) . '' . substr( $output, $head_end + 1 ); 72 | echo $output; 73 | 74 | } 75 | 76 | } else { 77 | 78 | echo $html_output; 79 | 80 | } 81 | 82 | } else { 83 | header("Content-type: " . $mimeType); 84 | header("Content-Disposition: filename=\"" . pathinfo($result, PATHINFO_BASENAME) . "\""); 85 | readfile($result); 86 | } 87 | } else { 88 | echo("AN ERROR HAS OCCURRED! - " . $result); 89 | } 90 | 91 | //purge old files from the cache again if $cache_age=0 (ie immediate deletion of cache files) 92 | if (($cache_age==0) && (strlen($cacheURL)==0)) { // do not purge immediately if web accessible websnapshot has been un zipped 93 | purge_cache( get_real_path( $cache_dir ), -1); 94 | } 95 | ?> 96 | -------------------------------------------------------------------------------- /cache/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | nothing to display 4 | 5 | 6 | -------------------------------------------------------------------------------- /data/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | nothing to display 4 | 5 | 6 | -------------------------------------------------------------------------------- /details.php: -------------------------------------------------------------------------------- 1 | setCacheTtl( $apc_cache_ttl ); 11 | 12 | //purge old files from the cache 13 | purge_cache( get_real_path( $cache_dir ), $cache_age); 14 | 15 | // reading item details from API 16 | $item = $zotero->fetchItem( $itemkey ); 17 | 18 | // displaying content of main item 19 | ?> 20 |
21 |

Item Details


22 | 23 | apiObject as $field_name => $field ) : 25 | 26 | // Apply any field-specific formatting 27 | switch( $field_name ) { 28 | case 'itemType': 29 | $field_formatted = un_camel( $field ); 30 | break; 31 | case 'tags': 32 | $field_formatted = implode( ', ', array_map( create_function( '$val', 'return $val["tag"];' ), $field ) ); 33 | break; 34 | case 'creators': 35 | $field_formatted = implode('
', array_map( create_function( '$val', 'return un_camel($val["creatorType"]) . ": " . $val["firstName"] . " " . $val["lastName"];' ), $field ) ); 36 | break; 37 | default: 38 | $field_formatted = $field; 39 | } 40 | 41 | ?> 42 | 43 | 44 | 45 | 46 | 47 |
48 |
49 |

Attachments (numChildren ?>)

50 |
51 | fetchItemChildren($item); 54 | 55 | if( $child_items ) { 56 | ?> 57 | 58 | 59 | 60 | 61 | 62 | apiObject as $field_name => $field ) : 64 | 65 | // Apply any field-specific formatting 66 | switch( $field_name ) { 67 | case 'tags': 68 | $field_formatted = implode( ', ', array_map( create_function( '$val', 'return $val["tag"];' ), $field ) ); 69 | break; 70 | default: 71 | $field_formatted = $field; 72 | } 73 | 74 | ?> 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | apiObject['linkMode'], array( 'linked_file', 'linked_url' ) ) ) { ?> 83 | 84 | 85 | 86 | 87 | 88 |
apiObject['title'] ?>
LinkapiObject['url'] ?>Access the Attachment as stored on the WebDAV server
89 |
90 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /inc/HTTP/WebDAV/Tools/_parse_lockinfo.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Christian Stocker | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: _parse_lockinfo.php,v 1.2 2004/01/05 12:32:40 hholzgra Exp $ 21 | // 22 | 23 | /** 24 | * helper class for parsing LOCK request bodies 25 | * 26 | * @package HTTP_WebDAV_Server 27 | * @author Hartmut Holzgraefe 28 | * @version 0.99.1dev 29 | */ 30 | class _parse_lockinfo 31 | { 32 | /** 33 | * success state flag 34 | * 35 | * @var bool 36 | * @access public 37 | */ 38 | var $success = false; 39 | 40 | /** 41 | * lock type, currently only "write" 42 | * 43 | * @var string 44 | * @access public 45 | */ 46 | var $locktype = ""; 47 | 48 | /** 49 | * lock scope, "shared" or "exclusive" 50 | * 51 | * @var string 52 | * @access public 53 | */ 54 | var $lockscope = ""; 55 | 56 | /** 57 | * lock owner information 58 | * 59 | * @var string 60 | * @access public 61 | */ 62 | var $owner = ""; 63 | 64 | /** 65 | * flag that is set during lock owner read 66 | * 67 | * @var bool 68 | * @access private 69 | */ 70 | var $collect_owner = false; 71 | 72 | /** 73 | * constructor 74 | * 75 | * @param string path of stream to read 76 | * @access public 77 | */ 78 | function _parse_lockinfo($path) 79 | { 80 | // we assume success unless problems occur 81 | $this->success = true; 82 | 83 | // remember if any input was parsed 84 | $had_input = false; 85 | 86 | // open stream 87 | $f_in = fopen($path, "r"); 88 | if (!$f_in) { 89 | $this->success = false; 90 | return; 91 | } 92 | 93 | // create namespace aware parser 94 | $xml_parser = xml_parser_create_ns("UTF-8", " "); 95 | 96 | // set tag and data handlers 97 | xml_set_element_handler($xml_parser, 98 | array(&$this, "_startElement"), 99 | array(&$this, "_endElement")); 100 | xml_set_character_data_handler($xml_parser, 101 | array(&$this, "_data")); 102 | 103 | // we want a case sensitive parser 104 | xml_parser_set_option($xml_parser, 105 | XML_OPTION_CASE_FOLDING, false); 106 | 107 | // parse input 108 | while($this->success && !feof($f_in)) { 109 | $line = fgets($f_in); 110 | if (is_string($line)) { 111 | $had_input = true; 112 | $this->success &= xml_parse($xml_parser, $line, false); 113 | } 114 | } 115 | 116 | // finish parsing 117 | if($had_input) { 118 | $this->success &= xml_parse($xml_parser, "", true); 119 | } 120 | 121 | // check if required tags where found 122 | $this->success &= !empty($this->locktype); 123 | $this->success &= !empty($this->lockscope); 124 | 125 | // free parser resource 126 | xml_parser_free($xml_parser); 127 | 128 | // close input stream 129 | fclose($f_in); 130 | } 131 | 132 | 133 | /** 134 | * tag start handler 135 | * 136 | * @param resource parser 137 | * @param string tag name 138 | * @param array tag attributes 139 | * @return void 140 | * @access private 141 | */ 142 | function _startElement($parser, $name, $attrs) 143 | { 144 | // namespace handling 145 | if (strstr($name, " ")) { 146 | list($ns, $tag) = explode(" ", $name); 147 | } else { 148 | $ns = ""; 149 | $tag = $name; 150 | } 151 | 152 | 153 | if ($this->collect_owner) { 154 | // everything within the tag needs to be collected 155 | $ns_short = ""; 156 | $ns_attr = ""; 157 | if ($ns) { 158 | if ($ns == "DAV:") { 159 | $ns_short = "D:"; 160 | } else { 161 | $ns_attr = " xmlns='$ns'"; 162 | } 163 | } 164 | $this->owner .= "<$ns_short$tag$ns_attr>"; 165 | } else if ($ns == "DAV:") { 166 | // parse only the essential tags 167 | switch ($tag) { 168 | case "write": 169 | $this->locktype = $tag; 170 | break; 171 | case "exclusive": 172 | case "shared": 173 | $this->lockscope = $tag; 174 | break; 175 | case "owner": 176 | $this->collect_owner = true; 177 | break; 178 | } 179 | } 180 | } 181 | 182 | /** 183 | * data handler 184 | * 185 | * @param resource parser 186 | * @param string data 187 | * @return void 188 | * @access private 189 | */ 190 | function _data($parser, $data) 191 | { 192 | // only the tag has data content 193 | if ($this->collect_owner) { 194 | $this->owner .= $data; 195 | } 196 | } 197 | 198 | /** 199 | * tag end handler 200 | * 201 | * @param resource parser 202 | * @param string tag name 203 | * @return void 204 | * @access private 205 | */ 206 | function _endElement($parser, $name) 207 | { 208 | // namespace handling 209 | if (strstr($name, " ")) { 210 | list($ns, $tag) = explode(" ", $name); 211 | } else { 212 | $ns = ""; 213 | $tag = $name; 214 | } 215 | 216 | // finished? 217 | if (($ns == "DAV:") && ($tag == "owner")) { 218 | $this->collect_owner = false; 219 | } 220 | 221 | // within we have to collect everything 222 | if ($this->collect_owner) { 223 | $ns_short = ""; 224 | $ns_attr = ""; 225 | if ($ns) { 226 | if ($ns == "DAV:") { 227 | $ns_short = "D:"; 228 | } else { 229 | $ns_attr = " xmlns='$ns'"; 230 | } 231 | } 232 | $this->owner .= ""; 233 | } 234 | } 235 | } 236 | 237 | ?> -------------------------------------------------------------------------------- /inc/HTTP/WebDAV/Tools/_parse_propfind.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Christian Stocker | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: _parse_propfind.php,v 1.2 2004/01/05 12:33:22 hholzgra Exp $ 21 | // 22 | 23 | /** 24 | * helper class for parsing PROPFIND request bodies 25 | * 26 | * @package HTTP_WebDAV_Server 27 | * @author Hartmut Holzgraefe 28 | * @version 0.99.1dev 29 | */ 30 | class _parse_propfind 31 | { 32 | /** 33 | * success state flag 34 | * 35 | * @var bool 36 | * @access public 37 | */ 38 | var $success = false; 39 | 40 | /** 41 | * found properties are collected here 42 | * 43 | * @var array 44 | * @access public 45 | */ 46 | var $props = false; 47 | 48 | /** 49 | * internal tag nesting depth counter 50 | * 51 | * @var int 52 | * @access private 53 | */ 54 | var $depth = 0; 55 | 56 | 57 | /** 58 | * constructor 59 | * 60 | * @access public 61 | */ 62 | function _parse_propfind($path) 63 | { 64 | // success state flag 65 | $this->success = true; 66 | 67 | // property storage array 68 | $this->props = array(); 69 | 70 | // internal tag depth counter 71 | $this->depth = 0; 72 | 73 | // remember if any input was parsed 74 | $had_input = false; 75 | 76 | // open input stream 77 | $f_in = fopen($path, "r"); 78 | if (!$f_in) { 79 | $this->success = false; 80 | return; 81 | } 82 | 83 | // create XML parser 84 | $xml_parser = xml_parser_create_ns("UTF-8", " "); 85 | 86 | // set tag and data handlers 87 | xml_set_element_handler($xml_parser, 88 | array(&$this, "_startElement"), 89 | array(&$this, "_endElement")); 90 | 91 | // we want a case sensitive parser 92 | xml_parser_set_option($xml_parser, 93 | XML_OPTION_CASE_FOLDING, false); 94 | 95 | 96 | // parse input 97 | while($this->success && !feof($f_in)) { 98 | $line = fgets($f_in); 99 | if (is_string($line)) { 100 | $had_input = true; 101 | $this->success &= xml_parse($xml_parser, $line, false); 102 | } 103 | } 104 | 105 | // finish parsing 106 | if($had_input) { 107 | $this->success &= xml_parse($xml_parser, "", true); 108 | } 109 | 110 | // free parser 111 | xml_parser_free($xml_parser); 112 | 113 | // close input stream 114 | fclose($f_in); 115 | 116 | // if no input was parsed it was a request 117 | if(!count($this->props)) $this->props = "all"; // default 118 | } 119 | 120 | 121 | /** 122 | * start tag handler 123 | * 124 | * @access private 125 | * @param resource parser 126 | * @param string tag name 127 | * @param array tag attributes 128 | */ 129 | function _startElement($parser, $name, $attrs) 130 | { 131 | // name space handling 132 | if (strstr($name, " ")) { 133 | list($ns, $tag) = explode(" ", $name); 134 | if ($ns == "") 135 | $this->success = false; 136 | } else { 137 | $ns = ""; 138 | $tag = $name; 139 | } 140 | 141 | // special tags at level 1: and 142 | if ($this->depth == 1) { 143 | if ($tag == "allprop") 144 | $this->props = "all"; 145 | 146 | if ($tag == "propname") 147 | $this->props = "names"; 148 | } 149 | 150 | // requested properties are found at level 2 151 | if ($this->depth == 2) { 152 | $prop = array("name" => $tag); 153 | if ($ns) 154 | $prop["xmlns"] = $ns; 155 | $this->props[] = $prop; 156 | } 157 | 158 | // increment depth count 159 | $this->depth++; 160 | } 161 | 162 | 163 | /** 164 | * end tag handler 165 | * 166 | * @access private 167 | * @param resource parser 168 | * @param string tag name 169 | */ 170 | function _endElement($parser, $name) 171 | { 172 | // here we only need to decrement the depth count 173 | $this->depth--; 174 | } 175 | } 176 | 177 | 178 | ?> -------------------------------------------------------------------------------- /inc/HTTP/WebDAV/Tools/_parse_proppatch.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Christian Stocker | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: _parse_proppatch.php,v 1.3 2004/01/05 12:41:34 hholzgra Exp $ 21 | // 22 | 23 | /** 24 | * helper class for parsing PROPPATCH request bodies 25 | * 26 | * @package HTTP_WebDAV_Server 27 | * @author Hartmut Holzgraefe 28 | * @version 0.99.1dev 29 | */ 30 | class _parse_proppatch 31 | { 32 | /** 33 | * 34 | * 35 | * @var 36 | * @access 37 | */ 38 | var $success; 39 | 40 | /** 41 | * 42 | * 43 | * @var 44 | * @access 45 | */ 46 | var $props; 47 | 48 | /** 49 | * 50 | * 51 | * @var 52 | * @access 53 | */ 54 | var $depth; 55 | 56 | /** 57 | * 58 | * 59 | * @var 60 | * @access 61 | */ 62 | var $mode; 63 | 64 | /** 65 | * 66 | * 67 | * @var 68 | * @access 69 | */ 70 | var $current; 71 | 72 | /** 73 | * constructor 74 | * 75 | * @param string path of input stream 76 | * @access public 77 | */ 78 | function _parse_proppatch($path) 79 | { 80 | $this->success = true; 81 | 82 | $this->depth = 0; 83 | $this->props = array(); 84 | $had_input = false; 85 | 86 | $f_in = fopen($path, "r"); 87 | if (!$f_in) { 88 | $this->success = false; 89 | return; 90 | } 91 | 92 | $xml_parser = xml_parser_create_ns("UTF-8", " "); 93 | 94 | xml_set_element_handler($xml_parser, 95 | array(&$this, "_startElement"), 96 | array(&$this, "_endElement")); 97 | 98 | xml_set_character_data_handler($xml_parser, 99 | array(&$this, "_data")); 100 | 101 | xml_parser_set_option($xml_parser, 102 | XML_OPTION_CASE_FOLDING, false); 103 | 104 | while($this->success && !feof($f_in)) { 105 | $line = fgets($f_in); 106 | if (is_string($line)) { 107 | $had_input = true; 108 | $this->success &= xml_parse($xml_parser, $line, false); 109 | } 110 | } 111 | 112 | if($had_input) { 113 | $this->success &= xml_parse($xml_parser, "", true); 114 | } 115 | 116 | xml_parser_free($xml_parser); 117 | 118 | fclose($f_in); 119 | } 120 | 121 | /** 122 | * tag start handler 123 | * 124 | * @param resource parser 125 | * @param string tag name 126 | * @param array tag attributes 127 | * @return void 128 | * @access private 129 | */ 130 | function _startElement($parser, $name, $attrs) 131 | { 132 | if (strstr($name, " ")) { 133 | list($ns, $tag) = explode(" ", $name); 134 | if ($ns == "") 135 | $this->success = false; 136 | } else { 137 | $ns = ""; 138 | $tag = $name; 139 | } 140 | 141 | if ($this->depth == 1) { 142 | $this->mode = $tag; 143 | } 144 | 145 | if ($this->depth == 3) { 146 | $prop = array("name" => $tag); 147 | $this->current = array("name" => $tag, "ns" => $ns, "status"=> 200); 148 | if ($this->mode == "set") { 149 | $this->current["val"] = ""; // default set val 150 | } 151 | } 152 | 153 | if ($this->depth >= 4) { 154 | $this->current["val"] .= "<$tag"; 155 | foreach ($attr as $key => $val) { 156 | $this->current["val"] .= ' '.$key.'="'.str_replace('"','"', $val).'"'; 157 | } 158 | $this->current["val"] .= ">"; 159 | } 160 | 161 | 162 | 163 | $this->depth++; 164 | } 165 | 166 | /** 167 | * tag end handler 168 | * 169 | * @param resource parser 170 | * @param string tag name 171 | * @return void 172 | * @access private 173 | */ 174 | function _endElement($parser, $name) 175 | { 176 | if (strstr($name, " ")) { 177 | list($ns, $tag) = explode(" ", $name); 178 | if ($ns == "") 179 | $this->success = false; 180 | } else { 181 | $ns = ""; 182 | $tag = $name; 183 | } 184 | 185 | $this->depth--; 186 | 187 | if ($this->depth >= 4) { 188 | $this->current["val"] .= ""; 189 | } 190 | 191 | if ($this->depth == 3) { 192 | if (isset($this->current)) { 193 | $this->props[] = $this->current; 194 | unset($this->current); 195 | } 196 | } 197 | } 198 | 199 | /** 200 | * input data handler 201 | * 202 | * @param resource parser 203 | * @param string data 204 | * @return void 205 | * @access private 206 | */ 207 | function _data($parser, $data) { 208 | if (isset($this->current)) { 209 | $this->current["val"] .= $data; 210 | } 211 | } 212 | } 213 | 214 | ?> -------------------------------------------------------------------------------- /inc/PEAR/Autoloader.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krueschan/phpZoteroWebDAV/1f2236bb362c45727fab1341803b5b6fbb624b5b/inc/PEAR/Autoloader.php -------------------------------------------------------------------------------- /inc/PEAR/Builder.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krueschan/phpZoteroWebDAV/1f2236bb362c45727fab1341803b5b6fbb624b5b/inc/PEAR/Builder.php -------------------------------------------------------------------------------- /inc/PEAR/Command.php: -------------------------------------------------------------------------------- 1 | | 17 | // +----------------------------------------------------------------------+ 18 | // 19 | // $Id: Command.php,v 1.24 2004/05/16 15:43:30 pajoye Exp $ 20 | 21 | 22 | require_once "PEAR.php"; 23 | 24 | /** 25 | * List of commands and what classes they are implemented in. 26 | * @var array command => implementing class 27 | */ 28 | $GLOBALS['_PEAR_Command_commandlist'] = array(); 29 | 30 | /** 31 | * List of shortcuts to common commands. 32 | * @var array shortcut => command 33 | */ 34 | $GLOBALS['_PEAR_Command_shortcuts'] = array(); 35 | 36 | /** 37 | * Array of command objects 38 | * @var array class => object 39 | */ 40 | $GLOBALS['_PEAR_Command_objects'] = array(); 41 | 42 | /** 43 | * Which user interface class is being used. 44 | * @var string class name 45 | */ 46 | $GLOBALS['_PEAR_Command_uiclass'] = 'PEAR_Frontend_CLI'; 47 | 48 | /** 49 | * Instance of $_PEAR_Command_uiclass. 50 | * @var object 51 | */ 52 | $GLOBALS['_PEAR_Command_uiobject'] = null; 53 | 54 | /** 55 | * PEAR command class, a simple factory class for administrative 56 | * commands. 57 | * 58 | * How to implement command classes: 59 | * 60 | * - The class must be called PEAR_Command_Nnn, installed in the 61 | * "PEAR/Common" subdir, with a method called getCommands() that 62 | * returns an array of the commands implemented by the class (see 63 | * PEAR/Command/Install.php for an example). 64 | * 65 | * - The class must implement a run() function that is called with three 66 | * params: 67 | * 68 | * (string) command name 69 | * (array) assoc array with options, freely defined by each 70 | * command, for example: 71 | * array('force' => true) 72 | * (array) list of the other parameters 73 | * 74 | * The run() function returns a PEAR_CommandResponse object. Use 75 | * these methods to get information: 76 | * 77 | * int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) 78 | * *_PARTIAL means that you need to issue at least 79 | * one more command to complete the operation 80 | * (used for example for validation steps). 81 | * 82 | * string getMessage() Returns a message for the user. Remember, 83 | * no HTML or other interface-specific markup. 84 | * 85 | * If something unexpected happens, run() returns a PEAR error. 86 | * 87 | * - DON'T OUTPUT ANYTHING! Return text for output instead. 88 | * 89 | * - DON'T USE HTML! The text you return will be used from both Gtk, 90 | * web and command-line interfaces, so for now, keep everything to 91 | * plain text. 92 | * 93 | * - DON'T USE EXIT OR DIE! Always use pear errors. From static 94 | * classes do PEAR::raiseError(), from other classes do 95 | * $this->raiseError(). 96 | */ 97 | class PEAR_Command 98 | { 99 | // {{{ factory() 100 | 101 | /** 102 | * Get the right object for executing a command. 103 | * 104 | * @param string $command The name of the command 105 | * @param object $config Instance of PEAR_Config object 106 | * 107 | * @return object the command object or a PEAR error 108 | * 109 | * @access public 110 | * @static 111 | */ 112 | function factory($command, &$config) 113 | { 114 | if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 115 | PEAR_Command::registerCommands(); 116 | } 117 | if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { 118 | $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; 119 | } 120 | if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { 121 | return PEAR::raiseError("unknown command `$command'"); 122 | } 123 | $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; 124 | if (!class_exists($class)) { 125 | return PEAR::raiseError("unknown command `$command'"); 126 | } 127 | $ui =& PEAR_Command::getFrontendObject(); 128 | $obj = &new $class($ui, $config); 129 | return $obj; 130 | } 131 | 132 | // }}} 133 | // {{{ & getFrontendObject() 134 | 135 | /** 136 | * Get instance of frontend object. 137 | * 138 | * @return object 139 | * @static 140 | */ 141 | function &getFrontendObject() 142 | { 143 | if (empty($GLOBALS['_PEAR_Command_uiobject'])) { 144 | $GLOBALS['_PEAR_Command_uiobject'] = &new $GLOBALS['_PEAR_Command_uiclass']; 145 | } 146 | return $GLOBALS['_PEAR_Command_uiobject']; 147 | } 148 | 149 | // }}} 150 | // {{{ & setFrontendClass() 151 | 152 | /** 153 | * Load current frontend class. 154 | * 155 | * @param string $uiclass Name of class implementing the frontend 156 | * 157 | * @return object the frontend object, or a PEAR error 158 | * @static 159 | */ 160 | function &setFrontendClass($uiclass) 161 | { 162 | if (is_object($GLOBALS['_PEAR_Command_uiobject']) && 163 | is_a($GLOBALS['_PEAR_Command_uiobject'], $uiclass)) { 164 | return $GLOBALS['_PEAR_Command_uiobject']; 165 | } 166 | if (!class_exists($uiclass)) { 167 | $file = str_replace('_', '/', $uiclass) . '.php'; 168 | if (PEAR_Command::isIncludeable($file)) { 169 | include_once $file; 170 | } 171 | } 172 | if (class_exists($uiclass)) { 173 | $obj = &new $uiclass; 174 | // quick test to see if this class implements a few of the most 175 | // important frontend methods 176 | if (method_exists($obj, 'userConfirm')) { 177 | $GLOBALS['_PEAR_Command_uiobject'] = &$obj; 178 | $GLOBALS['_PEAR_Command_uiclass'] = $uiclass; 179 | return $obj; 180 | } else { 181 | $err = PEAR::raiseError("not a frontend class: $uiclass"); 182 | return $err; 183 | } 184 | } 185 | $err = PEAR::raiseError("no such class: $uiclass"); 186 | return $err; 187 | } 188 | 189 | // }}} 190 | // {{{ setFrontendType() 191 | 192 | // }}} 193 | // {{{ isIncludeable() 194 | 195 | /** 196 | * @param string $path relative or absolute include path 197 | * @return boolean 198 | * @static 199 | */ 200 | function isIncludeable($path) 201 | { 202 | if (file_exists($path) && is_readable($path)) { 203 | return true; 204 | } 205 | $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); 206 | foreach ($ipath as $include) { 207 | $test = realpath($include . DIRECTORY_SEPARATOR . $path); 208 | if (file_exists($test) && is_readable($test)) { 209 | return true; 210 | } 211 | } 212 | return false; 213 | } 214 | 215 | /** 216 | * Set current frontend. 217 | * 218 | * @param string $uitype Name of the frontend type (for example "CLI") 219 | * 220 | * @return object the frontend object, or a PEAR error 221 | * @static 222 | */ 223 | function setFrontendType($uitype) 224 | { 225 | $uiclass = 'PEAR_Frontend_' . $uitype; 226 | return PEAR_Command::setFrontendClass($uiclass); 227 | } 228 | 229 | // }}} 230 | // {{{ registerCommands() 231 | 232 | /** 233 | * Scan through the Command directory looking for classes 234 | * and see what commands they implement. 235 | * 236 | * @param bool (optional) if FALSE (default), the new list of 237 | * commands should replace the current one. If TRUE, 238 | * new entries will be merged with old. 239 | * 240 | * @param string (optional) where (what directory) to look for 241 | * classes, defaults to the Command subdirectory of 242 | * the directory from where this file (__FILE__) is 243 | * included. 244 | * 245 | * @return bool TRUE on success, a PEAR error on failure 246 | * 247 | * @access public 248 | * @static 249 | */ 250 | function registerCommands($merge = false, $dir = null) 251 | { 252 | if ($dir === null) { 253 | $dir = dirname(__FILE__) . '/Command'; 254 | } 255 | $dp = @opendir($dir); 256 | if (empty($dp)) { 257 | return PEAR::raiseError("registerCommands: opendir($dir) failed"); 258 | } 259 | if (!$merge) { 260 | $GLOBALS['_PEAR_Command_commandlist'] = array(); 261 | } 262 | while ($entry = readdir($dp)) { 263 | if ($entry{0} == '.' || substr($entry, -4) != '.php' || $entry == 'Common.php') { 264 | continue; 265 | } 266 | $class = "PEAR_Command_".substr($entry, 0, -4); 267 | $file = "$dir/$entry"; 268 | include_once $file; 269 | // List of commands 270 | if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { 271 | $GLOBALS['_PEAR_Command_objects'][$class] = &new $class($ui, $config); 272 | } 273 | $implements = $GLOBALS['_PEAR_Command_objects'][$class]->getCommands(); 274 | foreach ($implements as $command => $desc) { 275 | $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; 276 | $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc; 277 | } 278 | $shortcuts = $GLOBALS['_PEAR_Command_objects'][$class]->getShortcuts(); 279 | foreach ($shortcuts as $shortcut => $command) { 280 | $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; 281 | } 282 | } 283 | @closedir($dp); 284 | return true; 285 | } 286 | 287 | // }}} 288 | // {{{ getCommands() 289 | 290 | /** 291 | * Get the list of currently supported commands, and what 292 | * classes implement them. 293 | * 294 | * @return array command => implementing class 295 | * 296 | * @access public 297 | * @static 298 | */ 299 | function getCommands() 300 | { 301 | if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 302 | PEAR_Command::registerCommands(); 303 | } 304 | return $GLOBALS['_PEAR_Command_commandlist']; 305 | } 306 | 307 | // }}} 308 | // {{{ getShortcuts() 309 | 310 | /** 311 | * Get the list of command shortcuts. 312 | * 313 | * @return array shortcut => command 314 | * 315 | * @access public 316 | * @static 317 | */ 318 | function getShortcuts() 319 | { 320 | if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { 321 | PEAR_Command::registerCommands(); 322 | } 323 | return $GLOBALS['_PEAR_Command_shortcuts']; 324 | } 325 | 326 | // }}} 327 | // {{{ getGetoptArgs() 328 | 329 | /** 330 | * Compiles arguments for getopt. 331 | * 332 | * @param string $command command to get optstring for 333 | * @param string $short_args (reference) short getopt format 334 | * @param array $long_args (reference) long getopt format 335 | * 336 | * @return void 337 | * 338 | * @access public 339 | * @static 340 | */ 341 | function getGetoptArgs($command, &$short_args, &$long_args) 342 | { 343 | if (empty($GLOBALS['_PEAR_Command_commandlist'])) { 344 | PEAR_Command::registerCommands(); 345 | } 346 | if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { 347 | return null; 348 | } 349 | $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; 350 | $obj = &$GLOBALS['_PEAR_Command_objects'][$class]; 351 | return $obj->getGetoptArgs($command, $short_args, $long_args); 352 | } 353 | 354 | // }}} 355 | // {{{ getDescription() 356 | 357 | /** 358 | * Get description for a command. 359 | * 360 | * @param string $command Name of the command 361 | * 362 | * @return string command description 363 | * 364 | * @access public 365 | * @static 366 | */ 367 | function getDescription($command) 368 | { 369 | if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { 370 | return null; 371 | } 372 | return $GLOBALS['_PEAR_Command_commanddesc'][$command]; 373 | } 374 | 375 | // }}} 376 | // {{{ getHelp() 377 | 378 | /** 379 | * Get help for command. 380 | * 381 | * @param string $command Name of the command to return help for 382 | * 383 | * @access public 384 | * @static 385 | */ 386 | function getHelp($command) 387 | { 388 | $cmds = PEAR_Command::getCommands(); 389 | if (isset($cmds[$command])) { 390 | $class = $cmds[$command]; 391 | return $GLOBALS['_PEAR_Command_objects'][$class]->getHelp($command); 392 | } 393 | return false; 394 | } 395 | // }}} 396 | } 397 | 398 | ?> 399 | -------------------------------------------------------------------------------- /inc/PEAR/Command/Auth.php: -------------------------------------------------------------------------------- 1 | | 17 | // +----------------------------------------------------------------------+ 18 | // 19 | // $Id: Auth.php,v 1.15 2004/01/08 17:33:13 sniper Exp $ 20 | 21 | require_once "PEAR/Command/Common.php"; 22 | require_once "PEAR/Remote.php"; 23 | require_once "PEAR/Config.php"; 24 | 25 | /** 26 | * PEAR commands for managing configuration data. 27 | * 28 | */ 29 | class PEAR_Command_Auth extends PEAR_Command_Common 30 | { 31 | // {{{ properties 32 | 33 | var $commands = array( 34 | 'login' => array( 35 | 'summary' => 'Connects and authenticates to remote server', 36 | 'shortcut' => 'li', 37 | 'function' => 'doLogin', 38 | 'options' => array(), 39 | 'doc' => ' 40 | Log in to the remote server. To use remote functions in the installer 41 | that require any kind of privileges, you need to log in first. The 42 | username and password you enter here will be stored in your per-user 43 | PEAR configuration (~/.pearrc on Unix-like systems). After logging 44 | in, your username and password will be sent along in subsequent 45 | operations on the remote server.', 46 | ), 47 | 'logout' => array( 48 | 'summary' => 'Logs out from the remote server', 49 | 'shortcut' => 'lo', 50 | 'function' => 'doLogout', 51 | 'options' => array(), 52 | 'doc' => ' 53 | Logs out from the remote server. This command does not actually 54 | connect to the remote server, it only deletes the stored username and 55 | password from your user configuration.', 56 | ) 57 | 58 | ); 59 | 60 | // }}} 61 | 62 | // {{{ constructor 63 | 64 | /** 65 | * PEAR_Command_Auth constructor. 66 | * 67 | * @access public 68 | */ 69 | function PEAR_Command_Auth(&$ui, &$config) 70 | { 71 | parent::PEAR_Command_Common($ui, $config); 72 | } 73 | 74 | // }}} 75 | 76 | // {{{ doLogin() 77 | 78 | /** 79 | * Execute the 'login' command. 80 | * 81 | * @param string $command command name 82 | * 83 | * @param array $options option_name => value 84 | * 85 | * @param array $params list of additional parameters 86 | * 87 | * @return bool TRUE on success, FALSE for unknown commands, or 88 | * a PEAR error on failure 89 | * 90 | * @access public 91 | */ 92 | function doLogin($command, $options, $params) 93 | { 94 | $server = $this->config->get('master_server'); 95 | $remote = new PEAR_Remote($this->config); 96 | $username = $this->config->get('username'); 97 | if (empty($username)) { 98 | $username = @$_ENV['USER']; 99 | } 100 | $this->ui->outputData("Logging in to $server.", $command); 101 | 102 | list($username, $password) = $this->ui->userDialog( 103 | $command, 104 | array('Username', 'Password'), 105 | array('text', 'password'), 106 | array($username, '') 107 | ); 108 | $username = trim($username); 109 | $password = trim($password); 110 | 111 | $this->config->set('username', $username); 112 | $this->config->set('password', $password); 113 | 114 | $remote->expectError(401); 115 | $ok = $remote->call('logintest'); 116 | $remote->popExpect(); 117 | if ($ok === true) { 118 | $this->ui->outputData("Logged in.", $command); 119 | $this->config->store(); 120 | } else { 121 | return $this->raiseError("Login failed!"); 122 | } 123 | 124 | } 125 | 126 | // }}} 127 | // {{{ doLogout() 128 | 129 | /** 130 | * Execute the 'logout' command. 131 | * 132 | * @param string $command command name 133 | * 134 | * @param array $options option_name => value 135 | * 136 | * @param array $params list of additional parameters 137 | * 138 | * @return bool TRUE on success, FALSE for unknown commands, or 139 | * a PEAR error on failure 140 | * 141 | * @access public 142 | */ 143 | function doLogout($command, $options, $params) 144 | { 145 | $server = $this->config->get('master_server'); 146 | $this->ui->outputData("Logging out from $server.", $command); 147 | $this->config->remove('username'); 148 | $this->config->remove('password'); 149 | $this->config->store(); 150 | } 151 | 152 | // }}} 153 | } 154 | 155 | ?> -------------------------------------------------------------------------------- /inc/PEAR/Command/Build.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Tomas V.V.Cox | 18 | // | | 19 | // +----------------------------------------------------------------------+ 20 | // 21 | // $Id: Build.php,v 1.9 2004/01/08 17:33:13 sniper Exp $ 22 | 23 | require_once "PEAR/Command/Common.php"; 24 | require_once "PEAR/Builder.php"; 25 | 26 | /** 27 | * PEAR commands for building extensions. 28 | * 29 | */ 30 | class PEAR_Command_Build extends PEAR_Command_Common 31 | { 32 | // {{{ properties 33 | 34 | var $commands = array( 35 | 'build' => array( 36 | 'summary' => 'Build an Extension From C Source', 37 | 'function' => 'doBuild', 38 | 'shortcut' => 'b', 39 | 'options' => array(), 40 | 'doc' => '[package.xml] 41 | Builds one or more extensions contained in a package.' 42 | ), 43 | ); 44 | 45 | // }}} 46 | 47 | // {{{ constructor 48 | 49 | /** 50 | * PEAR_Command_Build constructor. 51 | * 52 | * @access public 53 | */ 54 | function PEAR_Command_Build(&$ui, &$config) 55 | { 56 | parent::PEAR_Command_Common($ui, $config); 57 | } 58 | 59 | // }}} 60 | 61 | // {{{ doBuild() 62 | 63 | function doBuild($command, $options, $params) 64 | { 65 | if (sizeof($params) < 1) { 66 | $params[0] = 'package.xml'; 67 | } 68 | $builder = &new PEAR_Builder($this->ui); 69 | $this->debug = $this->config->get('verbose'); 70 | $err = $builder->build($params[0], array(&$this, 'buildCallback')); 71 | if (PEAR::isError($err)) { 72 | return $err; 73 | } 74 | return true; 75 | } 76 | 77 | // }}} 78 | // {{{ buildCallback() 79 | 80 | function buildCallback($what, $data) 81 | { 82 | if (($what == 'cmdoutput' && $this->debug > 1) || 83 | ($what == 'output' && $this->debug > 0)) { 84 | $this->ui->outputData(rtrim($data), 'build'); 85 | } 86 | } 87 | 88 | // }}} 89 | } 90 | -------------------------------------------------------------------------------- /inc/PEAR/Command/Common.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krueschan/phpZoteroWebDAV/1f2236bb362c45727fab1341803b5b6fbb624b5b/inc/PEAR/Command/Common.php -------------------------------------------------------------------------------- /inc/PEAR/Command/Config.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Tomas V.V.Cox | 18 | // | | 19 | // +----------------------------------------------------------------------+ 20 | // 21 | // $Id: Config.php,v 1.27 2004/06/15 16:48:49 pajoye Exp $ 22 | 23 | require_once "PEAR/Command/Common.php"; 24 | require_once "PEAR/Config.php"; 25 | 26 | /** 27 | * PEAR commands for managing configuration data. 28 | * 29 | */ 30 | class PEAR_Command_Config extends PEAR_Command_Common 31 | { 32 | // {{{ properties 33 | 34 | var $commands = array( 35 | 'config-show' => array( 36 | 'summary' => 'Show All Settings', 37 | 'function' => 'doConfigShow', 38 | 'shortcut' => 'csh', 39 | 'options' => array(), 40 | 'doc' => ' 41 | Displays all configuration values. An optional argument 42 | may be used to tell which configuration layer to display. Valid 43 | configuration layers are "user", "system" and "default". 44 | ', 45 | ), 46 | 'config-get' => array( 47 | 'summary' => 'Show One Setting', 48 | 'function' => 'doConfigGet', 49 | 'shortcut' => 'cg', 50 | 'options' => array(), 51 | 'doc' => ' [layer] 52 | Displays the value of one configuration parameter. The 53 | first argument is the name of the parameter, an optional second argument 54 | may be used to tell which configuration layer to look in. Valid configuration 55 | layers are "user", "system" and "default". If no layer is specified, a value 56 | will be picked from the first layer that defines the parameter, in the order 57 | just specified. 58 | ', 59 | ), 60 | 'config-set' => array( 61 | 'summary' => 'Change Setting', 62 | 'function' => 'doConfigSet', 63 | 'shortcut' => 'cs', 64 | 'options' => array(), 65 | 'doc' => ' [layer] 66 | Sets the value of one configuration parameter. The first argument is 67 | the name of the parameter, the second argument is the new value. Some 68 | parameters are subject to validation, and the command will fail with 69 | an error message if the new value does not make sense. An optional 70 | third argument may be used to specify in which layer to set the 71 | configuration parameter. The default layer is "user". 72 | ', 73 | ), 74 | 'config-help' => array( 75 | 'summary' => 'Show Information About Setting', 76 | 'function' => 'doConfigHelp', 77 | 'shortcut' => 'ch', 78 | 'options' => array(), 79 | 'doc' => '[parameter] 80 | Displays help for a configuration parameter. Without arguments it 81 | displays help for all configuration parameters. 82 | ', 83 | ), 84 | ); 85 | 86 | // }}} 87 | // {{{ constructor 88 | 89 | /** 90 | * PEAR_Command_Config constructor. 91 | * 92 | * @access public 93 | */ 94 | function PEAR_Command_Config(&$ui, &$config) 95 | { 96 | parent::PEAR_Command_Common($ui, $config); 97 | } 98 | 99 | // }}} 100 | 101 | // {{{ doConfigShow() 102 | 103 | function doConfigShow($command, $options, $params) 104 | { 105 | // $params[0] -> the layer 106 | if ($error = $this->_checkLayer(@$params[0])) { 107 | return $this->raiseError($error); 108 | } 109 | $keys = $this->config->getKeys(); 110 | sort($keys); 111 | $data = array('caption' => 'Configuration:'); 112 | foreach ($keys as $key) { 113 | $type = $this->config->getType($key); 114 | $value = $this->config->get($key, @$params[0]); 115 | if ($type == 'password' && $value) { 116 | $value = '********'; 117 | } 118 | if ($value === false) { 119 | $value = 'false'; 120 | } elseif ($value === true) { 121 | $value = 'true'; 122 | } 123 | $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); 124 | } 125 | $this->ui->outputData($data, $command); 126 | return true; 127 | } 128 | 129 | // }}} 130 | // {{{ doConfigGet() 131 | 132 | function doConfigGet($command, $options, $params) 133 | { 134 | // $params[0] -> the parameter 135 | // $params[1] -> the layer 136 | if ($error = $this->_checkLayer(@$params[1])) { 137 | return $this->raiseError($error); 138 | } 139 | if (sizeof($params) < 1 || sizeof($params) > 2) { 140 | return $this->raiseError("config-get expects 1 or 2 parameters"); 141 | } elseif (sizeof($params) == 1) { 142 | $this->ui->outputData($this->config->get($params[0]), $command); 143 | } else { 144 | $data = $this->config->get($params[0], $params[1]); 145 | $this->ui->outputData($data, $command); 146 | } 147 | return true; 148 | } 149 | 150 | // }}} 151 | // {{{ doConfigSet() 152 | 153 | function doConfigSet($command, $options, $params) 154 | { 155 | // $param[0] -> a parameter to set 156 | // $param[1] -> the value for the parameter 157 | // $param[2] -> the layer 158 | $failmsg = ''; 159 | if (sizeof($params) < 2 || sizeof($params) > 3) { 160 | $failmsg .= "config-set expects 2 or 3 parameters"; 161 | return PEAR::raiseError($failmsg); 162 | } 163 | if ($error = $this->_checkLayer(@$params[2])) { 164 | $failmsg .= $error; 165 | return PEAR::raiseError($failmsg); 166 | } 167 | if (!call_user_func_array(array(&$this->config, 'set'), $params)) 168 | { 169 | $failmsg = "config-set (" . implode(", ", $params) . ") failed"; 170 | } else { 171 | $this->config->store(); 172 | } 173 | if ($failmsg) { 174 | return $this->raiseError($failmsg); 175 | } 176 | return true; 177 | } 178 | 179 | // }}} 180 | // {{{ doConfigHelp() 181 | 182 | function doConfigHelp($command, $options, $params) 183 | { 184 | if (empty($params)) { 185 | $params = $this->config->getKeys(); 186 | } 187 | $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); 188 | $data['headline'] = array('Name', 'Type', 'Description'); 189 | $data['border'] = true; 190 | foreach ($params as $name) { 191 | $type = $this->config->getType($name); 192 | $docs = $this->config->getDocs($name); 193 | if ($type == 'set') { 194 | $docs = rtrim($docs) . "\nValid set: " . 195 | implode(' ', $this->config->getSetValues($name)); 196 | } 197 | $data['data'][] = array($name, $type, $docs); 198 | } 199 | $this->ui->outputData($data, $command); 200 | } 201 | 202 | // }}} 203 | // {{{ _checkLayer() 204 | 205 | /** 206 | * Checks if a layer is defined or not 207 | * 208 | * @param string $layer The layer to search for 209 | * @return mixed False on no error or the error message 210 | */ 211 | function _checkLayer($layer = null) 212 | { 213 | if (!empty($layer) && $layer != 'default') { 214 | $layers = $this->config->getLayers(); 215 | if (!in_array($layer, $layers)) { 216 | return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; 217 | } 218 | } 219 | return false; 220 | } 221 | 222 | // }}} 223 | } 224 | 225 | ?> 226 | -------------------------------------------------------------------------------- /inc/PEAR/Command/Install.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krueschan/phpZoteroWebDAV/1f2236bb362c45727fab1341803b5b6fbb624b5b/inc/PEAR/Command/Install.php -------------------------------------------------------------------------------- /inc/PEAR/Command/Mirror.php: -------------------------------------------------------------------------------- 1 | | 17 | // | | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: Mirror.php,v 1.5 2004/03/18 12:23:57 mj Exp $ 21 | 22 | require_once "PEAR/Command/Common.php"; 23 | require_once "PEAR/Command.php"; 24 | require_once "PEAR/Remote.php"; 25 | require_once "PEAR.php"; 26 | 27 | /** 28 | * PEAR commands for providing file mirrors 29 | * 30 | */ 31 | class PEAR_Command_Mirror extends PEAR_Command_Common 32 | { 33 | // {{{ properties 34 | 35 | var $commands = array( 36 | 'download-all' => array( 37 | 'summary' => 'Downloads each available package from master_server', 38 | 'function' => 'doDownloadAll', 39 | 'shortcut' => 'da', 40 | 'options' => array(), 41 | 'doc' => ' 42 | Requests a list of available packages from the package server 43 | (master_server) and downloads them to current working directory' 44 | ), 45 | ); 46 | 47 | // }}} 48 | 49 | // {{{ constructor 50 | 51 | /** 52 | * PEAR_Command_Mirror constructor. 53 | * 54 | * @access public 55 | * @param object PEAR_Frontend a reference to an frontend 56 | * @param object PEAR_Config a reference to the configuration data 57 | */ 58 | function PEAR_Command_Mirror(&$ui, &$config) 59 | { 60 | parent::PEAR_Command_Common($ui, $config); 61 | } 62 | 63 | // }}} 64 | 65 | // {{{ doDownloadAll() 66 | /** 67 | * retrieves a list of avaible Packages from master server 68 | * and downloads them 69 | * 70 | * @access public 71 | * @param string $command the command 72 | * @param array $options the command options before the command 73 | * @param array $params the stuff after the command name 74 | * @return bool true if succesful 75 | * @throw PEAR_Error 76 | */ 77 | function doDownloadAll($command, $options, $params) 78 | { 79 | $this->config->set("php_dir", "."); 80 | $remote = &new PEAR_Remote($this->config); 81 | $remoteInfo = $remote->call("package.listAll"); 82 | if (PEAR::isError($remoteInfo)) { 83 | return $remoteInfo; 84 | } 85 | $cmd = &PEAR_Command::factory("download", $this->config); 86 | if (PEAR::isError($cmd)) { 87 | return $cmd; 88 | } 89 | foreach ($remoteInfo as $pkgn => $pkg) { 90 | /** 91 | * Error handling not neccesary, because already done by 92 | * the download command 93 | */ 94 | $cmd->run("download", array(), array($pkgn)); 95 | } 96 | 97 | return true; 98 | } 99 | 100 | // }}} 101 | } 102 | -------------------------------------------------------------------------------- /inc/PEAR/Command/Registry.php: -------------------------------------------------------------------------------- 1 | | 17 | // | | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: Registry.php,v 1.36 2004/01/08 17:33:13 sniper Exp $ 21 | 22 | require_once 'PEAR/Command/Common.php'; 23 | require_once 'PEAR/Registry.php'; 24 | require_once 'PEAR/Config.php'; 25 | 26 | class PEAR_Command_Registry extends PEAR_Command_Common 27 | { 28 | // {{{ properties 29 | 30 | var $commands = array( 31 | 'list' => array( 32 | 'summary' => 'List Installed Packages', 33 | 'function' => 'doList', 34 | 'shortcut' => 'l', 35 | 'options' => array(), 36 | 'doc' => '[package] 37 | If invoked without parameters, this command lists the PEAR packages 38 | installed in your php_dir ({config php_dir)). With a parameter, it 39 | lists the files in that package. 40 | ', 41 | ), 42 | 'shell-test' => array( 43 | 'summary' => 'Shell Script Test', 44 | 'function' => 'doShellTest', 45 | 'shortcut' => 'st', 46 | 'options' => array(), 47 | 'doc' => ' [[relation] version] 48 | Tests if a package is installed in the system. Will exit(1) if it is not. 49 | The version comparison operator. One of: 50 | <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne 51 | The version to compare with 52 | '), 53 | 'info' => array( 54 | 'summary' => 'Display information about a package', 55 | 'function' => 'doInfo', 56 | 'shortcut' => 'in', 57 | 'options' => array(), 58 | 'doc' => ' 59 | Displays information about a package. The package argument may be a 60 | local package file, an URL to a package file, or the name of an 61 | installed package.' 62 | ) 63 | ); 64 | 65 | // }}} 66 | // {{{ constructor 67 | 68 | /** 69 | * PEAR_Command_Registry constructor. 70 | * 71 | * @access public 72 | */ 73 | function PEAR_Command_Registry(&$ui, &$config) 74 | { 75 | parent::PEAR_Command_Common($ui, $config); 76 | } 77 | 78 | // }}} 79 | 80 | // {{{ doList() 81 | 82 | function _sortinfo($a, $b) 83 | { 84 | return strcmp($a['package'], $b['package']); 85 | } 86 | 87 | function doList($command, $options, $params) 88 | { 89 | $reg = new PEAR_Registry($this->config->get('php_dir')); 90 | if (sizeof($params) == 0) { 91 | $installed = $reg->packageInfo(); 92 | usort($installed, array(&$this, '_sortinfo')); 93 | $i = $j = 0; 94 | $data = array( 95 | 'caption' => 'Installed packages:', 96 | 'border' => true, 97 | 'headline' => array('Package', 'Version', 'State') 98 | ); 99 | foreach ($installed as $package) { 100 | $data['data'][] = array($package['package'], 101 | $package['version'], 102 | @$package['release_state']); 103 | } 104 | if (count($installed)==0) { 105 | $data = '(no packages installed)'; 106 | } 107 | $this->ui->outputData($data, $command); 108 | } else { 109 | if (file_exists($params[0]) && !is_dir($params[0])) { 110 | include_once "PEAR/Common.php"; 111 | $obj = &new PEAR_Common; 112 | $info = $obj->infoFromAny($params[0]); 113 | $headings = array('Package File', 'Install Path'); 114 | $installed = false; 115 | } else { 116 | $info = $reg->packageInfo($params[0]); 117 | $headings = array('Type', 'Install Path'); 118 | $installed = true; 119 | } 120 | if (PEAR::isError($info)) { 121 | return $this->raiseError($info); 122 | } 123 | if ($info === null) { 124 | return $this->raiseError("`$params[0]' not installed"); 125 | } 126 | $list = $info['filelist']; 127 | if ($installed) { 128 | $caption = 'Installed Files For ' . $params[0]; 129 | } else { 130 | $caption = 'Contents of ' . basename($params[0]); 131 | } 132 | $data = array( 133 | 'caption' => $caption, 134 | 'border' => true, 135 | 'headline' => $headings); 136 | foreach ($list as $file => $att) { 137 | if ($installed) { 138 | if (empty($att['installed_as'])) { 139 | continue; 140 | } 141 | $data['data'][] = array($att['role'], $att['installed_as']); 142 | } else { 143 | if (isset($att['baseinstalldir'])) { 144 | $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . 145 | $file; 146 | } else { 147 | $dest = $file; 148 | } 149 | switch ($att['role']) { 150 | case 'test': 151 | case 'data': 152 | if ($installed) { 153 | break 2; 154 | } 155 | $dest = '-- will not be installed --'; 156 | break; 157 | case 'doc': 158 | $dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR . 159 | $dest; 160 | break; 161 | case 'php': 162 | default: 163 | $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . 164 | $dest; 165 | } 166 | $dest = preg_replace('!/+!', '/', $dest); 167 | $file = preg_replace('!/+!', '/', $file); 168 | $data['data'][] = array($file, $dest); 169 | } 170 | } 171 | $this->ui->outputData($data, $command); 172 | 173 | 174 | } 175 | return true; 176 | } 177 | 178 | // }}} 179 | // {{{ doShellTest() 180 | 181 | function doShellTest($command, $options, $params) 182 | { 183 | $this->pushErrorHandling(PEAR_ERROR_RETURN); 184 | $reg = &new PEAR_Registry($this->config->get('php_dir')); 185 | // "pear shell-test Foo" 186 | if (sizeof($params) == 1) { 187 | if (!$reg->packageExists($params[0])) { 188 | exit(1); 189 | } 190 | // "pear shell-test Foo 1.0" 191 | } elseif (sizeof($params) == 2) { 192 | $v = $reg->packageInfo($params[0], 'version'); 193 | if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { 194 | exit(1); 195 | } 196 | // "pear shell-test Foo ge 1.0" 197 | } elseif (sizeof($params) == 3) { 198 | $v = $reg->packageInfo($params[0], 'version'); 199 | if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { 200 | exit(1); 201 | } 202 | } else { 203 | $this->popErrorHandling(); 204 | $this->raiseError("$command: expects 1 to 3 parameters"); 205 | exit(1); 206 | } 207 | } 208 | 209 | // }}} 210 | // {{{ doInfo 211 | 212 | function doInfo($command, $options, $params) 213 | { 214 | // $params[0] The package for showing info 215 | if (sizeof($params) != 1) { 216 | return $this->raiseError("This command only accepts one param: ". 217 | "the package you want information"); 218 | } 219 | if (@is_file($params[0])) { 220 | $obj = &new PEAR_Common(); 221 | $info = $obj->infoFromAny($params[0]); 222 | } else { 223 | $reg = &new PEAR_Registry($this->config->get('php_dir')); 224 | $info = $reg->packageInfo($params[0]); 225 | } 226 | if (PEAR::isError($info)) { 227 | return $info; 228 | } 229 | if (empty($info)) { 230 | $this->raiseError("Nothing found for `$params[0]'"); 231 | return; 232 | } 233 | unset($info['filelist']); 234 | unset($info['changelog']); 235 | $keys = array_keys($info); 236 | $longtext = array('description', 'summary'); 237 | foreach ($keys as $key) { 238 | if (is_array($info[$key])) { 239 | switch ($key) { 240 | case 'maintainers': { 241 | $i = 0; 242 | $mstr = ''; 243 | foreach ($info[$key] as $m) { 244 | if ($i++ > 0) { 245 | $mstr .= "\n"; 246 | } 247 | $mstr .= $m['name'] . " <"; 248 | if (isset($m['email'])) { 249 | $mstr .= $m['email']; 250 | } else { 251 | $mstr .= $m['handle'] . '@php.net'; 252 | } 253 | $mstr .= "> ($m[role])"; 254 | } 255 | $info[$key] = $mstr; 256 | break; 257 | } 258 | case 'release_deps': { 259 | $i = 0; 260 | $dstr = ''; 261 | foreach ($info[$key] as $d) { 262 | if (isset($this->_deps_rel_trans[$d['rel']])) { 263 | $rel = $this->_deps_rel_trans[$d['rel']]; 264 | } else { 265 | $rel = $d['rel']; 266 | } 267 | if (isset($this->_deps_type_trans[$d['type']])) { 268 | $type = ucfirst($this->_deps_type_trans[$d['type']]); 269 | } else { 270 | $type = $d['type']; 271 | } 272 | if (isset($d['name'])) { 273 | $name = $d['name'] . ' '; 274 | } else { 275 | $name = ''; 276 | } 277 | if (isset($d['version'])) { 278 | $version = $d['version'] . ' '; 279 | } else { 280 | $version = ''; 281 | } 282 | $dstr .= "$type $name$rel $version\n"; 283 | } 284 | $info[$key] = $dstr; 285 | break; 286 | } 287 | case 'provides' : { 288 | $debug = $this->config->get('verbose'); 289 | if ($debug < 2) { 290 | $pstr = 'Classes: '; 291 | } else { 292 | $pstr = ''; 293 | } 294 | $i = 0; 295 | foreach ($info[$key] as $p) { 296 | if ($debug < 2 && $p['type'] != "class") { 297 | continue; 298 | } 299 | // Only print classes when verbosity mode is < 2 300 | if ($debug < 2) { 301 | if ($i++ > 0) { 302 | $pstr .= ", "; 303 | } 304 | $pstr .= $p['name']; 305 | } else { 306 | if ($i++ > 0) { 307 | $pstr .= "\n"; 308 | } 309 | $pstr .= ucfirst($p['type']) . " " . $p['name']; 310 | if (isset($p['explicit']) && $p['explicit'] == 1) { 311 | $pstr .= " (explicit)"; 312 | } 313 | } 314 | } 315 | $info[$key] = $pstr; 316 | break; 317 | } 318 | default: { 319 | $info[$key] = implode(", ", $info[$key]); 320 | break; 321 | } 322 | } 323 | } 324 | if ($key == '_lastmodified') { 325 | $hdate = date('Y-m-d', $info[$key]); 326 | unset($info[$key]); 327 | $info['Last Modified'] = $hdate; 328 | } else { 329 | $info[$key] = trim($info[$key]); 330 | if (in_array($key, $longtext)) { 331 | $info[$key] = preg_replace('/ +/', ' ', $info[$key]); 332 | } 333 | } 334 | } 335 | $caption = 'About ' . $info['package'] . '-' . $info['version']; 336 | $data = array( 337 | 'caption' => $caption, 338 | 'border' => true); 339 | foreach ($info as $key => $value) { 340 | $key = ucwords(trim(str_replace('_', ' ', $key))); 341 | $data['data'][] = array($key, $value); 342 | } 343 | $data['raw'] = $info; 344 | 345 | $this->ui->outputData($data, 'package-info'); 346 | } 347 | 348 | // }}} 349 | } 350 | 351 | ?> 352 | -------------------------------------------------------------------------------- /inc/PEAR/Command/Remote.php: -------------------------------------------------------------------------------- 1 | | 17 | // | | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: Remote.php,v 1.39 2004/04/03 15:56:00 cellog Exp $ 21 | 22 | require_once 'PEAR/Command/Common.php'; 23 | require_once 'PEAR/Common.php'; 24 | require_once 'PEAR/Remote.php'; 25 | require_once 'PEAR/Registry.php'; 26 | 27 | class PEAR_Command_Remote extends PEAR_Command_Common 28 | { 29 | // {{{ command definitions 30 | 31 | var $commands = array( 32 | 'remote-info' => array( 33 | 'summary' => 'Information About Remote Packages', 34 | 'function' => 'doRemoteInfo', 35 | 'shortcut' => 'ri', 36 | 'options' => array(), 37 | 'doc' => ' 38 | Get details on a package from the server.', 39 | ), 40 | 'list-upgrades' => array( 41 | 'summary' => 'List Available Upgrades', 42 | 'function' => 'doListUpgrades', 43 | 'shortcut' => 'lu', 44 | 'options' => array(), 45 | 'doc' => ' 46 | List releases on the server of packages you have installed where 47 | a newer version is available with the same release state (stable etc.).' 48 | ), 49 | 'remote-list' => array( 50 | 'summary' => 'List Remote Packages', 51 | 'function' => 'doRemoteList', 52 | 'shortcut' => 'rl', 53 | 'options' => array(), 54 | 'doc' => ' 55 | Lists the packages available on the configured server along with the 56 | latest stable release of each package.', 57 | ), 58 | 'search' => array( 59 | 'summary' => 'Search remote package database', 60 | 'function' => 'doSearch', 61 | 'shortcut' => 'sp', 62 | 'options' => array(), 63 | 'doc' => ' 64 | Lists all packages which match the search parameters (first param 65 | is package name, second package info)', 66 | ), 67 | 'list-all' => array( 68 | 'summary' => 'List All Packages', 69 | 'function' => 'doListAll', 70 | 'shortcut' => 'la', 71 | 'options' => array(), 72 | 'doc' => ' 73 | Lists the packages available on the configured server along with the 74 | latest stable release of each package.', 75 | ), 76 | 'download' => array( 77 | 'summary' => 'Download Package', 78 | 'function' => 'doDownload', 79 | 'shortcut' => 'd', 80 | 'options' => array( 81 | 'nocompress' => array( 82 | 'shortopt' => 'Z', 83 | 'doc' => 'download an uncompressed (.tar) file', 84 | ), 85 | ), 86 | 'doc' => '{package|package-version} 87 | Download a package tarball. The file will be named as suggested by the 88 | server, for example if you download the DB package and the latest stable 89 | version of DB is 1.2, the downloaded file will be DB-1.2.tgz.', 90 | ), 91 | 'clear-cache' => array( 92 | 'summary' => 'Clear XML-RPC Cache', 93 | 'function' => 'doClearCache', 94 | 'shortcut' => 'cc', 95 | 'options' => array(), 96 | 'doc' => ' 97 | Clear the XML-RPC cache. See also the cache_ttl configuration 98 | parameter. 99 | ', 100 | ), 101 | ); 102 | 103 | // }}} 104 | // {{{ constructor 105 | 106 | /** 107 | * PEAR_Command_Remote constructor. 108 | * 109 | * @access public 110 | */ 111 | function PEAR_Command_Remote(&$ui, &$config) 112 | { 113 | parent::PEAR_Command_Common($ui, $config); 114 | } 115 | 116 | // }}} 117 | 118 | // {{{ doRemoteInfo() 119 | 120 | function doRemoteInfo($command, $options, $params) 121 | { 122 | if (sizeof($params) != 1) { 123 | return $this->raiseError("$command expects one param: the remote package name"); 124 | } 125 | $r = new PEAR_Remote($this->config); 126 | $info = $r->call('package.info', $params[0]); 127 | if (PEAR::isError($info)) { 128 | return $this->raiseError($info); 129 | } 130 | 131 | $reg = new PEAR_Registry($this->config->get('php_dir')); 132 | $installed = $reg->packageInfo($info['name']); 133 | $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; 134 | 135 | $this->ui->outputData($info, $command); 136 | 137 | return true; 138 | } 139 | 140 | // }}} 141 | // {{{ doRemoteList() 142 | 143 | function doRemoteList($command, $options, $params) 144 | { 145 | $r = new PEAR_Remote($this->config); 146 | $list_options = false; 147 | if ($this->config->get('preferred_state') == 'stable') 148 | $list_options = true; 149 | $available = $r->call('package.listAll', $list_options); 150 | if (PEAR::isError($available)) { 151 | return $this->raiseError($available); 152 | } 153 | $i = $j = 0; 154 | $data = array( 155 | 'caption' => 'Available packages:', 156 | 'border' => true, 157 | 'headline' => array('Package', 'Version'), 158 | ); 159 | foreach ($available as $name => $info) { 160 | $data['data'][] = array($name, isset($info['stable']) ? $info['stable'] : '-n/a-'); 161 | } 162 | if (count($available)==0) { 163 | $data = '(no packages installed yet)'; 164 | } 165 | $this->ui->outputData($data, $command); 166 | return true; 167 | } 168 | 169 | // }}} 170 | // {{{ doListAll() 171 | 172 | function doListAll($command, $options, $params) 173 | { 174 | $r = new PEAR_Remote($this->config); 175 | $reg = new PEAR_Registry($this->config->get('php_dir')); 176 | $list_options = false; 177 | if ($this->config->get('preferred_state') == 'stable') 178 | $list_options = true; 179 | $available = $r->call('package.listAll', $list_options); 180 | if (PEAR::isError($available)) { 181 | return $this->raiseError($available); 182 | } 183 | if (!is_array($available)) { 184 | return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "'.$available.'")'); 185 | } 186 | $data = array( 187 | 'caption' => 'All packages:', 188 | 'border' => true, 189 | 'headline' => array('Package', 'Latest', 'Local'), 190 | ); 191 | $local_pkgs = $reg->listPackages(); 192 | 193 | foreach ($available as $name => $info) { 194 | $installed = $reg->packageInfo($name); 195 | $desc = $info['summary']; 196 | if (isset($params[$name])) 197 | $desc .= "\n\n".$info['description']; 198 | 199 | if (isset($options['mode'])) 200 | { 201 | if ($options['mode'] == 'installed' && !isset($installed['version'])) 202 | continue; 203 | if ($options['mode'] == 'notinstalled' && isset($installed['version'])) 204 | continue; 205 | if ($options['mode'] == 'upgrades' 206 | && (!isset($installed['version']) || $installed['version'] == $info['stable'])) 207 | { 208 | continue; 209 | } 210 | } 211 | $pos = array_search(strtolower($name), $local_pkgs); 212 | if ($pos !== false) { 213 | unset($local_pkgs[$pos]); 214 | } 215 | 216 | $data['data'][$info['category']][] = array( 217 | $name, 218 | @$info['stable'], 219 | @$installed['version'], 220 | @$desc, 221 | @$info['deps'], 222 | ); 223 | } 224 | 225 | foreach ($local_pkgs as $name) { 226 | $info = $reg->packageInfo($name); 227 | $data['data']['Local'][] = array( 228 | $info['package'], 229 | '', 230 | $info['version'], 231 | $info['summary'], 232 | @$info['release_deps'] 233 | ); 234 | } 235 | 236 | $this->ui->outputData($data, $command); 237 | return true; 238 | } 239 | 240 | // }}} 241 | // {{{ doSearch() 242 | 243 | function doSearch($command, $options, $params) 244 | { 245 | if ((!isset($params[0]) || empty($params[0])) 246 | && (!isset($params[1]) || empty($params[1]))) 247 | { 248 | return $this->raiseError('no valid search string supplied'); 249 | }; 250 | 251 | $r = new PEAR_Remote($this->config); 252 | $reg = new PEAR_Registry($this->config->get('php_dir')); 253 | $available = $r->call('package.listAll', true, false); 254 | if (PEAR::isError($available)) { 255 | return $this->raiseError($available); 256 | } 257 | $data = array( 258 | 'caption' => 'Matched packages:', 259 | 'border' => true, 260 | 'headline' => array('Package', 'Stable/(Latest)', 'Local'), 261 | ); 262 | 263 | foreach ($available as $name => $info) { 264 | $found = (!empty($params[0]) && stristr($name, $params[0]) !== false); 265 | if (!$found && !(isset($params[1]) && !empty($params[1]) 266 | && (stristr($info['summary'], $params[1]) !== false 267 | || stristr($info['description'], $params[1]) !== false))) 268 | { 269 | continue; 270 | }; 271 | 272 | $installed = $reg->packageInfo($name); 273 | $desc = $info['summary']; 274 | if (isset($params[$name])) 275 | $desc .= "\n\n".$info['description']; 276 | 277 | $unstable = ''; 278 | if ($info['unstable']) { 279 | $unstable = '/(' . $info['unstable'] . $info['state'] . ')'; 280 | } 281 | if (!isset($info['stable']) || !$info['stable']) { 282 | $info['stable'] = 'none'; 283 | } 284 | $data['data'][$info['category']][] = array( 285 | $name, 286 | $info['stable'] . $unstable, 287 | $installed['version'], 288 | $desc, 289 | ); 290 | } 291 | if (!isset($data['data'])) { 292 | return $this->raiseError('no packages found'); 293 | } 294 | $this->ui->outputData($data, $command); 295 | return true; 296 | } 297 | 298 | // }}} 299 | // {{{ doDownload() 300 | 301 | function doDownload($command, $options, $params) 302 | { 303 | //$params[0] -> The package to download 304 | if (count($params) != 1) { 305 | return PEAR::raiseError("download expects one argument: the package to download"); 306 | } 307 | $server = $this->config->get('master_server'); 308 | if (!ereg('^http://', $params[0])) { 309 | $getoption = isset($options['nocompress'])&&$options['nocompress']==1?'?uncompress=on':''; 310 | $pkgfile = "http://$server/get/$params[0]".$getoption; 311 | } else { 312 | $pkgfile = $params[0]; 313 | } 314 | $this->bytes_downloaded = 0; 315 | $saved = PEAR_Common::downloadHttp($pkgfile, $this->ui, '.', 316 | array(&$this, 'downloadCallback')); 317 | if (PEAR::isError($saved)) { 318 | return $this->raiseError($saved); 319 | } 320 | $fname = basename($saved); 321 | $this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command); 322 | return true; 323 | } 324 | 325 | function downloadCallback($msg, $params = null) 326 | { 327 | if ($msg == 'done') { 328 | $this->bytes_downloaded = $params; 329 | } 330 | } 331 | 332 | // }}} 333 | // {{{ doListUpgrades() 334 | 335 | function doListUpgrades($command, $options, $params) 336 | { 337 | include_once "PEAR/Registry.php"; 338 | $remote = new PEAR_Remote($this->config); 339 | if (empty($params[0])) { 340 | $state = $this->config->get('preferred_state'); 341 | } else { 342 | $state = $params[0]; 343 | } 344 | $caption = 'Available Upgrades'; 345 | if (empty($state) || $state == 'any') { 346 | $latest = $remote->call("package.listLatestReleases"); 347 | } else { 348 | $latest = $remote->call("package.listLatestReleases", $state); 349 | $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; 350 | } 351 | $caption .= ':'; 352 | if (PEAR::isError($latest)) { 353 | return $latest; 354 | } 355 | $reg = new PEAR_Registry($this->config->get('php_dir')); 356 | $inst = array_flip($reg->listPackages()); 357 | $data = array( 358 | 'caption' => $caption, 359 | 'border' => 1, 360 | 'headline' => array('Package', 'Local', 'Remote', 'Size'), 361 | ); 362 | foreach ((array)$latest as $pkg => $info) { 363 | $package = strtolower($pkg); 364 | if (!isset($inst[$package])) { 365 | // skip packages we don't have installed 366 | continue; 367 | } 368 | extract($info); 369 | $pkginfo = $reg->packageInfo($package); 370 | $inst_version = $pkginfo['version']; 371 | $inst_state = $pkginfo['release_state']; 372 | if (version_compare("$version", "$inst_version", "le")) { 373 | // installed version is up-to-date 374 | continue; 375 | } 376 | if ($filesize >= 20480) { 377 | $filesize += 1024 - ($filesize % 1024); 378 | $fs = sprintf("%dkB", $filesize / 1024); 379 | } elseif ($filesize > 0) { 380 | $filesize += 103 - ($filesize % 103); 381 | $fs = sprintf("%.1fkB", $filesize / 1024.0); 382 | } else { 383 | $fs = " -"; // XXX center instead 384 | } 385 | $data['data'][] = array($pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); 386 | } 387 | if (empty($data['data'])) { 388 | $this->ui->outputData('No upgrades available'); 389 | } else { 390 | $this->ui->outputData($data, $command); 391 | } 392 | return true; 393 | } 394 | 395 | // }}} 396 | // {{{ doClearCache() 397 | 398 | function doClearCache($command, $options, $params) 399 | { 400 | $cache_dir = $this->config->get('cache_dir'); 401 | $verbose = $this->config->get('verbose'); 402 | $output = ''; 403 | if (!($dp = @opendir($cache_dir))) { 404 | return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); 405 | } 406 | if ($verbose >= 1) { 407 | $output .= "reading directory $cache_dir\n"; 408 | } 409 | $num = 0; 410 | while ($ent = readdir($dp)) { 411 | if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent)) { 412 | $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; 413 | $ok = @unlink($path); 414 | if ($ok) { 415 | if ($verbose >= 2) { 416 | $output .= "deleted $path\n"; 417 | } 418 | $num++; 419 | } elseif ($verbose >= 1) { 420 | $output .= "failed to delete $path\n"; 421 | } 422 | } 423 | } 424 | closedir($dp); 425 | if ($verbose >= 1) { 426 | $output .= "$num cache entries cleared\n"; 427 | } 428 | $this->ui->outputData(rtrim($output), $command); 429 | return $num; 430 | } 431 | 432 | // }}} 433 | } 434 | 435 | ?> 436 | -------------------------------------------------------------------------------- /inc/PEAR/Dependency.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Stig Bakken | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: Dependency.php,v 1.36.4.1 2004/12/27 07:04:19 cellog Exp $ 21 | 22 | require_once "PEAR.php"; 23 | 24 | define('PEAR_DEPENDENCY_MISSING', -1); 25 | define('PEAR_DEPENDENCY_CONFLICT', -2); 26 | define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3); 27 | define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4); 28 | define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5); 29 | define('PEAR_DEPENDENCY_MISSING_OPTIONAL', -6); 30 | define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL', -7); 31 | define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL', -8); 32 | define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL', -9); 33 | 34 | /** 35 | * Dependency check for PEAR packages 36 | * 37 | * The class is based on the dependency RFC that can be found at 38 | * http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1 39 | * 40 | * @author Tomas V.V.Vox 41 | * @author Stig Bakken 42 | */ 43 | class PEAR_Dependency 44 | { 45 | // {{{ constructor 46 | /** 47 | * Constructor 48 | * 49 | * @access public 50 | * @param object Registry object 51 | * @return void 52 | */ 53 | function PEAR_Dependency(&$registry) 54 | { 55 | $this->registry = &$registry; 56 | } 57 | 58 | // }}} 59 | // {{{ callCheckMethod() 60 | 61 | /** 62 | * This method maps the XML dependency definition to the 63 | * corresponding one from PEAR_Dependency 64 | * 65 | *
 66 |     * $opts => Array
 67 |     *    (
 68 |     *        [type] => pkg
 69 |     *        [rel] => ge
 70 |     *        [version] => 3.4
 71 |     *        [name] => HTML_Common
 72 |     *        [optional] => false
 73 |     *    )
 74 |     * 
75 | * 76 | * @param string Error message 77 | * @param array Options 78 | * @return boolean 79 | */ 80 | function callCheckMethod(&$errmsg, $opts) 81 | { 82 | $rel = isset($opts['rel']) ? $opts['rel'] : 'has'; 83 | $req = isset($opts['version']) ? $opts['version'] : null; 84 | $name = isset($opts['name']) ? $opts['name'] : null; 85 | $opt = (isset($opts['optional']) && $opts['optional'] == 'yes') ? 86 | $opts['optional'] : null; 87 | $errmsg = ''; 88 | switch ($opts['type']) { 89 | case 'pkg': 90 | return $this->checkPackage($errmsg, $name, $req, $rel, $opt); 91 | break; 92 | case 'ext': 93 | return $this->checkExtension($errmsg, $name, $req, $rel, $opt); 94 | break; 95 | case 'php': 96 | return $this->checkPHP($errmsg, $req, $rel); 97 | break; 98 | case 'prog': 99 | return $this->checkProgram($errmsg, $name); 100 | break; 101 | case 'os': 102 | return $this->checkOS($errmsg, $name); 103 | break; 104 | case 'sapi': 105 | return $this->checkSAPI($errmsg, $name); 106 | break; 107 | case 'zend': 108 | return $this->checkZend($errmsg, $name); 109 | break; 110 | default: 111 | return "'{$opts['type']}' dependency type not supported"; 112 | } 113 | } 114 | 115 | // }}} 116 | // {{{ checkPackage() 117 | 118 | /** 119 | * Package dependencies check method 120 | * 121 | * @param string $errmsg Empty string, it will be populated with an error message, if any 122 | * @param string $name Name of the package to test 123 | * @param string $req The package version required 124 | * @param string $relation How to compare versions with each other 125 | * @param bool $opt Whether the relationship is optional 126 | * 127 | * @return mixed bool false if no error or the error string 128 | */ 129 | function checkPackage(&$errmsg, $name, $req = null, $relation = 'has', 130 | $opt = false) 131 | { 132 | if (is_string($req) && substr($req, 0, 2) == 'v.') { 133 | $req = substr($req, 2); 134 | } 135 | switch ($relation) { 136 | case 'has': 137 | if (!$this->registry->packageExists($name)) { 138 | if ($opt) { 139 | $errmsg = "package `$name' is recommended to utilize some features."; 140 | return PEAR_DEPENDENCY_MISSING_OPTIONAL; 141 | } 142 | $errmsg = "requires package `$name'"; 143 | return PEAR_DEPENDENCY_MISSING; 144 | } 145 | return false; 146 | case 'not': 147 | if ($this->registry->packageExists($name)) { 148 | $errmsg = "conflicts with package `$name'"; 149 | return PEAR_DEPENDENCY_CONFLICT; 150 | } 151 | return false; 152 | case 'lt': 153 | case 'le': 154 | case 'eq': 155 | case 'ne': 156 | case 'ge': 157 | case 'gt': 158 | $version = $this->registry->packageInfo($name, 'version'); 159 | if (!$this->registry->packageExists($name) 160 | || !version_compare("$version", "$req", $relation)) 161 | { 162 | $code = $this->codeFromRelation($relation, $version, $req, $opt); 163 | if ($opt) { 164 | $errmsg = "package `$name' version " . $this->signOperator($relation) . 165 | " $req is recommended to utilize some features."; 166 | if ($version) { 167 | $errmsg .= " Installed version is $version"; 168 | } 169 | return $code; 170 | } 171 | $errmsg = "requires package `$name' " . 172 | $this->signOperator($relation) . " $req"; 173 | return $code; 174 | } 175 | return false; 176 | } 177 | $errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)"; 178 | return PEAR_DEPENDENCY_BAD_DEPENDENCY; 179 | } 180 | 181 | // }}} 182 | // {{{ checkPackageUninstall() 183 | 184 | /** 185 | * Check package dependencies on uninstall 186 | * 187 | * @param string $error The resultant error string 188 | * @param string $warning The resultant warning string 189 | * @param string $name Name of the package to test 190 | * 191 | * @return bool true if there were errors 192 | */ 193 | function checkPackageUninstall(&$error, &$warning, $package) 194 | { 195 | $error = null; 196 | $packages = $this->registry->listPackages(); 197 | foreach ($packages as $pkg) { 198 | if ($pkg == $package) { 199 | continue; 200 | } 201 | $deps = $this->registry->packageInfo($pkg, 'release_deps'); 202 | if (empty($deps)) { 203 | continue; 204 | } 205 | foreach ($deps as $dep) { 206 | if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) { 207 | if ($dep['rel'] == 'ne' || $dep['rel'] == 'not') { 208 | continue; 209 | } 210 | if (isset($dep['optional']) && $dep['optional'] == 'yes') { 211 | $warning .= "\nWarning: Package '$pkg' optionally depends on '$package'"; 212 | } else { 213 | $error .= "Package '$pkg' depends on '$package'\n"; 214 | } 215 | } 216 | } 217 | } 218 | return ($error) ? true : false; 219 | } 220 | 221 | // }}} 222 | // {{{ checkExtension() 223 | 224 | /** 225 | * Extension dependencies check method 226 | * 227 | * @param string $name Name of the extension to test 228 | * @param string $req_ext_ver Required extension version to compare with 229 | * @param string $relation How to compare versions with eachother 230 | * @param bool $opt Whether the relationship is optional 231 | * 232 | * @return mixed bool false if no error or the error string 233 | */ 234 | function checkExtension(&$errmsg, $name, $req = null, $relation = 'has', 235 | $opt = false) 236 | { 237 | if ($relation == 'not') { 238 | if (extension_loaded($name)) { 239 | $errmsg = "conflicts with PHP extension '$name'"; 240 | return PEAR_DEPENDENCY_CONFLICT; 241 | } else { 242 | return false; 243 | } 244 | } 245 | 246 | if (!extension_loaded($name)) { 247 | if ($relation == 'not') { 248 | return false; 249 | } 250 | if ($opt) { 251 | $errmsg = "'$name' PHP extension is recommended to utilize some features"; 252 | return PEAR_DEPENDENCY_MISSING_OPTIONAL; 253 | } 254 | $errmsg = "'$name' PHP extension is not installed"; 255 | return PEAR_DEPENDENCY_MISSING; 256 | } 257 | if ($relation == 'has') { 258 | return false; 259 | } 260 | $code = false; 261 | if (is_string($req) && substr($req, 0, 2) == 'v.') { 262 | $req = substr($req, 2); 263 | } 264 | $ext_ver = phpversion($name); 265 | $operator = $relation; 266 | // Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90) 267 | if (!version_compare("$ext_ver", "$req", $operator)) { 268 | $errmsg = "'$name' PHP extension version " . 269 | $this->signOperator($operator) . " $req is required"; 270 | $code = $this->codeFromRelation($relation, $ext_ver, $req, $opt); 271 | if ($opt) { 272 | $errmsg = "'$name' PHP extension version " . $this->signOperator($operator) . 273 | " $req is recommended to utilize some features"; 274 | return $code; 275 | } 276 | } 277 | return $code; 278 | } 279 | 280 | // }}} 281 | // {{{ checkOS() 282 | 283 | /** 284 | * Operating system dependencies check method 285 | * 286 | * @param string $os Name of the operating system 287 | * 288 | * @return mixed bool false if no error or the error string 289 | */ 290 | function checkOS(&$errmsg, $os) 291 | { 292 | // XXX Fixme: Implement a more flexible way, like 293 | // comma separated values or something similar to PEAR_OS 294 | static $myos; 295 | if (empty($myos)) { 296 | include_once "OS/Guess.php"; 297 | $myos = new OS_Guess(); 298 | } 299 | // only 'has' relation is currently supported 300 | if ($myos->matchSignature($os)) { 301 | return false; 302 | } 303 | $errmsg = "'$os' operating system not supported"; 304 | return PEAR_DEPENDENCY_CONFLICT; 305 | } 306 | 307 | // }}} 308 | // {{{ checkPHP() 309 | 310 | /** 311 | * PHP version check method 312 | * 313 | * @param string $req which version to compare 314 | * @param string $relation how to compare the version 315 | * 316 | * @return mixed bool false if no error or the error string 317 | */ 318 | function checkPHP(&$errmsg, $req, $relation = 'ge') 319 | { 320 | // this would be a bit stupid, but oh well :) 321 | if ($relation == 'has') { 322 | return false; 323 | } 324 | if ($relation == 'not') { 325 | $errmsg = 'Invalid dependency - "not" is not allowed for php dependencies, ' . 326 | 'php cannot conflict with itself'; 327 | return PEAR_DEPENDENCY_BAD_DEPENDENCY; 328 | } 329 | if (substr($req, 0, 2) == 'v.') { 330 | $req = substr($req,2, strlen($req) - 2); 331 | } 332 | $php_ver = phpversion(); 333 | $operator = $relation; 334 | if (!version_compare("$php_ver", "$req", $operator)) { 335 | $errmsg = "PHP version " . $this->signOperator($operator) . 336 | " $req is required"; 337 | return PEAR_DEPENDENCY_CONFLICT; 338 | } 339 | return false; 340 | } 341 | 342 | // }}} 343 | // {{{ checkProgram() 344 | 345 | /** 346 | * External program check method. Looks for executable files in 347 | * directories listed in the PATH environment variable. 348 | * 349 | * @param string $program which program to look for 350 | * 351 | * @return mixed bool false if no error or the error string 352 | */ 353 | function checkProgram(&$errmsg, $program) 354 | { 355 | // XXX FIXME honor safe mode 356 | $exe_suffix = OS_WINDOWS ? '.exe' : ''; 357 | $path_elements = explode(PATH_SEPARATOR, getenv('PATH')); 358 | foreach ($path_elements as $dir) { 359 | $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix; 360 | if (@file_exists($file) && @is_executable($file)) { 361 | return false; 362 | } 363 | } 364 | $errmsg = "'$program' program is not present in the PATH"; 365 | return PEAR_DEPENDENCY_MISSING; 366 | } 367 | 368 | // }}} 369 | // {{{ checkSAPI() 370 | 371 | /** 372 | * SAPI backend check method. Version comparison is not yet 373 | * available here. 374 | * 375 | * @param string $name name of SAPI backend 376 | * @param string $req which version to compare 377 | * @param string $relation how to compare versions (currently 378 | * hardcoded to 'has') 379 | * @return mixed bool false if no error or the error string 380 | */ 381 | function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has') 382 | { 383 | // XXX Fixme: There is no way to know if the user has or 384 | // not other SAPI backends installed than the installer one 385 | 386 | $sapi_backend = php_sapi_name(); 387 | // Version comparisons not supported, sapi backends don't have 388 | // version information yet. 389 | if ($sapi_backend == $name) { 390 | return false; 391 | } 392 | $errmsg = "'$sapi_backend' SAPI backend not supported"; 393 | return PEAR_DEPENDENCY_CONFLICT; 394 | } 395 | 396 | // }}} 397 | // {{{ checkZend() 398 | 399 | /** 400 | * Zend version check method 401 | * 402 | * @param string $req which version to compare 403 | * @param string $relation how to compare the version 404 | * 405 | * @return mixed bool false if no error or the error string 406 | */ 407 | function checkZend(&$errmsg, $req, $relation = 'ge') 408 | { 409 | if (substr($req, 0, 2) == 'v.') { 410 | $req = substr($req,2, strlen($req) - 2); 411 | } 412 | $zend_ver = zend_version(); 413 | $operator = substr($relation,0,2); 414 | if (!version_compare("$zend_ver", "$req", $operator)) { 415 | $errmsg = "Zend version " . $this->signOperator($operator) . 416 | " $req is required"; 417 | return PEAR_DEPENDENCY_CONFLICT; 418 | } 419 | return false; 420 | } 421 | 422 | // }}} 423 | // {{{ signOperator() 424 | 425 | /** 426 | * Converts text comparing operators to them sign equivalents 427 | * 428 | * Example: 'ge' to '>=' 429 | * 430 | * @access public 431 | * @param string Operator 432 | * @return string Sign equivalent 433 | */ 434 | function signOperator($operator) 435 | { 436 | switch($operator) { 437 | case 'lt': return '<'; 438 | case 'le': return '<='; 439 | case 'gt': return '>'; 440 | case 'ge': return '>='; 441 | case 'eq': return '=='; 442 | case 'ne': return '!='; 443 | default: 444 | return $operator; 445 | } 446 | } 447 | 448 | // }}} 449 | // {{{ codeFromRelation() 450 | 451 | /** 452 | * Convert relation into corresponding code 453 | * 454 | * @access public 455 | * @param string Relation 456 | * @param string Version 457 | * @param string Requirement 458 | * @param bool Optional dependency indicator 459 | * @return integer 460 | */ 461 | function codeFromRelation($relation, $version, $req, $opt = false) 462 | { 463 | $code = PEAR_DEPENDENCY_BAD_DEPENDENCY; 464 | switch ($relation) { 465 | case 'gt': case 'ge': case 'eq': 466 | // upgrade 467 | $have_major = preg_replace('/\D.*/', '', $version); 468 | $need_major = preg_replace('/\D.*/', '', $req); 469 | if ($need_major > $have_major) { 470 | $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL : 471 | PEAR_DEPENDENCY_UPGRADE_MAJOR; 472 | } else { 473 | $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL : 474 | PEAR_DEPENDENCY_UPGRADE_MINOR; 475 | } 476 | break; 477 | case 'lt': case 'le': case 'ne': 478 | $code = $opt ? PEAR_DEPENDENCY_CONFLICT_OPTIONAL : 479 | PEAR_DEPENDENCY_CONFLICT; 480 | break; 481 | } 482 | return $code; 483 | } 484 | 485 | // }}} 486 | } 487 | ?> 488 | -------------------------------------------------------------------------------- /inc/PEAR/Exception.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Hans Lellelid | 18 | // | Bertrand Mansion | 19 | // | Greg Beaver | 20 | // +----------------------------------------------------------------------+ 21 | // 22 | // $Id: Exception.php,v 1.4.2.2 2004/12/31 19:01:52 cellog Exp $ 23 | 24 | 25 | /** 26 | * Base PEAR_Exception Class 27 | * 28 | * WARNING: This code should be considered stable, but the API is 29 | * subject to immediate and drastic change, so API stability is 30 | * at best alpha 31 | * 32 | * 1) Features: 33 | * 34 | * - Nestable exceptions (throw new PEAR_Exception($msg, $prev_exception)) 35 | * - Definable triggers, shot when exceptions occur 36 | * - Pretty and informative error messages 37 | * - Added more context info available (like class, method or cause) 38 | * - cause can be a PEAR_Exception or an array of mixed 39 | * PEAR_Exceptions/PEAR_ErrorStack warnings 40 | * - callbacks for specific exception classes and their children 41 | * 42 | * 2) Ideas: 43 | * 44 | * - Maybe a way to define a 'template' for the output 45 | * 46 | * 3) Inherited properties from PHP Exception Class: 47 | * 48 | * protected $message 49 | * protected $code 50 | * protected $line 51 | * protected $file 52 | * private $trace 53 | * 54 | * 4) Inherited methods from PHP Exception Class: 55 | * 56 | * __clone 57 | * __construct 58 | * getMessage 59 | * getCode 60 | * getFile 61 | * getLine 62 | * getTraceSafe 63 | * getTraceSafeAsString 64 | * __toString 65 | * 66 | * 5) Usage example 67 | * 68 | * 69 | * require_once 'PEAR/Exception.php'; 70 | * 71 | * class Test { 72 | * function foo() { 73 | * throw new PEAR_Exception('Error Message', ERROR_CODE); 74 | * } 75 | * } 76 | * 77 | * function myLogger($pear_exception) { 78 | * echo $pear_exception->getMessage(); 79 | * } 80 | * // each time a exception is thrown the 'myLogger' will be called 81 | * // (its use is completely optional) 82 | * PEAR_Exception::addObserver('myLogger'); 83 | * $test = new Test; 84 | * try { 85 | * $test->foo(); 86 | * } catch (PEAR_Exception $e) { 87 | * print $e; 88 | * } 89 | * 90 | * 91 | * @since PHP 5 92 | * @package PEAR 93 | * @version $Revision: 1.4.2.2 $ 94 | * @author Tomas V.V.Cox 95 | * @author Hans Lellelid 96 | * @author Bertrand Mansion 97 | * 98 | */ 99 | class PEAR_Exception extends Exception 100 | { 101 | const OBSERVER_PRINT = -2; 102 | const OBSERVER_TRIGGER = -4; 103 | const OBSERVER_DIE = -8; 104 | protected $cause; 105 | private static $_observers = array(); 106 | private static $_uniqueid = 0; 107 | private $_trace; 108 | 109 | /** 110 | * Supported signatures: 111 | * PEAR_Exception(string $message); 112 | * PEAR_Exception(string $message, int $code); 113 | * PEAR_Exception(string $message, Exception $cause); 114 | * PEAR_Exception(string $message, Exception $cause, int $code); 115 | * PEAR_Exception(string $message, array $causes); 116 | * PEAR_Exception(string $message, array $causes, int $code); 117 | */ 118 | public function __construct($message, $p2 = null, $p3 = null) 119 | { 120 | if (is_int($p2)) { 121 | $code = $p2; 122 | $this->cause = null; 123 | } elseif ($p2 instanceof Exception || is_array($p2)) { 124 | $code = $p3; 125 | if (is_array($p2) && isset($p2['message'])) { 126 | // fix potential problem of passing in a single warning 127 | $p2 = array($p2); 128 | } 129 | $this->cause = $p2; 130 | } else { 131 | $code = null; 132 | $this->cause = null; 133 | } 134 | parent::__construct($message, $code); 135 | $this->signal(); 136 | } 137 | 138 | /** 139 | * @param mixed $callback - A valid php callback, see php func is_callable() 140 | * - A PEAR_Exception::OBSERVER_* constant 141 | * - An array(const PEAR_Exception::OBSERVER_*, 142 | * mixed $options) 143 | * @param string $label The name of the observer. Use this if you want 144 | * to remove it later with removeObserver() 145 | */ 146 | public static function addObserver($callback, $label = 'default') 147 | { 148 | self::$_observers[$label] = $callback; 149 | } 150 | 151 | public static function removeObserver($label = 'default') 152 | { 153 | unset(self::$_observers[$label]); 154 | } 155 | 156 | /** 157 | * @return int unique identifier for an observer 158 | */ 159 | public static function getUniqueId() 160 | { 161 | return self::$_uniqueid++; 162 | } 163 | 164 | private function signal() 165 | { 166 | foreach (self::$_observers as $func) { 167 | if (is_callable($func)) { 168 | call_user_func($func, $this); 169 | continue; 170 | } 171 | settype($func, 'array'); 172 | switch ($func[0]) { 173 | case self::OBSERVER_PRINT : 174 | $f = (isset($func[1])) ? $func[1] : '%s'; 175 | printf($f, $this->getMessage()); 176 | break; 177 | case self::OBSERVER_TRIGGER : 178 | $f = (isset($func[1])) ? $func[1] : E_USER_NOTICE; 179 | trigger_error($this->getMessage(), $f); 180 | break; 181 | case self::OBSERVER_DIE : 182 | $f = (isset($func[1])) ? $func[1] : '%s'; 183 | die(printf($f, $this->getMessage())); 184 | break; 185 | default: 186 | trigger_error('invalid observer type', E_USER_WARNING); 187 | } 188 | } 189 | } 190 | 191 | /** 192 | * Return specific error information that can be used for more detailed 193 | * error messages or translation. 194 | * 195 | * This method may be overridden in child exception classes in order 196 | * to add functionality not present in PEAR_Exception and is a placeholder 197 | * to define API 198 | * 199 | * The returned array must be an associative array of parameter => value like so: 200 | *
201 |      * array('name' => $name, 'context' => array(...))
202 |      * 
203 | * @return array 204 | */ 205 | public function getErrorData() 206 | { 207 | return array(); 208 | } 209 | 210 | /** 211 | * Returns the exception that caused this exception to be thrown 212 | * @access public 213 | * @return Exception|array The context of the exception 214 | */ 215 | public function getCause() 216 | { 217 | return $this->cause; 218 | } 219 | 220 | /** 221 | * Function must be public to call on caused exceptions 222 | * @param array 223 | */ 224 | public function getCauseMessage(&$causes) 225 | { 226 | $trace = $this->getTraceSafe(); 227 | $cause = array('class' => get_class($this), 228 | 'message' => $this->message, 229 | 'file' => 'unknown', 230 | 'line' => 'unknown'); 231 | if (isset($trace[0])) { 232 | if (isset($trace[0]['file'])) { 233 | $cause['file'] = $trace[0]['file']; 234 | $cause['line'] = $trace[0]['line']; 235 | } 236 | } 237 | if ($this->cause instanceof PEAR_Exception) { 238 | $this->cause->getCauseMessage($causes); 239 | } 240 | if (is_array($this->cause)) { 241 | foreach ($this->cause as $cause) { 242 | if ($cause instanceof PEAR_Exception) { 243 | $cause->getCauseMessage($causes); 244 | } elseif (is_array($cause) && isset($cause['message'])) { 245 | // PEAR_ErrorStack warning 246 | $causes[] = array( 247 | 'class' => $cause['package'], 248 | 'message' => $cause['message'], 249 | 'file' => isset($cause['context']['file']) ? 250 | $cause['context']['file'] : 251 | 'unknown', 252 | 'line' => isset($cause['context']['line']) ? 253 | $cause['context']['line'] : 254 | 'unknown', 255 | ); 256 | } 257 | } 258 | } 259 | } 260 | 261 | public function getTraceSafe() 262 | { 263 | if (!isset($this->_trace)) { 264 | $this->_trace = $this->getTrace(); 265 | if (empty($this->_trace)) { 266 | $backtrace = debug_backtrace(); 267 | $this->_trace = array($backtrace[count($backtrace)-1]); 268 | } 269 | } 270 | return $this->_trace; 271 | } 272 | 273 | public function getErrorClass() 274 | { 275 | $trace = $this->getTraceSafe(); 276 | return $trace[0]['class']; 277 | } 278 | 279 | public function getErrorMethod() 280 | { 281 | $trace = $this->getTraceSafe(); 282 | return $trace[0]['function']; 283 | } 284 | 285 | public function __toString() 286 | { 287 | if (isset($_SERVER['REQUEST_URI'])) { 288 | return $this->toHtml(); 289 | } 290 | return $this->toText(); 291 | } 292 | 293 | public function toHtml() 294 | { 295 | $trace = $this->getTraceSafe(); 296 | $causes = array(); 297 | $this->getCauseMessage($causes); 298 | $html = '' . "\n"; 299 | foreach ($causes as $i => $cause) { 300 | $html .= '\n"; 305 | } 306 | $html .= '' . "\n" 307 | . '' 308 | . '' 309 | . '' . "\n"; 310 | 311 | foreach ($trace as $k => $v) { 312 | $html .= '' 313 | . '' 336 | . '' . "\n"; 337 | } 338 | $html .= '' 339 | . '' 340 | . '' . "\n" 341 | . '
' 301 | . str_repeat('-', $i) . ' ' . $cause['class'] . ': ' 302 | . htmlspecialchars($cause['message']) . ' in ' . $cause['file'] . ' ' 303 | . 'on line ' . $cause['line'] . '' 304 | . "
Exception trace
#FunctionLocation
' . $k . ''; 314 | if (!empty($v['class'])) { 315 | $html .= $v['class'] . $v['type']; 316 | } 317 | $html .= $v['function']; 318 | $args = array(); 319 | if (!empty($v['args'])) { 320 | foreach ($v['args'] as $arg) { 321 | if (is_null($arg)) $args[] = 'null'; 322 | elseif (is_array($arg)) $args[] = 'Array'; 323 | elseif (is_object($arg)) $args[] = 'Object('.get_class($arg).')'; 324 | elseif (is_bool($arg)) $args[] = $arg ? 'true' : 'false'; 325 | elseif (is_int($arg) || is_double($arg)) $args[] = $arg; 326 | else { 327 | $arg = (string)$arg; 328 | $str = htmlspecialchars(substr($arg, 0, 16)); 329 | if (strlen($arg) > 16) $str .= '…'; 330 | $args[] = "'" . $str . "'"; 331 | } 332 | } 333 | } 334 | $html .= '(' . implode(', ',$args) . ')' 335 | . '' . $v['file'] . ':' . $v['line'] . '
' . ($k+1) . '{main} 
'; 342 | return $html; 343 | } 344 | 345 | public function toText() 346 | { 347 | $causes = array(); 348 | $this->getCauseMessage($causes); 349 | $causeMsg = ''; 350 | foreach ($causes as $i => $cause) { 351 | $causeMsg .= str_repeat(' ', $i) . $cause['class'] . ': ' 352 | . $cause['message'] . ' in ' . $cause['file'] 353 | . ' on line ' . $cause['line'] . "\n"; 354 | } 355 | return $causeMsg . $this->getTraceAsString(); 356 | } 357 | } 358 | 359 | ?> -------------------------------------------------------------------------------- /inc/PEAR/Frontend/CLI.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/krueschan/phpZoteroWebDAV/1f2236bb362c45727fab1341803b5b6fbb624b5b/inc/PEAR/Frontend/CLI.php -------------------------------------------------------------------------------- /inc/PEAR/Packager.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Tomas V.V.Cox | 18 | // +----------------------------------------------------------------------+ 19 | // 20 | // $Id: Packager.php,v 1.53 2004/06/13 14:06:01 pajoye Exp $ 21 | 22 | require_once 'PEAR/Common.php'; 23 | require_once 'System.php'; 24 | 25 | /** 26 | * Administration class used to make a PEAR release tarball. 27 | * 28 | * TODO: 29 | * - add an extra param the dir where to place the created package 30 | * 31 | * @since PHP 4.0.2 32 | * @author Stig Bakken 33 | */ 34 | class PEAR_Packager extends PEAR_Common 35 | { 36 | // {{{ constructor 37 | 38 | function PEAR_Packager() 39 | { 40 | parent::PEAR_Common(); 41 | } 42 | 43 | // }}} 44 | // {{{ destructor 45 | 46 | function _PEAR_Packager() 47 | { 48 | parent::_PEAR_Common(); 49 | } 50 | 51 | // }}} 52 | 53 | // {{{ package() 54 | 55 | function package($pkgfile = null, $compress = true) 56 | { 57 | // {{{ validate supplied package.xml file 58 | if (empty($pkgfile)) { 59 | $pkgfile = 'package.xml'; 60 | } 61 | // $this->pkginfo gets populated inside 62 | $pkginfo = $this->infoFromDescriptionFile($pkgfile); 63 | if (PEAR::isError($pkginfo)) { 64 | return $this->raiseError($pkginfo); 65 | } 66 | 67 | $pkgdir = dirname(realpath($pkgfile)); 68 | $pkgfile = basename($pkgfile); 69 | 70 | $errors = $warnings = array(); 71 | $this->validatePackageInfo($pkginfo, $errors, $warnings, $pkgdir); 72 | foreach ($warnings as $w) { 73 | $this->log(1, "Warning: $w"); 74 | } 75 | foreach ($errors as $e) { 76 | $this->log(0, "Error: $e"); 77 | } 78 | if (sizeof($errors) > 0) { 79 | return $this->raiseError('Errors in package'); 80 | } 81 | // }}} 82 | 83 | $pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; 84 | 85 | // {{{ Create the package file list 86 | $filelist = array(); 87 | $i = 0; 88 | 89 | foreach ($pkginfo['filelist'] as $fname => $atts) { 90 | $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; 91 | if (!file_exists($file)) { 92 | return $this->raiseError("File does not exist: $fname"); 93 | } else { 94 | $filelist[$i++] = $file; 95 | if (empty($pkginfo['filelist'][$fname]['md5sum'])) { 96 | $md5sum = md5_file($file); 97 | $pkginfo['filelist'][$fname]['md5sum'] = $md5sum; 98 | } 99 | $this->log(2, "Adding file $fname"); 100 | } 101 | } 102 | // }}} 103 | 104 | // {{{ regenerate package.xml 105 | $new_xml = $this->xmlFromInfo($pkginfo); 106 | if (PEAR::isError($new_xml)) { 107 | return $this->raiseError($new_xml); 108 | } 109 | if (!($tmpdir = System::mktemp(array('-d')))) { 110 | return $this->raiseError("PEAR_Packager: mktemp failed"); 111 | } 112 | $newpkgfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; 113 | $np = @fopen($newpkgfile, 'wb'); 114 | if (!$np) { 115 | return $this->raiseError("PEAR_Packager: unable to rewrite $pkgfile as $newpkgfile"); 116 | } 117 | fwrite($np, $new_xml); 118 | fclose($np); 119 | // }}} 120 | 121 | // {{{ TAR the Package ------------------------------------------- 122 | $ext = $compress ? '.tgz' : '.tar'; 123 | $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; 124 | $tar =& new Archive_Tar($dest_package, $compress); 125 | $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors 126 | // ----- Creates with the package.xml file 127 | $ok = $tar->createModify(array($newpkgfile), '', $tmpdir); 128 | if (PEAR::isError($ok)) { 129 | return $this->raiseError($ok); 130 | } elseif (!$ok) { 131 | return $this->raiseError('PEAR_Packager: tarball creation failed'); 132 | } 133 | // ----- Add the content of the package 134 | if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { 135 | return $this->raiseError('PEAR_Packager: tarball creation failed'); 136 | } 137 | $this->log(1, "Package $dest_package done"); 138 | if (file_exists("$pkgdir/CVS/Root")) { 139 | $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pkginfo['version']); 140 | $cvstag = "RELEASE_$cvsversion"; 141 | $this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); 142 | $this->log(1, "(or set the CVS tag $cvstag by hand)"); 143 | } 144 | // }}} 145 | 146 | return $dest_package; 147 | } 148 | 149 | // }}} 150 | } 151 | 152 | // {{{ md5_file() utility function 153 | if (!function_exists('md5_file')) { 154 | function md5_file($file) { 155 | if (!$fd = @fopen($file, 'r')) { 156 | return false; 157 | } 158 | $md5 = md5(fread($fd, filesize($file))); 159 | fclose($fd); 160 | return $md5; 161 | } 162 | } 163 | // }}} 164 | 165 | ?> 166 | -------------------------------------------------------------------------------- /inc/PEAR/Registry.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Tomas V.V.Cox | 18 | // | | 19 | // +----------------------------------------------------------------------+ 20 | // 21 | // $Id: Registry.php,v 1.50.4.3 2004/10/26 19:19:56 cellog Exp $ 22 | 23 | /* 24 | TODO: 25 | - Transform into singleton() 26 | - Add application level lock (avoid change the registry from the cmdline 27 | while using the GTK interface, for ex.) 28 | */ 29 | require_once "System.php"; 30 | require_once "PEAR.php"; 31 | 32 | define('PEAR_REGISTRY_ERROR_LOCK', -2); 33 | define('PEAR_REGISTRY_ERROR_FORMAT', -3); 34 | define('PEAR_REGISTRY_ERROR_FILE', -4); 35 | 36 | /** 37 | * Administration class used to maintain the installed package database. 38 | */ 39 | class PEAR_Registry extends PEAR 40 | { 41 | // {{{ properties 42 | 43 | /** Directory where registry files are stored. 44 | * @var string 45 | */ 46 | var $statedir = ''; 47 | 48 | /** File where the file map is stored 49 | * @var string 50 | */ 51 | var $filemap = ''; 52 | 53 | /** Name of file used for locking the registry 54 | * @var string 55 | */ 56 | var $lockfile = ''; 57 | 58 | /** File descriptor used during locking 59 | * @var resource 60 | */ 61 | var $lock_fp = null; 62 | 63 | /** Mode used during locking 64 | * @var int 65 | */ 66 | var $lock_mode = 0; // XXX UNUSED 67 | 68 | /** Cache of package information. Structure: 69 | * array( 70 | * 'package' => array('id' => ... ), 71 | * ... ) 72 | * @var array 73 | */ 74 | var $pkginfo_cache = array(); 75 | 76 | /** Cache of file map. Structure: 77 | * array( '/path/to/file' => 'package', ... ) 78 | * @var array 79 | */ 80 | var $filemap_cache = array(); 81 | 82 | // }}} 83 | 84 | // {{{ constructor 85 | 86 | /** 87 | * PEAR_Registry constructor. 88 | * 89 | * @param string (optional) PEAR install directory (for .php files) 90 | * 91 | * @access public 92 | */ 93 | function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR) 94 | { 95 | parent::PEAR(); 96 | $ds = DIRECTORY_SEPARATOR; 97 | $this->install_dir = $pear_install_dir; 98 | $this->statedir = $pear_install_dir.$ds.'.registry'; 99 | $this->filemap = $pear_install_dir.$ds.'.filemap'; 100 | $this->lockfile = $pear_install_dir.$ds.'.lock'; 101 | 102 | // XXX Compatibility code should be removed in the future 103 | // rename all registry files if any to lowercase 104 | if (!OS_WINDOWS && $handle = @opendir($this->statedir)) { 105 | $dest = $this->statedir . DIRECTORY_SEPARATOR; 106 | while (false !== ($file = readdir($handle))) { 107 | if (preg_match('/^.*[A-Z].*\.reg$/', $file)) { 108 | rename($dest . $file, $dest . strtolower($file)); 109 | } 110 | } 111 | closedir($handle); 112 | } 113 | if (!file_exists($this->filemap)) { 114 | $this->rebuildFileMap(); 115 | } 116 | } 117 | 118 | // }}} 119 | // {{{ destructor 120 | 121 | /** 122 | * PEAR_Registry destructor. Makes sure no locks are forgotten. 123 | * 124 | * @access private 125 | */ 126 | function _PEAR_Registry() 127 | { 128 | parent::_PEAR(); 129 | if (is_resource($this->lock_fp)) { 130 | $this->_unlock(); 131 | } 132 | } 133 | 134 | // }}} 135 | 136 | // {{{ _assertStateDir() 137 | 138 | /** 139 | * Make sure the directory where we keep registry files exists. 140 | * 141 | * @return bool TRUE if directory exists, FALSE if it could not be 142 | * created 143 | * 144 | * @access private 145 | */ 146 | function _assertStateDir() 147 | { 148 | if (!@is_dir($this->statedir)) { 149 | if (!System::mkdir(array('-p', $this->statedir))) { 150 | return $this->raiseError("could not create directory '{$this->statedir}'"); 151 | } 152 | } 153 | return true; 154 | } 155 | 156 | // }}} 157 | // {{{ _packageFileName() 158 | 159 | /** 160 | * Get the name of the file where data for a given package is stored. 161 | * 162 | * @param string package name 163 | * 164 | * @return string registry file name 165 | * 166 | * @access public 167 | */ 168 | function _packageFileName($package) 169 | { 170 | return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; 171 | } 172 | 173 | // }}} 174 | // {{{ _openPackageFile() 175 | 176 | function _openPackageFile($package, $mode) 177 | { 178 | $this->_assertStateDir(); 179 | $file = $this->_packageFileName($package); 180 | $fp = @fopen($file, $mode); 181 | if (!$fp) { 182 | return null; 183 | } 184 | return $fp; 185 | } 186 | 187 | // }}} 188 | // {{{ _closePackageFile() 189 | 190 | function _closePackageFile($fp) 191 | { 192 | fclose($fp); 193 | } 194 | 195 | // }}} 196 | // {{{ rebuildFileMap() 197 | 198 | function rebuildFileMap() 199 | { 200 | $packages = $this->listPackages(); 201 | $files = array(); 202 | foreach ($packages as $package) { 203 | $version = $this->packageInfo($package, 'version'); 204 | $filelist = $this->packageInfo($package, 'filelist'); 205 | if (!is_array($filelist)) { 206 | continue; 207 | } 208 | foreach ($filelist as $name => $attrs) { 209 | if (isset($attrs['role']) && $attrs['role'] != 'php') { 210 | continue; 211 | } 212 | if (isset($attrs['baseinstalldir'])) { 213 | $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; 214 | } else { 215 | $file = $name; 216 | } 217 | $file = preg_replace(',^/+,', '', $file); 218 | $files[$file] = $package; 219 | } 220 | } 221 | $this->_assertStateDir(); 222 | $fp = @fopen($this->filemap, 'wb'); 223 | if (!$fp) { 224 | return false; 225 | } 226 | $this->filemap_cache = $files; 227 | fwrite($fp, serialize($files)); 228 | fclose($fp); 229 | return true; 230 | } 231 | 232 | // }}} 233 | // {{{ readFileMap() 234 | 235 | function readFileMap() 236 | { 237 | $fp = @fopen($this->filemap, 'r'); 238 | if (!$fp) { 239 | return $this->raiseError('PEAR_Registry: could not open filemap', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); 240 | } 241 | $fsize = filesize($this->filemap); 242 | $rt = get_magic_quotes_runtime(); 243 | set_magic_quotes_runtime(0); 244 | $data = fread($fp, $fsize); 245 | set_magic_quotes_runtime($rt); 246 | fclose($fp); 247 | $tmp = unserialize($data); 248 | if (!$tmp && $fsize > 7) { 249 | return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); 250 | } 251 | $this->filemap_cache = $tmp; 252 | return true; 253 | } 254 | 255 | // }}} 256 | // {{{ _lock() 257 | 258 | /** 259 | * Lock the registry. 260 | * 261 | * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. 262 | * See flock manual for more information. 263 | * 264 | * @return bool TRUE on success, FALSE if locking failed, or a 265 | * PEAR error if some other error occurs (such as the 266 | * lock file not being writable). 267 | * 268 | * @access private 269 | */ 270 | function _lock($mode = LOCK_EX) 271 | { 272 | if (!eregi('Windows 9', php_uname())) { 273 | if ($mode != LOCK_UN && is_resource($this->lock_fp)) { 274 | // XXX does not check type of lock (LOCK_SH/LOCK_EX) 275 | return true; 276 | } 277 | if (PEAR::isError($err = $this->_assertStateDir())) { 278 | return $err; 279 | } 280 | $open_mode = 'w'; 281 | // XXX People reported problems with LOCK_SH and 'w' 282 | if ($mode === LOCK_SH || $mode === LOCK_UN) { 283 | if (@!is_file($this->lockfile)) { 284 | touch($this->lockfile); 285 | } 286 | $open_mode = 'r'; 287 | } 288 | 289 | if (!is_resource($this->lock_fp)) { 290 | $this->lock_fp = @fopen($this->lockfile, $open_mode); 291 | } 292 | 293 | if (!is_resource($this->lock_fp)) { 294 | return $this->raiseError("could not create lock file" . 295 | (isset($php_errormsg) ? ": " . $php_errormsg : "")); 296 | } 297 | if (!(int)flock($this->lock_fp, $mode)) { 298 | switch ($mode) { 299 | case LOCK_SH: $str = 'shared'; break; 300 | case LOCK_EX: $str = 'exclusive'; break; 301 | case LOCK_UN: $str = 'unlock'; break; 302 | default: $str = 'unknown'; break; 303 | } 304 | return $this->raiseError("could not acquire $str lock ($this->lockfile)", 305 | PEAR_REGISTRY_ERROR_LOCK); 306 | } 307 | } 308 | return true; 309 | } 310 | 311 | // }}} 312 | // {{{ _unlock() 313 | 314 | function _unlock() 315 | { 316 | $ret = $this->_lock(LOCK_UN); 317 | if (is_resource($this->lock_fp)) { 318 | fclose($this->lock_fp); 319 | } 320 | $this->lock_fp = null; 321 | return $ret; 322 | } 323 | 324 | // }}} 325 | // {{{ _packageExists() 326 | 327 | function _packageExists($package) 328 | { 329 | return file_exists($this->_packageFileName($package)); 330 | } 331 | 332 | // }}} 333 | // {{{ _packageInfo() 334 | 335 | function _packageInfo($package = null, $key = null) 336 | { 337 | if ($package === null) { 338 | return array_map(array($this, '_packageInfo'), 339 | $this->_listPackages()); 340 | } 341 | $fp = $this->_openPackageFile($package, 'r'); 342 | if ($fp === null) { 343 | return null; 344 | } 345 | $rt = get_magic_quotes_runtime(); 346 | set_magic_quotes_runtime(0); 347 | $data = fread($fp, filesize($this->_packageFileName($package))); 348 | set_magic_quotes_runtime($rt); 349 | $this->_closePackageFile($fp); 350 | $data = unserialize($data); 351 | if ($key === null) { 352 | return $data; 353 | } 354 | if (isset($data[$key])) { 355 | return $data[$key]; 356 | } 357 | return null; 358 | } 359 | 360 | // }}} 361 | // {{{ _listPackages() 362 | 363 | function _listPackages() 364 | { 365 | $pkglist = array(); 366 | $dp = @opendir($this->statedir); 367 | if (!$dp) { 368 | return $pkglist; 369 | } 370 | while ($ent = readdir($dp)) { 371 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { 372 | continue; 373 | } 374 | $pkglist[] = substr($ent, 0, -4); 375 | } 376 | return $pkglist; 377 | } 378 | 379 | // }}} 380 | 381 | // {{{ packageExists() 382 | 383 | function packageExists($package) 384 | { 385 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { 386 | return $e; 387 | } 388 | $ret = $this->_packageExists($package); 389 | $this->_unlock(); 390 | return $ret; 391 | } 392 | 393 | // }}} 394 | // {{{ packageInfo() 395 | 396 | function packageInfo($package = null, $key = null) 397 | { 398 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { 399 | return $e; 400 | } 401 | $ret = $this->_packageInfo($package, $key); 402 | $this->_unlock(); 403 | return $ret; 404 | } 405 | 406 | // }}} 407 | // {{{ listPackages() 408 | 409 | function listPackages() 410 | { 411 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { 412 | return $e; 413 | } 414 | $ret = $this->_listPackages(); 415 | $this->_unlock(); 416 | return $ret; 417 | } 418 | 419 | // }}} 420 | // {{{ addPackage() 421 | 422 | function addPackage($package, $info) 423 | { 424 | if ($this->packageExists($package)) { 425 | return false; 426 | } 427 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { 428 | return $e; 429 | } 430 | $fp = $this->_openPackageFile($package, 'wb'); 431 | if ($fp === null) { 432 | $this->_unlock(); 433 | return false; 434 | } 435 | $info['_lastmodified'] = time(); 436 | fwrite($fp, serialize($info)); 437 | $this->_closePackageFile($fp); 438 | $this->_unlock(); 439 | return true; 440 | } 441 | 442 | // }}} 443 | // {{{ deletePackage() 444 | 445 | function deletePackage($package) 446 | { 447 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { 448 | return $e; 449 | } 450 | $file = $this->_packageFileName($package); 451 | $ret = @unlink($file); 452 | $this->rebuildFileMap(); 453 | $this->_unlock(); 454 | return $ret; 455 | } 456 | 457 | // }}} 458 | // {{{ updatePackage() 459 | 460 | function updatePackage($package, $info, $merge = true) 461 | { 462 | $oldinfo = $this->packageInfo($package); 463 | if (empty($oldinfo)) { 464 | return false; 465 | } 466 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { 467 | return $e; 468 | } 469 | $fp = $this->_openPackageFile($package, 'w'); 470 | if ($fp === null) { 471 | $this->_unlock(); 472 | return false; 473 | } 474 | $info['_lastmodified'] = time(); 475 | if ($merge) { 476 | fwrite($fp, serialize(array_merge($oldinfo, $info))); 477 | } else { 478 | fwrite($fp, serialize($info)); 479 | } 480 | $this->_closePackageFile($fp); 481 | if (isset($info['filelist'])) { 482 | $this->rebuildFileMap(); 483 | } 484 | $this->_unlock(); 485 | return true; 486 | } 487 | 488 | // }}} 489 | // {{{ checkFileMap() 490 | 491 | /** 492 | * Test whether a file belongs to a package. 493 | * 494 | * @param string $path file path, absolute or relative to the pear 495 | * install dir 496 | * 497 | * @return string which package the file belongs to, or an empty 498 | * string if the file does not belong to an installed package 499 | * 500 | * @access public 501 | */ 502 | function checkFileMap($path) 503 | { 504 | if (is_array($path)) { 505 | static $notempty; 506 | if (empty($notempty)) { 507 | $notempty = create_function('$a','return !empty($a);'); 508 | } 509 | $pkgs = array(); 510 | foreach ($path as $name => $attrs) { 511 | if (is_array($attrs) && isset($attrs['baseinstalldir'])) { 512 | $name = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; 513 | } 514 | $pkgs[$name] = $this->checkFileMap($name); 515 | } 516 | return array_filter($pkgs, $notempty); 517 | } 518 | if (empty($this->filemap_cache) && PEAR::isError($this->readFileMap())) { 519 | return $err; 520 | } 521 | if (isset($this->filemap_cache[$path])) { 522 | return $this->filemap_cache[$path]; 523 | } 524 | $l = strlen($this->install_dir); 525 | if (substr($path, 0, $l) == $this->install_dir) { 526 | $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); 527 | } 528 | if (isset($this->filemap_cache[$path])) { 529 | return $this->filemap_cache[$path]; 530 | } 531 | return ''; 532 | } 533 | 534 | // }}} 535 | 536 | } 537 | 538 | ?> 539 | -------------------------------------------------------------------------------- /inc/PEAR/Remote.php: -------------------------------------------------------------------------------- 1 | | 17 | // +----------------------------------------------------------------------+ 18 | // 19 | // $Id: Remote.php,v 1.50 2004/06/08 18:03:46 cellog Exp $ 20 | 21 | require_once 'PEAR.php'; 22 | require_once 'PEAR/Config.php'; 23 | 24 | /** 25 | * This is a class for doing remote operations against the central 26 | * PEAR database. 27 | * 28 | * @nodep XML_RPC_Value 29 | * @nodep XML_RPC_Message 30 | * @nodep XML_RPC_Client 31 | */ 32 | class PEAR_Remote extends PEAR 33 | { 34 | // {{{ properties 35 | 36 | var $config = null; 37 | var $cache = null; 38 | 39 | // }}} 40 | 41 | // {{{ PEAR_Remote(config_object) 42 | 43 | function PEAR_Remote(&$config) 44 | { 45 | $this->PEAR(); 46 | $this->config = &$config; 47 | } 48 | 49 | // }}} 50 | 51 | // {{{ getCache() 52 | 53 | 54 | function getCache($args) 55 | { 56 | $id = md5(serialize($args)); 57 | $cachedir = $this->config->get('cache_dir'); 58 | $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; 59 | if (!file_exists($filename)) { 60 | return null; 61 | }; 62 | 63 | $fp = fopen($filename, 'rb'); 64 | if (!$fp) { 65 | return null; 66 | } 67 | $content = fread($fp, filesize($filename)); 68 | fclose($fp); 69 | $result = array( 70 | 'age' => time() - filemtime($filename), 71 | 'lastChange' => filemtime($filename), 72 | 'content' => unserialize($content), 73 | ); 74 | return $result; 75 | } 76 | 77 | // }}} 78 | 79 | // {{{ saveCache() 80 | 81 | function saveCache($args, $data) 82 | { 83 | $id = md5(serialize($args)); 84 | $cachedir = $this->config->get('cache_dir'); 85 | if (!file_exists($cachedir)) { 86 | System::mkdir(array('-p', $cachedir)); 87 | } 88 | $filename = $cachedir.'/xmlrpc_cache_'.$id; 89 | 90 | $fp = @fopen($filename, "wb"); 91 | if ($fp) { 92 | fwrite($fp, serialize($data)); 93 | fclose($fp); 94 | }; 95 | } 96 | 97 | // }}} 98 | 99 | // {{{ call(method, [args...]) 100 | 101 | function call($method) 102 | { 103 | $_args = $args = func_get_args(); 104 | 105 | $this->cache = $this->getCache($args); 106 | $cachettl = $this->config->get('cache_ttl'); 107 | // If cache is newer than $cachettl seconds, we use the cache! 108 | if ($this->cache !== null && $this->cache['age'] < $cachettl) { 109 | return $this->cache['content']; 110 | }; 111 | 112 | if (extension_loaded("xmlrpc")) { 113 | $result = call_user_func_array(array(&$this, 'call_epi'), $args); 114 | if (!PEAR::isError($result)) { 115 | $this->saveCache($_args, $result); 116 | }; 117 | return $result; 118 | } 119 | if (!@include_once("XML/RPC.php")) { 120 | return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); 121 | } 122 | array_shift($args); 123 | $server_host = $this->config->get('master_server'); 124 | $username = $this->config->get('username'); 125 | $password = $this->config->get('password'); 126 | $eargs = array(); 127 | foreach($args as $arg) $eargs[] = $this->_encode($arg); 128 | $f = new XML_RPC_Message($method, $eargs); 129 | if ($this->cache !== null) { 130 | $maxAge = '?maxAge='.$this->cache['lastChange']; 131 | } else { 132 | $maxAge = ''; 133 | }; 134 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; 135 | if ($proxy = parse_url($this->config->get('http_proxy'))) { 136 | $proxy_host = @$proxy['host']; 137 | $proxy_port = @$proxy['port']; 138 | $proxy_user = @urldecode(@$proxy['user']); 139 | $proxy_pass = @urldecode(@$proxy['pass']); 140 | } 141 | $c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass); 142 | if ($username && $password) { 143 | $c->setCredentials($username, $password); 144 | } 145 | if ($this->config->get('verbose') >= 3) { 146 | $c->setDebug(1); 147 | } 148 | $r = $c->send($f); 149 | if (!$r) { 150 | return $this->raiseError("XML_RPC send failed"); 151 | } 152 | $v = $r->value(); 153 | if ($e = $r->faultCode()) { 154 | if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { 155 | return $this->cache['content']; 156 | } 157 | return $this->raiseError($r->faultString(), $e); 158 | } 159 | 160 | $result = XML_RPC_decode($v); 161 | $this->saveCache($_args, $result); 162 | return $result; 163 | } 164 | 165 | // }}} 166 | 167 | // {{{ call_epi(method, [args...]) 168 | 169 | function call_epi($method) 170 | { 171 | do { 172 | if (extension_loaded("xmlrpc")) { 173 | break; 174 | } 175 | if (OS_WINDOWS) { 176 | $ext = 'dll'; 177 | } elseif (PHP_OS == 'HP-UX') { 178 | $ext = 'sl'; 179 | } elseif (PHP_OS == 'AIX') { 180 | $ext = 'a'; 181 | } else { 182 | $ext = 'so'; 183 | } 184 | $ext = OS_WINDOWS ? 'dll' : 'so'; 185 | @dl("xmlrpc-epi.$ext"); 186 | if (extension_loaded("xmlrpc")) { 187 | break; 188 | } 189 | @dl("xmlrpc.$ext"); 190 | if (extension_loaded("xmlrpc")) { 191 | break; 192 | } 193 | return $this->raiseError("unable to load xmlrpc extension"); 194 | } while (false); 195 | $params = func_get_args(); 196 | array_shift($params); 197 | $method = str_replace("_", ".", $method); 198 | $request = xmlrpc_encode_request($method, $params); 199 | $server_host = $this->config->get("master_server"); 200 | if (empty($server_host)) { 201 | return $this->raiseError("PEAR_Remote::call: no master_server configured"); 202 | } 203 | $server_port = 80; 204 | if ($http_proxy = $this->config->get('http_proxy')) { 205 | $proxy = parse_url($http_proxy); 206 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; 207 | $proxy_host = @$proxy['host']; 208 | $proxy_port = @$proxy['port']; 209 | $proxy_user = @urldecode(@$proxy['user']); 210 | $proxy_pass = @urldecode(@$proxy['pass']); 211 | $fp = @fsockopen($proxy_host, $proxy_port); 212 | $use_proxy = true; 213 | } else { 214 | $use_proxy = false; 215 | $fp = @fsockopen($server_host, $server_port); 216 | } 217 | if (!$fp && $http_proxy) { 218 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); 219 | } elseif (!$fp) { 220 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); 221 | } 222 | $len = strlen($request); 223 | $req_headers = "Host: $server_host:$server_port\r\n" . 224 | "Content-type: text/xml\r\n" . 225 | "Content-length: $len\r\n"; 226 | $username = $this->config->get('username'); 227 | $password = $this->config->get('password'); 228 | if ($username && $password) { 229 | $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; 230 | $tmp = base64_encode("$username:$password"); 231 | $req_headers .= "Authorization: Basic $tmp\r\n"; 232 | } 233 | if ($this->cache !== null) { 234 | $maxAge = '?maxAge='.$this->cache['lastChange']; 235 | } else { 236 | $maxAge = ''; 237 | }; 238 | 239 | if ($use_proxy && $proxy_host != '' && $proxy_user != '') { 240 | $req_headers .= 'Proxy-Authorization: Basic ' 241 | .base64_encode($proxy_user.':'.$proxy_pass) 242 | ."\r\n"; 243 | } 244 | 245 | if ($this->config->get('verbose') > 3) { 246 | print "XMLRPC REQUEST HEADERS:\n"; 247 | var_dump($req_headers); 248 | print "XMLRPC REQUEST BODY:\n"; 249 | var_dump($request); 250 | } 251 | 252 | if ($use_proxy && $proxy_host != '') { 253 | $post_string = "POST http://".$server_host; 254 | if ($proxy_port > '') { 255 | $post_string .= ':'.$server_port; 256 | } 257 | } else { 258 | $post_string = "POST "; 259 | } 260 | 261 | fwrite($fp, ($post_string."/xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); 262 | $response = ''; 263 | $line1 = fgets($fp, 2048); 264 | if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { 265 | return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); 266 | } 267 | switch ($matches[1]) { 268 | case "200": // OK 269 | break; 270 | case "304": // Not Modified 271 | return $this->cache['content']; 272 | case "401": // Unauthorized 273 | if ($username && $password) { 274 | return $this->raiseError("PEAR_Remote: authorization failed", 401); 275 | } else { 276 | return $this->raiseError("PEAR_Remote: authorization required, please log in first", 401); 277 | } 278 | default: 279 | return $this->raiseError("PEAR_Remote: unexpected HTTP response", (int)$matches[1], null, null, "$matches[1] $matches[2]"); 280 | } 281 | while (trim(fgets($fp, 2048)) != ''); // skip rest of headers 282 | while ($chunk = fread($fp, 10240)) { 283 | $response .= $chunk; 284 | } 285 | fclose($fp); 286 | if ($this->config->get('verbose') > 3) { 287 | print "XMLRPC RESPONSE:\n"; 288 | var_dump($response); 289 | } 290 | $ret = xmlrpc_decode($response); 291 | if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { 292 | if ($ret['__PEAR_TYPE__'] == 'error') { 293 | if (isset($ret['__PEAR_CLASS__'])) { 294 | $class = $ret['__PEAR_CLASS__']; 295 | } else { 296 | $class = "PEAR_Error"; 297 | } 298 | if ($ret['code'] === '') $ret['code'] = null; 299 | if ($ret['message'] === '') $ret['message'] = null; 300 | if ($ret['userinfo'] === '') $ret['userinfo'] = null; 301 | if (strtolower($class) == 'db_error') { 302 | $ret = $this->raiseError(PEAR::errorMessage($ret['code']), 303 | $ret['code'], null, null, 304 | $ret['userinfo']); 305 | } else { 306 | $ret = $this->raiseError($ret['message'], $ret['code'], 307 | null, null, $ret['userinfo']); 308 | } 309 | } 310 | } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) 311 | && is_array($ret[0]) && 312 | !empty($ret[0]['faultString']) && 313 | !empty($ret[0]['faultCode'])) { 314 | extract($ret[0]); 315 | $faultString = "XML-RPC Server Fault: " . 316 | str_replace("\n", " ", $faultString); 317 | return $this->raiseError($faultString, $faultCode); 318 | } 319 | return $ret; 320 | } 321 | 322 | // }}} 323 | 324 | // {{{ _encode 325 | 326 | // a slightly extended version of XML_RPC_encode 327 | function _encode($php_val) 328 | { 329 | global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; 330 | global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; 331 | 332 | $type = gettype($php_val); 333 | $xmlrpcval = new XML_RPC_Value; 334 | 335 | switch($type) { 336 | case "array": 337 | reset($php_val); 338 | $firstkey = key($php_val); 339 | end($php_val); 340 | $lastkey = key($php_val); 341 | if ($firstkey === 0 && is_int($lastkey) && 342 | ($lastkey + 1) == count($php_val)) { 343 | $is_continuous = true; 344 | reset($php_val); 345 | $size = count($php_val); 346 | for ($expect = 0; $expect < $size; $expect++, next($php_val)) { 347 | if (key($php_val) !== $expect) { 348 | $is_continuous = false; 349 | break; 350 | } 351 | } 352 | if ($is_continuous) { 353 | reset($php_val); 354 | $arr = array(); 355 | while (list($k, $v) = each($php_val)) { 356 | $arr[$k] = $this->_encode($v); 357 | } 358 | $xmlrpcval->addArray($arr); 359 | break; 360 | } 361 | } 362 | // fall though if not numerical and continuous 363 | case "object": 364 | $arr = array(); 365 | while (list($k, $v) = each($php_val)) { 366 | $arr[$k] = $this->_encode($v); 367 | } 368 | $xmlrpcval->addStruct($arr); 369 | break; 370 | case "integer": 371 | $xmlrpcval->addScalar($php_val, $XML_RPC_Int); 372 | break; 373 | case "double": 374 | $xmlrpcval->addScalar($php_val, $XML_RPC_Double); 375 | break; 376 | case "string": 377 | case "NULL": 378 | $xmlrpcval->addScalar($php_val, $XML_RPC_String); 379 | break; 380 | case "boolean": 381 | $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); 382 | break; 383 | case "unknown type": 384 | default: 385 | return null; 386 | } 387 | return $xmlrpcval; 388 | } 389 | 390 | // }}} 391 | 392 | } 393 | 394 | ?> 395 | -------------------------------------------------------------------------------- /inc/PEAR/RunTest.php: -------------------------------------------------------------------------------- 1 | | 17 | // | Greg Beaver | 18 | // | | 19 | // +----------------------------------------------------------------------+ 20 | // 21 | // $Id: RunTest.php,v 1.3.2.4 2005/02/17 17:47:55 cellog Exp $ 22 | // 23 | 24 | /** 25 | * Simplified version of PHP's test suite 26 | * -- EXPERIMENTAL -- 27 | 28 | Try it with: 29 | 30 | $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);' 31 | 32 | 33 | TODO: 34 | 35 | Actually finish the development and testing 36 | 37 | */ 38 | 39 | require_once 'PEAR.php'; 40 | require_once 'PEAR/Config.php'; 41 | 42 | define('DETAILED', 1); 43 | putenv("PHP_PEAR_RUNTESTS=1"); 44 | 45 | class PEAR_RunTest 46 | { 47 | var $_logger; 48 | 49 | /** 50 | * An object that supports the PEAR_Common->log() signature, or null 51 | * @param PEAR_Common|null 52 | */ 53 | function PEAR_RunTest($logger = null) 54 | { 55 | $this->_logger = $logger; 56 | } 57 | 58 | // 59 | // Run an individual test case. 60 | // 61 | 62 | function run($file, $ini_settings = '') 63 | { 64 | $cwd = getcwd(); 65 | $conf = &PEAR_Config::singleton(); 66 | $php = $conf->get('php_bin'); 67 | //var_dump($php);exit; 68 | global $log_format, $info_params, $ini_overwrites; 69 | 70 | $info_params = ''; 71 | $log_format = 'LEOD'; 72 | 73 | // Load the sections of the test file. 74 | $section_text = array( 75 | 'TEST' => '(unnamed test)', 76 | 'SKIPIF' => '', 77 | 'GET' => '', 78 | 'ARGS' => '', 79 | ); 80 | 81 | if (!is_file($file) || !$fp = fopen($file, "r")) { 82 | return PEAR::raiseError("Cannot open test file: $file"); 83 | } 84 | 85 | $section = ''; 86 | while (!feof($fp)) { 87 | $line = fgets($fp); 88 | 89 | // Match the beginning of a section. 90 | if (ereg('^--([A-Z]+)--',$line,$r)) { 91 | $section = $r[1]; 92 | $section_text[$section] = ''; 93 | continue; 94 | } 95 | 96 | // Add to the section text. 97 | $section_text[$section] .= $line; 98 | } 99 | fclose($fp); 100 | 101 | $shortname = str_replace($cwd.'/', '', $file); 102 | $tested = trim($section_text['TEST'])." [$shortname]"; 103 | 104 | $tmp = realpath(dirname($file)); 105 | $tmp_skipif = $tmp . uniqid('/phpt.'); 106 | $tmp_file = ereg_replace('\.phpt$','.php',$file); 107 | $tmp_post = $tmp . uniqid('/phpt.'); 108 | 109 | @unlink($tmp_skipif); 110 | @unlink($tmp_file); 111 | @unlink($tmp_post); 112 | 113 | // unlink old test results 114 | @unlink(ereg_replace('\.phpt$','.diff',$file)); 115 | @unlink(ereg_replace('\.phpt$','.log',$file)); 116 | @unlink(ereg_replace('\.phpt$','.exp',$file)); 117 | @unlink(ereg_replace('\.phpt$','.out',$file)); 118 | 119 | // Check if test should be skipped. 120 | $info = ''; 121 | $warn = false; 122 | if (array_key_exists('SKIPIF', $section_text)) { 123 | if (trim($section_text['SKIPIF'])) { 124 | $this->save_text($tmp_skipif, $section_text['SKIPIF']); 125 | //$extra = substr(PHP_OS, 0, 3) !== "WIN" ? 126 | // "unset REQUEST_METHOD;": ""; 127 | 128 | //$output = `$extra $php $info_params -f $tmp_skipif`; 129 | $output = `$php $info_params -f $tmp_skipif`; 130 | unlink($tmp_skipif); 131 | if (eregi("^skip", trim($output))) { 132 | $skipreason = "SKIP $tested"; 133 | $reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; 134 | if ($reason) { 135 | $skipreason .= " (reason: $reason)"; 136 | } 137 | $this->_logger->log(0, $skipreason); 138 | if (isset($old_php)) { 139 | $php = $old_php; 140 | } 141 | return 'SKIPPED'; 142 | } 143 | if (eregi("^info", trim($output))) { 144 | $reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; 145 | if ($reason) { 146 | $info = " (info: $reason)"; 147 | } 148 | } 149 | if (eregi("^warn", trim($output))) { 150 | $reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE; 151 | if ($reason) { 152 | $warn = true; /* only if there is a reason */ 153 | $info = " (warn: $reason)"; 154 | } 155 | } 156 | } 157 | } 158 | 159 | // We've satisfied the preconditions - run the test! 160 | $this->save_text($tmp_file,$section_text['FILE']); 161 | 162 | $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : ''; 163 | 164 | $cmd = "$php$ini_settings -f $tmp_file$args 2>&1"; 165 | if (isset($this->_logger)) { 166 | $this->_logger->log(2, 'Running command "' . $cmd . '"'); 167 | } 168 | 169 | $savedir = getcwd(); // in case the test moves us around 170 | if (isset($section_text['RETURNS'])) { 171 | ob_start(); 172 | system($cmd, $return_value); 173 | $out = ob_get_contents(); 174 | ob_end_clean(); 175 | @unlink($tmp_post); 176 | $section_text['RETURNS'] = (int) trim($section_text['RETURNS']); 177 | $returnfail = ($return_value != $section_text['RETURNS']); 178 | } else { 179 | $out = `$cmd`; 180 | $returnfail = false; 181 | } 182 | chdir($savedir); 183 | // Does the output match what is expected? 184 | $output = trim($out); 185 | $output = preg_replace('/\r\n/', "\n", $output); 186 | 187 | if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) { 188 | if (isset($section_text['EXPECTF'])) { 189 | $wanted = trim($section_text['EXPECTF']); 190 | } else { 191 | $wanted = trim($section_text['EXPECTREGEX']); 192 | } 193 | $wanted_re = preg_replace('/\r\n/',"\n",$wanted); 194 | if (isset($section_text['EXPECTF'])) { 195 | $wanted_re = preg_quote($wanted_re, '/'); 196 | // Stick to basics 197 | $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy 198 | $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re); 199 | $wanted_re = str_replace("%d", "[0-9]+", $wanted_re); 200 | $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re); 201 | $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re); 202 | $wanted_re = str_replace("%c", ".", $wanted_re); 203 | // %f allows two points "-.0.0" but that is the best *simple* expression 204 | } 205 | /* DEBUG YOUR REGEX HERE 206 | var_dump($wanted_re); 207 | print(str_repeat('=', 80) . "\n"); 208 | var_dump($output); 209 | */ 210 | if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) { 211 | @unlink($tmp_file); 212 | $this->_logger->log(0, "PASS $tested$info"); 213 | if (isset($old_php)) { 214 | $php = $old_php; 215 | } 216 | return 'PASSED'; 217 | } 218 | 219 | } else { 220 | $wanted = trim($section_text['EXPECT']); 221 | $wanted = preg_replace('/\r\n/',"\n",$wanted); 222 | // compare and leave on success 223 | $ok = (0 == strcmp($output,$wanted)); 224 | if (!$returnfail && $ok) { 225 | @unlink($tmp_file); 226 | $this->_logger->log(0, "PASS $tested$info"); 227 | if (isset($old_php)) { 228 | $php = $old_php; 229 | } 230 | return 'PASSED'; 231 | } 232 | } 233 | 234 | // Test failed so we need to report details. 235 | if ($warn) { 236 | $this->_logger->log(0, "WARN $tested$info"); 237 | } else { 238 | $this->_logger->log(0, "FAIL $tested$info"); 239 | } 240 | 241 | if (isset($section_text['RETURNS'])) { 242 | $GLOBALS['__PHP_FAILED_TESTS__'][] = array( 243 | 'name' => $file, 244 | 'test_name' => $tested, 245 | 'output' => ereg_replace('\.phpt$','.log', $file), 246 | 'diff' => ereg_replace('\.phpt$','.diff', $file), 247 | 'info' => $info, 248 | 'return' => $return_value 249 | ); 250 | } else { 251 | $GLOBALS['__PHP_FAILED_TESTS__'][] = array( 252 | 'name' => $file, 253 | 'test_name' => $tested, 254 | 'output' => ereg_replace('\.phpt$','.log', $file), 255 | 'diff' => ereg_replace('\.phpt$','.diff', $file), 256 | 'info' => $info, 257 | ); 258 | } 259 | 260 | // write .exp 261 | if (strpos($log_format,'E') !== FALSE) { 262 | $logname = ereg_replace('\.phpt$','.exp',$file); 263 | if (!$log = fopen($logname,'w')) { 264 | return PEAR::raiseError("Cannot create test log - $logname"); 265 | } 266 | fwrite($log,$wanted); 267 | fclose($log); 268 | } 269 | 270 | // write .out 271 | if (strpos($log_format,'O') !== FALSE) { 272 | $logname = ereg_replace('\.phpt$','.out',$file); 273 | if (!$log = fopen($logname,'w')) { 274 | return PEAR::raiseError("Cannot create test log - $logname"); 275 | } 276 | fwrite($log,$output); 277 | fclose($log); 278 | } 279 | 280 | // write .diff 281 | if (strpos($log_format,'D') !== FALSE) { 282 | $logname = ereg_replace('\.phpt$','.diff',$file); 283 | if (!$log = fopen($logname,'w')) { 284 | return PEAR::raiseError("Cannot create test log - $logname"); 285 | } 286 | fwrite($log, $this->generate_diff($wanted, $output, 287 | isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']), 288 | $return_value) : null)); 289 | fclose($log); 290 | } 291 | 292 | // write .log 293 | if (strpos($log_format,'L') !== FALSE) { 294 | $logname = ereg_replace('\.phpt$','.log',$file); 295 | if (!$log = fopen($logname,'w')) { 296 | return PEAR::raiseError("Cannot create test log - $logname"); 297 | } 298 | fwrite($log," 299 | ---- EXPECTED OUTPUT 300 | $wanted 301 | ---- ACTUAL OUTPUT 302 | $output 303 | ---- FAILED 304 | "); 305 | if ($returnfail) { 306 | fwrite($log," 307 | ---- EXPECTED RETURN 308 | $section_text[RETURNS] 309 | ---- ACTUAL RETURN 310 | $return_value 311 | "); 312 | } 313 | fclose($log); 314 | //error_report($file,$logname,$tested); 315 | } 316 | 317 | if (isset($old_php)) { 318 | $php = $old_php; 319 | } 320 | 321 | return $warn ? 'WARNED' : 'FAILED'; 322 | } 323 | 324 | function generate_diff($wanted, $output, $return_value) 325 | { 326 | $w = explode("\n", $wanted); 327 | $o = explode("\n", $output); 328 | $w1 = array_diff_assoc($w,$o); 329 | $o1 = array_diff_assoc($o,$w); 330 | $w2 = array(); 331 | $o2 = array(); 332 | foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val; 333 | foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val; 334 | $diff = array_merge($w2, $o2); 335 | ksort($diff); 336 | if ($return_value) { 337 | $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]"; 338 | } else { 339 | $extra = ''; 340 | } 341 | return implode("\r\n", $diff) . $extra; 342 | } 343 | 344 | // 345 | // Write the given text to a temporary file, and return the filename. 346 | // 347 | 348 | function save_text($filename, $text) 349 | { 350 | if (!$fp = fopen($filename, 'w')) { 351 | return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)"); 352 | } 353 | fwrite($fp,$text); 354 | fclose($fp); 355 | if (1 < DETAILED) echo " 356 | FILE $filename {{{ 357 | $text 358 | }}} 359 | "; 360 | } 361 | 362 | } 363 | ?> -------------------------------------------------------------------------------- /inc/System.php: -------------------------------------------------------------------------------- 1 | | 17 | // +----------------------------------------------------------------------+ 18 | // 19 | // $Id: System.php,v 1.36 2004/06/15 16:33:46 pajoye Exp $ 20 | // 21 | 22 | require_once 'PEAR.php'; 23 | //require_once 'Console/Getopt.php'; 24 | 25 | $GLOBALS['_System_temp_files'] = array(); 26 | 27 | /** 28 | * System offers cross plattform compatible system functions 29 | * 30 | * Static functions for different operations. Should work under 31 | * Unix and Windows. The names and usage has been taken from its respectively 32 | * GNU commands. The functions will return (bool) false on error and will 33 | * trigger the error with the PHP trigger_error() function (you can silence 34 | * the error by prefixing a '@' sign after the function call). 35 | * 36 | * Documentation on this class you can find in: 37 | * http://pear.php.net/manual/ 38 | * 39 | * Example usage: 40 | * if (!@System::rm('-r file1 dir1')) { 41 | * print "could not delete file1 or dir1"; 42 | * } 43 | * 44 | * In case you need to to pass file names with spaces, 45 | * pass the params as an array: 46 | * 47 | * System::rm(array('-r', $file1, $dir1)); 48 | * 49 | * @package System 50 | * @author Tomas V.V.Cox 51 | * @version $Revision: 1.36 $ 52 | * @access public 53 | * @see http://pear.php.net/manual/ 54 | */ 55 | class System 56 | { 57 | /** 58 | * returns the commandline arguments of a function 59 | * 60 | * @param string $argv the commandline 61 | * @param string $short_options the allowed option short-tags 62 | * @param string $long_options the allowed option long-tags 63 | * @return array the given options and there values 64 | * @access private 65 | */ 66 | function _parseArgs($argv, $short_options, $long_options = null) 67 | { 68 | if (!is_array($argv) && $argv !== null) { 69 | $argv = preg_split('/\s+/', $argv); 70 | } 71 | return Console_Getopt::getopt2($argv, $short_options); 72 | } 73 | 74 | /** 75 | * Output errors with PHP trigger_error(). You can silence the errors 76 | * with prefixing a "@" sign to the function call: @System::mkdir(..); 77 | * 78 | * @param mixed $error a PEAR error or a string with the error message 79 | * @return bool false 80 | * @access private 81 | */ 82 | function raiseError($error) 83 | { 84 | if (PEAR::isError($error)) { 85 | $error = $error->getMessage(); 86 | } 87 | trigger_error($error, E_USER_WARNING); 88 | return false; 89 | } 90 | 91 | /** 92 | * Creates a nested array representing the structure of a directory 93 | * 94 | * System::_dirToStruct('dir1', 0) => 95 | * Array 96 | * ( 97 | * [dirs] => Array 98 | * ( 99 | * [0] => dir1 100 | * ) 101 | * 102 | * [files] => Array 103 | * ( 104 | * [0] => dir1/file2 105 | * [1] => dir1/file3 106 | * ) 107 | * ) 108 | * @param string $sPath Name of the directory 109 | * @param integer $maxinst max. deep of the lookup 110 | * @param integer $aktinst starting deep of the lookup 111 | * @return array the structure of the dir 112 | * @access private 113 | */ 114 | 115 | function _dirToStruct($sPath, $maxinst, $aktinst = 0) 116 | { 117 | $struct = array('dirs' => array(), 'files' => array()); 118 | if (($dir = @opendir($sPath)) === false) { 119 | System::raiseError("Could not open dir $sPath"); 120 | return $struct; // XXX could not open error 121 | } 122 | $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ? 123 | $list = array(); 124 | while ($file = readdir($dir)) { 125 | if ($file != '.' && $file != '..') { 126 | $list[] = $file; 127 | } 128 | } 129 | closedir($dir); 130 | sort($list); 131 | if ($aktinst < $maxinst || $maxinst == 0) { 132 | foreach($list as $val) { 133 | $path = $sPath . DIRECTORY_SEPARATOR . $val; 134 | if (is_dir($path)) { 135 | $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1); 136 | $struct = array_merge_recursive($tmp, $struct); 137 | } else { 138 | $struct['files'][] = $path; 139 | } 140 | } 141 | } 142 | return $struct; 143 | } 144 | 145 | /** 146 | * Creates a nested array representing the structure of a directory and files 147 | * 148 | * @param array $files Array listing files and dirs 149 | * @return array 150 | * @see System::_dirToStruct() 151 | */ 152 | function _multipleToStruct($files) 153 | { 154 | $struct = array('dirs' => array(), 'files' => array()); 155 | settype($files, 'array'); 156 | foreach ($files as $file) { 157 | if (is_dir($file)) { 158 | $tmp = System::_dirToStruct($file, 0); 159 | $struct = array_merge_recursive($tmp, $struct); 160 | } else { 161 | $struct['files'][] = $file; 162 | } 163 | } 164 | return $struct; 165 | } 166 | 167 | /** 168 | * The rm command for removing files. 169 | * Supports multiple files and dirs and also recursive deletes 170 | * 171 | * @param string $args the arguments for rm 172 | * @return mixed PEAR_Error or true for success 173 | * @access public 174 | */ 175 | function rm($args) 176 | { 177 | $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-) 178 | if (PEAR::isError($opts)) { 179 | return System::raiseError($opts); 180 | } 181 | foreach($opts[0] as $opt) { 182 | if ($opt[0] == 'r') { 183 | $do_recursive = true; 184 | } 185 | } 186 | $ret = true; 187 | if (isset($do_recursive)) { 188 | $struct = System::_multipleToStruct($opts[1]); 189 | foreach($struct['files'] as $file) { 190 | if (!@unlink($file)) { 191 | $ret = false; 192 | } 193 | } 194 | foreach($struct['dirs'] as $dir) { 195 | if (!@rmdir($dir)) { 196 | $ret = false; 197 | } 198 | } 199 | } else { 200 | foreach ($opts[1] as $file) { 201 | $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; 202 | if (!@$delete($file)) { 203 | $ret = false; 204 | } 205 | } 206 | } 207 | return $ret; 208 | } 209 | 210 | /** 211 | * Make directories. Note that we use call_user_func('mkdir') to avoid 212 | * a problem with ZE2 calling System::mkDir instead of the native PHP func. 213 | * 214 | * @param string $args the name of the director(y|ies) to create 215 | * @return bool True for success 216 | * @access public 217 | */ 218 | function mkDir($args) 219 | { 220 | $opts = System::_parseArgs($args, 'pm:'); 221 | if (PEAR::isError($opts)) { 222 | return System::raiseError($opts); 223 | } 224 | $mode = 0777; // default mode 225 | foreach($opts[0] as $opt) { 226 | if ($opt[0] == 'p') { 227 | $create_parents = true; 228 | } elseif($opt[0] == 'm') { 229 | // if the mode is clearly an octal number (starts with 0) 230 | // convert it to decimal 231 | if (strlen($opt[1]) && $opt[1]{0} == '0') { 232 | $opt[1] = octdec($opt[1]); 233 | } else { 234 | // convert to int 235 | $opt[1] += 0; 236 | } 237 | $mode = $opt[1]; 238 | } 239 | } 240 | $ret = true; 241 | if (isset($create_parents)) { 242 | foreach($opts[1] as $dir) { 243 | $dirstack = array(); 244 | while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { 245 | array_unshift($dirstack, $dir); 246 | $dir = dirname($dir); 247 | } 248 | while ($newdir = array_shift($dirstack)) { 249 | if (!call_user_func('mkdir', $newdir, $mode)) { 250 | $ret = false; 251 | } 252 | } 253 | } 254 | } else { 255 | foreach($opts[1] as $dir) { 256 | if (!@is_dir($dir) && !call_user_func('mkdir', $dir, $mode)) { 257 | $ret = false; 258 | } 259 | } 260 | } 261 | return $ret; 262 | } 263 | 264 | /** 265 | * Concatenate files 266 | * 267 | * Usage: 268 | * 1) $var = System::cat('sample.txt test.txt'); 269 | * 2) System::cat('sample.txt test.txt > final.txt'); 270 | * 3) System::cat('sample.txt test.txt >> final.txt'); 271 | * 272 | * Note: as the class use fopen, urls should work also (test that) 273 | * 274 | * @param string $args the arguments 275 | * @return boolean true on success 276 | * @access public 277 | */ 278 | function &cat($args) 279 | { 280 | $ret = null; 281 | $files = array(); 282 | if (!is_array($args)) { 283 | $args = preg_split('/\s+/', $args); 284 | } 285 | for($i=0; $i < count($args); $i++) { 286 | if ($args[$i] == '>') { 287 | $mode = 'wb'; 288 | $outputfile = $args[$i+1]; 289 | break; 290 | } elseif ($args[$i] == '>>') { 291 | $mode = 'ab+'; 292 | $outputfile = $args[$i+1]; 293 | break; 294 | } else { 295 | $files[] = $args[$i]; 296 | } 297 | } 298 | if (isset($mode)) { 299 | if (!$outputfd = fopen($outputfile, $mode)) { 300 | $err = System::raiseError("Could not open $outputfile"); 301 | return $err; 302 | } 303 | $ret = true; 304 | } 305 | foreach ($files as $file) { 306 | if (!$fd = fopen($file, 'r')) { 307 | System::raiseError("Could not open $file"); 308 | continue; 309 | } 310 | while ($cont = fread($fd, 2048)) { 311 | if (isset($outputfd)) { 312 | fwrite($outputfd, $cont); 313 | } else { 314 | $ret .= $cont; 315 | } 316 | } 317 | fclose($fd); 318 | } 319 | if (@is_resource($outputfd)) { 320 | fclose($outputfd); 321 | } 322 | return $ret; 323 | } 324 | 325 | /** 326 | * Creates temporary files or directories. This function will remove 327 | * the created files when the scripts finish its execution. 328 | * 329 | * Usage: 330 | * 1) $tempfile = System::mktemp("prefix"); 331 | * 2) $tempdir = System::mktemp("-d prefix"); 332 | * 3) $tempfile = System::mktemp(); 333 | * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); 334 | * 335 | * prefix -> The string that will be prepended to the temp name 336 | * (defaults to "tmp"). 337 | * -d -> A temporary dir will be created instead of a file. 338 | * -t -> The target dir where the temporary (file|dir) will be created. If 339 | * this param is missing by default the env vars TMP on Windows or 340 | * TMPDIR in Unix will be used. If these vars are also missing 341 | * c:\windows\temp or /tmp will be used. 342 | * 343 | * @param string $args The arguments 344 | * @return mixed the full path of the created (file|dir) or false 345 | * @see System::tmpdir() 346 | * @access public 347 | */ 348 | function mktemp($args = null) 349 | { 350 | static $first_time = true; 351 | $opts = System::_parseArgs($args, 't:d'); 352 | if (PEAR::isError($opts)) { 353 | return System::raiseError($opts); 354 | } 355 | foreach($opts[0] as $opt) { 356 | if($opt[0] == 'd') { 357 | $tmp_is_dir = true; 358 | } elseif($opt[0] == 't') { 359 | $tmpdir = $opt[1]; 360 | } 361 | } 362 | $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; 363 | if (!isset($tmpdir)) { 364 | $tmpdir = System::tmpdir(); 365 | } 366 | if (!System::mkDir("-p $tmpdir")) { 367 | return false; 368 | } 369 | $tmp = tempnam($tmpdir, $prefix); 370 | if (isset($tmp_is_dir)) { 371 | unlink($tmp); // be careful possible race condition here 372 | if (!call_user_func('mkdir', $tmp, 0700)) { 373 | return System::raiseError("Unable to create temporary directory $tmpdir"); 374 | } 375 | } 376 | $GLOBALS['_System_temp_files'][] = $tmp; 377 | if ($first_time) { 378 | PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); 379 | $first_time = false; 380 | } 381 | return $tmp; 382 | } 383 | 384 | /** 385 | * Remove temporary files created my mkTemp. This function is executed 386 | * at script shutdown time 387 | * 388 | * @access private 389 | */ 390 | function _removeTmpFiles() 391 | { 392 | if (count($GLOBALS['_System_temp_files'])) { 393 | $delete = $GLOBALS['_System_temp_files']; 394 | array_unshift($delete, '-r'); 395 | System::rm($delete); 396 | } 397 | } 398 | 399 | /** 400 | * Get the path of the temporal directory set in the system 401 | * by looking in its environments variables. 402 | * Note: php.ini-recommended removes the "E" from the variables_order setting, 403 | * making unavaible the $_ENV array, that s why we do tests with _ENV 404 | * 405 | * @return string The temporal directory on the system 406 | */ 407 | function tmpdir() 408 | { 409 | if (OS_WINDOWS) { 410 | if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { 411 | return $var; 412 | } 413 | if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { 414 | return $var; 415 | } 416 | if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { 417 | return $var; 418 | } 419 | return getenv('SystemRoot') . '\temp'; 420 | } 421 | if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { 422 | return $var; 423 | } 424 | return '/tmp'; 425 | } 426 | 427 | /** 428 | * The "which" command (show the full path of a command) 429 | * 430 | * @param string $program The command to search for 431 | * @return mixed A string with the full path or false if not found 432 | * @author Stig Bakken 433 | */ 434 | function which($program, $fallback = false) 435 | { 436 | // is_executable() is not available on windows 437 | if (OS_WINDOWS) { 438 | $pear_is_executable = 'is_file'; 439 | } else { 440 | $pear_is_executable = 'is_executable'; 441 | } 442 | 443 | // full path given 444 | if (basename($program) != $program) { 445 | return (@$pear_is_executable($program)) ? $program : $fallback; 446 | } 447 | 448 | // XXX FIXME honor safe mode 449 | $path_delim = OS_WINDOWS ? ';' : ':'; 450 | $exe_suffixes = OS_WINDOWS ? array('.exe','.bat','.cmd','.com') : array(''); 451 | $path_elements = explode($path_delim, getenv('PATH')); 452 | foreach ($exe_suffixes as $suff) { 453 | foreach ($path_elements as $dir) { 454 | $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; 455 | if (@is_file($file) && @$pear_is_executable($file)) { 456 | return $file; 457 | } 458 | } 459 | } 460 | return $fallback; 461 | } 462 | 463 | /** 464 | * The "find" command 465 | * 466 | * Usage: 467 | * 468 | * System::find($dir); 469 | * System::find("$dir -type d"); 470 | * System::find("$dir -type f"); 471 | * System::find("$dir -name *.php"); 472 | * System::find("$dir -name *.php -name *.htm*"); 473 | * System::find("$dir -maxdepth 1"); 474 | * 475 | * Params implmented: 476 | * $dir -> Start the search at this directory 477 | * -type d -> return only directories 478 | * -type f -> return only files 479 | * -maxdepth -> max depth of recursion 480 | * -name -> search pattern (bash style). Multiple -name param allowed 481 | * 482 | * @param mixed Either array or string with the command line 483 | * @return array Array of found files 484 | * 485 | */ 486 | function find($args) 487 | { 488 | if (!is_array($args)) { 489 | $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); 490 | } 491 | $dir = array_shift($args); 492 | $patterns = array(); 493 | $depth = 0; 494 | $do_files = $do_dirs = true; 495 | for ($i = 0; $i < count($args); $i++) { 496 | switch ($args[$i]) { 497 | case '-type': 498 | if (in_array($args[$i+1], array('d', 'f'))) { 499 | if ($args[$i+1] == 'd') { 500 | $do_files = false; 501 | } else { 502 | $do_dirs = false; 503 | } 504 | } 505 | $i++; 506 | break; 507 | case '-name': 508 | $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), 509 | array('\.', '.*'), 510 | $args[$i+1]) 511 | . ")"; 512 | $i++; 513 | break; 514 | case '-maxdepth': 515 | $depth = $args[$i+1]; 516 | break; 517 | } 518 | } 519 | $path = System::_dirToStruct($dir, $depth); 520 | if ($do_files && $do_dirs) { 521 | $files = array_merge($path['files'], $path['dirs']); 522 | } elseif ($do_dirs) { 523 | $files = $path['dirs']; 524 | } else { 525 | $files = $path['files']; 526 | } 527 | if (count($patterns)) { 528 | $patterns = implode('|', $patterns); 529 | $ret = array(); 530 | for ($i = 0; $i < count($files); $i++) { 531 | if (preg_match("#^$patterns\$#", $files[$i])) { 532 | $ret[] = $files[$i]; 533 | } 534 | } 535 | return $ret; 536 | } 537 | return $files; 538 | } 539 | } 540 | ?> 541 | -------------------------------------------------------------------------------- /inc/header.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | phpZoteroWebDAV 6 | 7 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /inc/include.php: -------------------------------------------------------------------------------- 1 | 0) { 60 | echo($e); 61 | return($e); 62 | } else { 63 | if($i>1) { 64 | return($outpath); 65 | } else { 66 | return($outpath . "/" . $zname); 67 | } 68 | } 69 | } 70 | 71 | // recursively remove directory (ie. directory and any file and subdirectory contents) 72 | function rmdirr($dir) { 73 | if (is_dir($dir)) { 74 | $objects = scandir($dir); 75 | foreach ($objects as $object) { 76 | if ($object != "." && $object != "..") { 77 | if (filetype($dir."/".$object) == "dir") rmdirr($dir."/".$object); else unlink($dir."/".$object); 78 | } 79 | } 80 | reset($objects); 81 | rmdir($dir); 82 | } 83 | } 84 | 85 | // recursively create a directory (i.e. creates any parent tree if not existing) 86 | function mkdirr($pn,$mode=null) { 87 | 88 | if(is_dir($pn)||empty($pn)) return true; 89 | $pn=str_replace(array('/', ''),DIRECTORY_SEPARATOR,$pn); 90 | 91 | if(is_file($pn)) {trigger_error('mkdirr() File exists', E_USER_WARNING);return false;} 92 | 93 | $next_pathname=substr($pn,0,strrpos($pn,DIRECTORY_SEPARATOR)); 94 | if(mkdirr($next_pathname,$mode)) {if(!file_exists($pn)) {return mkdir($pn,$mode);} } 95 | return false; 96 | } 97 | 98 | function findwebfile($path) { 99 | $filename = ""; 100 | if (is_dir($path)) { 101 | $objects = scandir($path); 102 | foreach ($objects as $object) { 103 | if(substr($object,-5)==".html") { 104 | if ($filename!="") { 105 | if(substr($filename,-7,1)=="_") $filename = $object; 106 | } else { 107 | $filename = $object; 108 | } 109 | } 110 | } 111 | reset($objects); 112 | } 113 | return $filename; 114 | } 115 | 116 | function foldersize($path) { 117 | $total_size = 0; 118 | $files = scandir($path); 119 | $cleanPath = rtrim($path, '/'). '/'; 120 | 121 | foreach($files as $t) { 122 | if ($t<>"." && $t<>"..") { 123 | $currentFile = $cleanPath . $t; 124 | if (is_dir($currentFile)) { 125 | $size = foldersize($currentFile); 126 | $total_size += $size; 127 | } 128 | else { 129 | $size = filesize($currentFile); 130 | $total_size += $size; 131 | } 132 | } 133 | } 134 | 135 | return $total_size; 136 | } 137 | 138 | function format_size($size) { 139 | $units = explode(' ', 'B KB MB GB TB PB'); 140 | 141 | $mod = 1024; 142 | 143 | for ($i = 0; $size > $mod; $i++) { 144 | $size /= $mod; 145 | } 146 | 147 | $endIndex = strpos($size, ".")+3; 148 | 149 | return substr( $size, 0, $endIndex).' '.$units[$i]; 150 | } 151 | 152 | /** 153 | * Format date from an item record into a 'x days/hours/minutes ago' format 154 | */ 155 | function format_date( $dateString ) { 156 | if( class_exists( 'DateTime' ) ) { 157 | $date = new DateTime(); 158 | $date->setTimestamp( strtotime( $dateString ) ); 159 | $interval = $date->diff( new DateTime( 'now' ) ); 160 | 161 | 162 | $format_array = array(); 163 | 164 | if( $interval->y !== 0 ) 165 | $format_array[] = '%y years'; 166 | if( $interval->m !== 0 ) 167 | $format_array[] = '%m months'; 168 | if( $interval->d !== 0 ) 169 | $format_array[] = '%d days'; 170 | if( $interval->h !== 0 ) 171 | $format_array[] = '%h hours'; 172 | 173 | return $interval->format( join(' ', $format_array ) . ' ago'); 174 | } 175 | return $dateString; 176 | } 177 | 178 | /** 179 | * Make a camelCase string into legible words 180 | */ 181 | function un_camel( $string ) { 182 | return ucfirst( implode(' ', preg_split('/([[:upper:]][[:lower:]]+)/', $string, null, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY) ) ); 183 | } 184 | 185 | /** 186 | * Resolve absolute and relative paths 187 | */ 188 | function get_real_path( $path ) { 189 | 190 | // Try to resolve absolute paths, but just return them on error 191 | if( '/' == $path[0] ) { 192 | if( ! $real_path = realpath( $path ) ) 193 | return $path; 194 | return realpath( $path ); 195 | } 196 | 197 | // Make relative paths absolute 198 | $root = dirname( dirname(__FILE__) ); 199 | if( ! realpath( $root . '/' . $path ) ) { 200 | return $root . '/' . $path; 201 | } 202 | return realpath( $root . '/' . $path ); 203 | } 204 | 205 | ?> -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | getMessage() ); 11 | } 12 | 13 | if( isset( $apc_cache_ttl ) && $apc_cache_ttl ) 14 | $zotero->setCacheTtl( $apc_cache_ttl ); 15 | 16 | $ipp = isset($_REQUEST['ipp']) ? (int)$_REQUEST['ipp'] : $def_ipp; 17 | $sort = isset($_REQUEST['sort']) ? $_REQUEST['sort'] : $def_sort; 18 | $sortorder = isset($_REQUEST['sortorder']) ? $_REQUEST['sortorder'] : $def_sortorder; 19 | $page = isset($_REQUEST['page']) ? (int)$_REQUEST['page'] : 1; 20 | $collectionKey = isset( $_REQUEST['collection'] ) ? $_REQUEST['collection'] : false; 21 | 22 | $webdav_url=( isset($_SERVER['HTTPS']) ? 'https' : 'http') . "://" . $_SERVER['HTTP_HOST'] . str_replace('?'.$_SERVER['QUERY_STRING'],'',$_SERVER['REQUEST_URI']) . "webdav_server.php/zotero/"; 23 | 24 | ?> 25 |

26 | Total size of stored attachments: 27 |         28 | WebDAV URL: 29 |

30 | $fetchlimit) $limit = $fetchlimit; else $limit = $ipp; 45 | 46 | // Include collections on index page for traversal 47 | $collections = $zotero->fetchCollections( array( 'collectionKey' => $collectionKey ) ); 48 | //print_r($collections); 49 | 50 | ?> 51 |
52 |

53 | 0 ) : ?> 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | parentCollectionKey != $collectionKey ) continue; ?> 64 | 65 | 66 | 67 | 68 | 69 | 70 |
Collection# Items
name; ?>numItems; ?> numItems == 1 ) ? 'item' : 'items' ; ?>
71 | 72 |

No collections were found.

73 | 74 |
75 | $sort, 79 | 'sort' => $sortorder, 80 | // 'content' => 'none', 81 | 'limit' => $limit, 82 | 'collectionKey' => $collectionKey 83 | ); 84 | 85 | $fetch_offset = $start; 86 | $items = array(); 87 | 88 | do { 89 | 90 | $fetched = $zotero->fetchItemsTop( array_merge( $fetch_params, array( 'start' => $fetch_offset ) ) ); 91 | 92 | $items = array_merge( $items, $fetched ); 93 | $fetch_offset += count( $items ); 94 | 95 | if( isset($zotero->getLastFeed()->links['next'])){ 96 | $moreItems = true; 97 | } else { 98 | $moreItems = false; 99 | } 100 | 101 | } while( count( $items ) < $ipp && count( $fetched ) >= $fetchlimit ); 102 | 103 | $totalitems = $zotero->getLastFeed()->totalResults; 104 | 105 | // MAIN DATA TABLE 106 | // parse result sets, write out data and get more from API if needed 107 | ?> 108 |
109 |

110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
AttachmentsAdded">Creator">Date">Title
numChildren ?>dateAdded ) ?>creatorSummary ?>apiObject['date'] ?>title ?>
137 |
138 |
139 |
140 | 141 | \n"); 172 | echo("\n"); 185 | echo("\n"); 196 | echo("\n
Pages"); 150 | $pages = intval($totalitems / $ipp) + 1; 151 | 152 | while ($i <= $pages) { 153 | if ($i != $page) echo(""); 154 | echo ("-$i-"); 155 | if ($i != $page) echo(""); 156 | echo ("   "); 157 | $i = $i + 1; 158 | if ($i > 5) { 159 | if ($i < ($page - 2)) { 160 | $i = $page - 2; 161 | echo (" . . .    "); 162 | } 163 | } 164 | if (($i > ($page + 2)) && ($i > 5)) { 165 | if ($i < ($pages - 4)) { 166 | $i = $pages - 4; 167 | echo (" . . .    "); 168 | } 169 | } 170 | } 171 | echo ("
Items per Page"); 173 | $ipp_list = array (1,10,20,50,100,200,500,1000,9999999); 174 | $i = 0; 175 | while ($i <= 7) { 176 | if ($ipp != $ipp_list[$i]) echo(""); 177 | echo ("-$ipp_list[$i]-"); 178 | if ($ipp != $ipp_list[$i]) echo(""); 179 | echo ("   "); 180 | $j = $i + 1; 181 | if (($ipp > $ipp_list[$i]) && ($ipp < $ipp_list[$j])) echo ("-$ipp-   "); 182 | $i = $i + 1; 183 | } 184 | echo ("
Sort By"); 186 | $s_list = array ("dateAdded", "title", "creator", "type", "date", "publisher", "publication", "journalAbbreviation", "language", "dateModified", "accessDate", "libraryCatalog", "callNumber", "rights", "addedBy", "numItems"); 187 | $i = 0; 188 | while ($i <= 15) { 189 | if ($sort != $s_list[$i]) echo(""); 190 | echo ("-$s_list[$i]-"); 191 | if ($sort != $s_list[$i]) echo(""); 192 | echo ("   "); 193 | $i = $i + 1; 194 | } 195 | echo ("
Sort Order"); 197 | $so_list = array ("asc", "desc"); 198 | $i = 0; 199 | while ($i <= 1) { 200 | if ($sortorder != $so_list[$i]) echo(""); 201 | echo ("-$so_list[$i]-"); 202 | if ($sortorder != $so_list[$i]) echo(""); 203 | echo ("   "); 204 | $i = $i + 1; 205 | } 206 | echo ("
\n"); 207 | ?> 208 | 209 | 210 | -------------------------------------------------------------------------------- /settings.php: -------------------------------------------------------------------------------- 1 | 42 | -------------------------------------------------------------------------------- /webdav_server.php: -------------------------------------------------------------------------------- 1 | ServeRequest( dirname( get_real_path( $data_dir ) ) ); 12 | #$server->ServeRequest( dirname( dirname(__FILE__) . '/' . $data_dir ) ); 13 | 14 | ?> 15 | --------------------------------------------------------------------------------