From bb2c046d5cb2ea914e1767f383ba3746cad13bfd Mon Sep 17 00:00:00 2001 From: dongsheng Date: Fri, 18 Jul 2008 07:40:12 +0000 Subject: [PATCH] MDL-13766 1. Move curl and repository_cache class to filelib.php 2. Name the file before downloading it 3. clean up code --- lib/filelib.php | 489 ++++++++++++++++++++++++- repository/ajax.php | 112 +++--- repository/boxnet/boxlibphp5.php | 8 +- repository/boxnet/repository.class.php | 45 +-- repository/curl.class.php | 428 ---------------------- repository/flickr/phpFlickr.php | 1 - repository/flickr/repository.class.php | 41 ++- repository/lib.php | 64 +--- repository/ws.php | 17 +- 9 files changed, 601 insertions(+), 604 deletions(-) delete mode 100644 repository/curl.class.php diff --git a/lib/filelib.php b/lib/filelib.php index 449cbc2a2d6..1561e47069e 100644 --- a/lib/filelib.php +++ b/lib/filelib.php @@ -95,7 +95,7 @@ function download_file_content($url, $headers=null, $postdata=null, $fullrespons } } - // check if proxy (if used) should be bypassed for this url + // check if proxy (if used) should be bypassed for this url $proxybypass = is_proxybypass( $url ); if (!extension_loaded('curl') or ($ch = curl_init($url)) === false) { @@ -169,11 +169,11 @@ function download_file_content($url, $headers=null, $postdata=null, $fullrespons curl_setopt($ch, CURLOPT_HTTPHEADER, $headers2); } - + if ($skipcertverify) { curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - + // use POST if requested if (is_array($postdata)) { foreach ($postdata as $k=>$v) { @@ -1090,4 +1090,485 @@ function file_modify_html_header($text) { return $text; } -?> +/** + * RESTful cURL class + * + * This is a wrapper class for curl, it is quite easy to use: + * + * $c = new curl; + * // enable cache + * $c = new curl(array('cache'=>true)); + * // enable cookie + * $c = new curl(array('cookie'=>true)); + * // enable proxy + * $c = new curl(array('proxy'=>true)); + * + * // HTTP GET Method + * $html = $c->get('http://example.com'); + * // HTTP POST Method + * $html = $c->post('http://example.com/', array('q'=>'words', 'name'=>'moodle')); + * // HTTP PUT Method + * $html = $c->put('http://example.com/', array('file'=>'/var/www/test.txt'); + * + * @author Dongsheng Cai + * @version 0.4 dev + * @license http://www.gnu.org/copyleft/gpl.html GNU Public License + */ + +class curl { + public $cache = false; + public $proxy = false; + public $version = '0.4 dev'; + public $response = array(); + public $header = array(); + public $info; + public $error; + + private $options; + private $proxy_host = ''; + private $proxy_auth = ''; + private $proxy_type = ''; + private $debug = false; + private $cookie = false; + + public function __construct($options = array()){ + global $CFG; + if (!function_exists('curl_init')) { + $this->error = 'cURL module must be enabled!'; + trigger_error($this->error, E_USER_ERROR); + return false; + } + // the options of curl should be init here. + $this->resetopt(); + if (!empty($options['debug'])) { + $this->debug = true; + } + if(!empty($options['cookie'])) { + if($options['cookie'] === true) { + $this->cookie = $CFG->dataroot.'/curl_cookie.txt'; + } else { + $this->cookie = $options['cookie']; + } + } + if (!empty($options['cache'])) { + if (class_exists('curl_cache')) { + $this->cache = new curl_cache; + } + } + if (!empty($options['proxy'])) { + if (!empty($CFG->proxyhost)) { + if (empty($CFG->proxyport)) { + $this->proxy_host = $CFG->proxyhost; + } else { + $this->proxy_host = $CFG->proxyhost.':'.$CFG->proxyport; + } + if (!empty($CFG->proxyuser) and !empty($CFG->proxypassword)) { + $this->proxy_auth = $CFG->proxyuser.':'.$CFG->proxypassword; + $this->setopt(array( + 'proxyauth'=> CURLAUTH_BASIC | CURLAUTH_NTLM, + 'proxyuserpwd'=>$this->proxy_auth)); + } + if (!empty($CFG->proxytype)) { + if ($CFG->proxytype == 'SOCKS5') { + $this->proxy_type = CURLPROXY_SOCKS5; + } else { + $this->proxy_type = CURLPROXY_HTTP; + $this->setopt(array('httpproxytunnel'=>true)); + } + $this->setopt(array('proxytype'=>$this->proxy_type)); + } + } + if (!empty($this->proxy_host)) { + $this->proxy = array('proxy'=>$this->proxy_host); + } + } + } + public function resetopt(){ + $this->options = array(); + $this->options['CURLOPT_USERAGENT'] = 'MoodleBot/1.0'; + // True to include the header in the output + $this->options['CURLOPT_HEADER'] = 0; + // True to Exclude the body from the output + $this->options['CURLOPT_NOBODY'] = 0; + // TRUE to follow any "Location: " header that the server + // sends as part of the HTTP header (note this is recursive, + // PHP will follow as many "Location: " headers that it is sent, + // unless CURLOPT_MAXREDIRS is set). + $this->options['CURLOPT_FOLLOWLOCATION'] = 1; + $this->options['CURLOPT_MAXREDIRS'] = 10; + $this->options['CURLOPT_ENCODING'] = ''; + // TRUE to return the transfer as a string of the return + // value of curl_exec() instead of outputting it out directly. + $this->options['CURLOPT_RETURNTRANSFER'] = 1; + $this->options['CURLOPT_BINARYTRANSFER'] = 0; + $this->options['CURLOPT_SSL_VERIFYPEER'] = 0; + $this->options['CURLOPT_SSL_VERIFYHOST'] = 2; + $this->options['CURLOPT_TIMEOUT'] = 120; + } + + /** + * Reset Cookie + * + * @param array $options If array is null, this function will + * reset the options to default value. + * + */ + public function resetcookie() { + if (!empty($this->cookie)) { + if (is_file($this->cookie)) { + $fp = fopen($this->cookie, 'w'); + if (!empty($fp)) { + fwrite($fp, ''); + fclose($fp); + } + } + } + } + + /** + * Set curl options + * + * @param array $options If array is null, this function will + * reset the options to default value. + * + */ + public function setopt($options = array()) { + if (is_array($options)) { + foreach($options as $name => $val){ + if (stripos($name, 'CURLOPT_') === false) { + $name = strtoupper('CURLOPT_'.$name); + } + $this->options[$name] = $val; + } + } + } + /** + * Reset http method + * + */ + public function cleanopt(){ + unset($this->options['CURLOPT_HTTPGET']); + unset($this->options['CURLOPT_POST']); + unset($this->options['CURLOPT_POSTFIELDS']); + unset($this->options['CURLOPT_PUT']); + unset($this->options['CURLOPT_INFILE']); + unset($this->options['CURLOPT_INFILESIZE']); + unset($this->options['CURLOPT_CUSTOMREQUEST']); + } + + /** + * Set HTTP Request Header + * + * @param array $headers + * + */ + public function setHeader($header) { + if (is_array($header)){ + foreach ($header as $v) { + $this->setHeader($v); + } + } else { + $this->header[] = $header; + } + } + /** + * Set HTTP Response Header + * + */ + public function getResponse(){ + return $this->response; + } + /** + * private callback function + * Formatting HTTP Response Header + * + */ + private function formatHeader($ch, $header) + { + $this->count++; + if (strlen($header) > 2) { + list($key, $value) = explode(" ", rtrim($header, "\r\n"), 2); + $key = rtrim($key, ':'); + if (!empty($this->response[$key])) { + if (is_array($this->response[$key])){ + $this->response[$key][] = $value; + } else { + $tmp = $this->response[$key]; + $this->response[$key] = array(); + $this->response[$key][] = $tmp; + $this->response[$key][] = $value; + + } + } else { + $this->response[$key] = $value; + } + } + return strlen($header); + } + + /** + * Set options for individual curl instance + */ + private function apply_opt($curl, $options) { + // Clean up + $this->cleanopt(); + // set cookie + if (!empty($this->cookie) || !empty($options['cookie'])) { + $this->setopt(array('cookiejar'=>$this->cookie, + 'cookiefile'=>$this->cookie + )); + } + + // set proxy + if (!empty($this->proxy) || !empty($options['proxy'])) { + $this->setopt($this->proxy); + } + $this->setopt($options); + // reset before set options + curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this,'formatHeader')); + // set headers + if (empty($this->header)){ + $this->setHeader(array( + 'User-Agent: MoodleBot/1.0', + 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7', + 'Connection: keep-alive' + )); + } + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->header); + + if ($this->debug){ + echo '

Options

'; + var_dump($this->options); + echo '

Header

'; + var_dump($this->header); + } + + // set options + foreach($this->options as $name => $val) { + if (is_string($name)) { + $name = constant(strtoupper($name)); + } + curl_setopt($curl, $name, $val); + } + return $curl; + } + /* + * Download multiple files in parallel + * $c = new curl; + * $c->download(array( + * array('url'=>'http://localhost/', 'file'=>fopen('a', 'wb')), + * array('url'=>'http://localhost/20/', 'file'=>fopen('b', 'wb')) + * )); + */ + public function download($requests, $options = array()) { + $options['CURLOPT_BINARYTRANSFER'] = 1; + $options['RETURNTRANSFER'] = false; + return $this->multi($requests, $options); + } + /* + * Mulit HTTP Requests + * This function could run multi-requests in parallel. + */ + protected function multi($requests, $options = array()) { + $count = count($requests); + $handles = array(); + $results = array(); + $main = curl_multi_init(); + for ($i = 0; $i < $count; $i++) { + $url = $requests[$i]; + foreach($url as $n=>$v){ + $options[$n] = $url[$n]; + } + $handles[$i] = curl_init($url['url']); + $this->apply_opt($handles[$i], $options); + curl_multi_add_handle($main, $handles[$i]); + } + $running = 0; + do { + curl_multi_exec($main, $running); + } while($running > 0); + for ($i = 0; $i < $count; $i++) { + if (!empty($optins['CURLOPT_RETURNTRANSFER'])) { + $results[] = true; + } else { + $results[] = curl_multi_getcontent($handles[$i]); + } + curl_multi_remove_handle($main, $handles[$i]); + } + curl_multi_close($main); + return $results; + } + /** + * Single HTTP Request + */ + protected function request($url, $options = array()){ + // create curl instance + $curl = curl_init($url); + $options['url'] = $url; + $this->apply_opt($curl, $options); + if ($this->cache && $ret = $this->cache->get($this->options)) { + return $ret; + } else { + $ret = curl_exec($curl); + if ($this->cache) { + $this->cache->set($this->options, $ret); + } + } + + $this->info = curl_getinfo($curl); + $this->error = curl_error($curl); + + if ($this->debug){ + echo '

Return Data

'; + var_dump($ret); + echo '

Info

'; + var_dump($this->info); + echo '

Error

'; + var_dump($this->error); + } + + curl_close($curl); + + if (!empty($ret)){ + return $ret; + } else { + return false; + } + } + + /** + * HTTP HEAD method + */ + public function head($url, $options = array()){ + $options['CURLOPT_HTTPGET'] = 0; + $options['CURLOPT_HEADER'] = 1; + $options['CURLOPT_NOBODY'] = 1; + return $this->request($url, $options); + } + + /** + * HTTP POST method + */ + public function post($url, $params = array(), $options = array()){ + $options['CURLOPT_POST'] = 1; + $options['CURLOPT_POSTFIELDS'] = $params; + return $this->request($url, $options); + } + + /** + * HTTP GET method + */ + public function get($url, $params = array(), $options = array()){ + $options['CURLOPT_HTTPGET'] = 1; + + if (!empty($params)){ + $url .= (stripos($url, '?') !== false) ? '&' : '?'; + $url .= http_build_query($params, '', '&'); + } + return $this->request($url, $options); + } + + /** + * HTTP PUT method + */ + public function put($url, $params = array(), $options = array()){ + $file = $params['file']; + if (!is_file($file)){ + return null; + } + $fp = fopen($file, 'r'); + $size = filesize($file); + $options['CURLOPT_PUT'] = 1; + $options['CURLOPT_INFILESIZE'] = $size; + $options['CURLOPT_INFILE'] = $fp; + if (!isset($this->options['CURLOPT_USERPWD'])){ + $this->setopt(array('CURLOPT_USERPWD'=>'anonymous: noreply@moodle.org')); + } + $ret = $this->request($url, $options); + fclose($fp); + return $ret; + } + + /** + * HTTP DELETE method + */ + public function delete($url, $param = array(), $options = array()){ + $options['CURLOPT_CUSTOMREQUEST'] = 'DELETE'; + if (!isset($options['CURLOPT_USERPWD'])) { + $options['CURLOPT_USERPWD'] = 'anonymous: noreply@moodle.org'; + } + $ret = $this->request($url, $options); + return $ret; + } + /** + * HTTP TRACE method + */ + public function trace($url, $options = array()){ + $options['CURLOPT_CUSTOMREQUEST'] = 'TRACE'; + $ret = $this->request($url, $options); + return $ret; + } + /** + * HTTP OPTIONS method + */ + public function options($url, $options = array()){ + $options['CURLOPT_CUSTOMREQUEST'] = 'OPTIONS'; + $ret = $this->request($url, $options); + return $ret; + } +} + +/** + * This class is used by cURL class, use case: + * + * $CFG->repository_cache_expire = 120; + * $c = new curl(array('cache'=>true)); + * $ret = $c->get('http://www.google.com'); + * + */ +class curl_cache { + public $dir = ''; + function __construct(){ + global $CFG; + if (!file_exists($CFG->dataroot.'/repository/cache')) { + mkdir($CFG->dataroot.'/repository/cache/', 0777, true); + } + if(is_dir($CFG->dataroot.'/repository/cache')) { + $this->dir = $CFG->dataroot.'/repository/cache/'; + } + } + public function get($param){ + global $CFG; + $filename = md5(serialize($param)); + if(file_exists($this->dir.$filename)) { + $lasttime = filemtime($this->dir.$filename); + if(time()-$lasttime > $CFG->repository_cache_expire) { + return false; + } else { + $fp = fopen($this->dir.$filename, 'r'); + $size = filesize($this->dir.$filename); + $content = fread($fp, $size); + return unserialize($content); + } + } + return false; + } + public function set($param, $val){ + $filename = md5(serialize($param)); + $fp = fopen($this->dir.$filename, 'w'); + fwrite($fp, serialize($val)); + fclose($fp); + } + public function cleanup($expire){ + if($dir = opendir($this->dir)){ + while (false !== ($file = readdir($dir))) { + if(!is_dir($file) && $file != '.' && $file != '..') { + $lasttime = @filemtime($this->dir.$file); + if(time() - $lasttime > $expire){ + @unlink($this->dir.$file); + } + } + } + } + } +} diff --git a/repository/ajax.php b/repository/ajax.php index 570b6e28a73..7623296cff6 100644 --- a/repository/ajax.php +++ b/repository/ajax.php @@ -1,3 +1,6 @@ + + + Ajax picker demo page pixpath.'/i/item.gif'; $meta = << + + + + + + - - - - - - - @@ -62,14 +66,16 @@ img{margin:0;padding:0;border:0} EOD; -print_header('', '', '', '', $meta, false); +echo $meta; ?> -
+ + +

-
+
@@ -116,13 +122,6 @@ function openpicker(){ units: [ {position: 'top', height: 32, resize: false, body:'
', gutter: '2'}, { position: 'left', width: 150, resize: true, body: '
    ', gutter: '0 5 0 2', minWidth: 150, maxWidth: 300 }, - { position: 'bottom', - height: 30, - body: '
    '+ - ''+ - ''+ - '
    ', - gutter: '2'}, { position: 'center', body: '
    ', scroll: true, gutter: '0 2 0 0' } ] }); @@ -157,10 +156,11 @@ function openpicker(){ list.on('contentReady', function(e){ for(var i=0; i'+ - repo.repositoryname+' '; - li.innerHTML += 'Logout'; + repo.repositoryname+'
    '; + li.innerHTML += 'search'; + li.innerHTML += 'Logout '; li.id = 'repo-'+repo.id; this.appendChild(li); var e = new YAHOO.util.Element('repo-call-'+repo.id); @@ -188,27 +188,6 @@ function openpicker(){ var btn_thumb = {label: 'Thumbnail', value: 't', onclick: {fn: viewthumb}}; viewbar.addButtons([btn_list, btn_thumb]); var select = new YAHOO.util.Element('select'); - select.on('click', function(e){ - var nodes = YAHOO.util.Selector.query('input:checked'); - var str = ''; - var files = []; - for(k in nodes){ - files.push(nodes[k].value); - } - loading(); - var trans = YAHOO.util.Connect.asyncRequest('POST', 'ws.php?id='+repositoryid+'&action=download', loadfile, postdata({'files':files})); - }) - var search = new YAHOO.util.Element('search'); - search.on('click', function(e) { - if(repositoryid==0){ - alert('Select a repository first.'); - return; - } - var data = window.prompt("What are you searching for?"); - if(data != null && data != '') { - dosearch(data); - } - }) }; function postdata(obj) { @@ -248,6 +227,24 @@ function loading(){ panel.get('element').innerHTML = 'loading...'; } +// name the file +function rename(oldname, url){ + var panel = new YAHOO.util.Element('panel'); + var html = '
    '; + html += ''; + html += '
    '; + html += ''; + html += ''; + html += 'Back'; + html += '
    '; + panel.get('element').innerHTML = html; +} +function download(){ + var title = document.getElementById('newname').value; + var file = document.getElementById('fileurl').value; + loading(); + var trans = YAHOO.util.Connect.asyncRequest('POST', 'ws.php?id='+repositoryid+'&action=download', loadfile, postdata({'file':file, 'title':title})); +} // produce thumbnail view function viewthumb(){ viewbar.check(1); @@ -261,7 +258,8 @@ function viewthumb(){ for(k in obj){ str += '
    '; str += ''; - str += '

    ' + str += '
    '; + str += (''); str += obj[k].title+'
    '; str += '
    '; } @@ -270,6 +268,13 @@ function viewthumb(){ return str; } +function viewfiles(){ + if(viewmode) { + viewthumb(); + } else { + viewlist(); + } +} // produce list view function viewlist(){ var str = ''; @@ -281,7 +286,7 @@ function viewlist(){ var panel = new YAHOO.util.Element('panel'); str += makepage(); for(k in obj){ - str += ''; + str += (''); str += obj[k].title; str += '
    '; } @@ -324,7 +329,9 @@ var loadfile = { alert('Invalid JSON String\n'+o.responseText); } var panel = new YAHOO.util.Element('panel'); - panel.get('element').innerHTML = '

    Download Successfully!

    '; + var html = '

    Download Successfully!

    '; + html += 'Back'; + panel.get('element').innerHTML = html; } } @@ -336,10 +343,15 @@ function cr(id, path, reset){ loading(); var trans = YAHOO.util.Connect.asyncRequest('GET', 'ws.php?id='+id+'&p='+path+'&reset='+reset, callback); } -function dosearch(text){ +function dosearch(id){ + var data = window.prompt("What are you searching for?"); + if(data == null && data == '') { + alert('nothing entered'); + return; + } viewbar.set('disabled', false); loading(); - var trans = YAHOO.util.Connect.asyncRequest('GET', 'ws.php?id='+repositoryid+'&s='+text, callback); + var trans = YAHOO.util.Connect.asyncRequest('GET', 'ws.php?id='+id+'&s='+data, callback); } function dologin(){ @@ -348,5 +360,5 @@ function dologin(){ var trans = YAHOO.util.Connect.asyncRequest('POST', 'ws.php', callback); } - + diff --git a/repository/boxnet/boxlibphp5.php b/repository/boxnet/boxlibphp5.php index 0a80a602d1b..538fa56f604 100755 --- a/repository/boxnet/boxlibphp5.php +++ b/repository/boxnet/boxlibphp5.php @@ -17,8 +17,6 @@ * */ -require_once($CFG->dirroot.'/repository/'.'curl.class.php'); - class boxclient { public $auth_token = ''; @@ -80,13 +78,13 @@ class boxclient { // 'username'=>'dongsheng@moodle.com', // 'password'=>'xxx')); // - function getAuthToken($ticket, $options = array()) { + function getAuthToken($ticket, $username, $password) { $c = new curl; $c->setopt(array('CURLOPT_FOLLOWLOCATION'=>0)); $param = array( 'login_form1'=>'', - 'login'=>$options['username'], - 'password'=>$options['password'], + 'login'=>$username, + 'password'=>$password, 'dologin'=>1, '__login'=>1 ); diff --git a/repository/boxnet/repository.class.php b/repository/boxnet/repository.class.php index c3ee4a925f6..31b00328b7c 100755 --- a/repository/boxnet/repository.class.php +++ b/repository/boxnet/repository.class.php @@ -7,14 +7,11 @@ * @version 0.1 dev * @license http://www.gnu.org/copyleft/gpl.html GNU Public License */ -require_once($CFG->dirroot.'/repository/'.'lib.php'); -require_once($CFG->dirroot.'/repository/'.'curl.class.php'); + require_once($CFG->dirroot.'/repository/boxnet/'.'boxlibphp5.php'); class repository_boxnet extends repository{ - - var $box; - var $ticket; + private $box; public function __construct($repositoryid, $context = SITEID, $options = array()){ global $SESSION, $action; @@ -32,31 +29,21 @@ class repository_boxnet extends repository{ && !empty($options['password']) && !empty($options['ticket']) ) { - $c = new curl; - $c->setopt(array('CURLOPT_FOLLOWLOCATION'=>0)); - $param = array( - 'login_form1'=>'', - 'login'=>$options['username'], - 'password'=>$options['password'], - 'dologin'=>1, - '__login'=>1 - ); - $ret = $c->post('http://www.box.net/api/1.0/auth/'.$options['ticket'], $param); - $header = $c->getResponse(); - $location = $header['location']; - preg_match('#auth_token=(.*)$#i', $location, $matches); - $auth_token = $matches[1]; - $SESSION->box_token = $auth_token; + $this->box = new boxclient($options['api_key']); + $SESSION->box_token = $this->box->getAuthToken($options['ticket'], + $options['username'], $options['password']); } // already logged if(!empty($SESSION->box_token)) { - $this->box = new boxclient($options['api_key'], $SESSION->box_token); + if(empty($this->box)) { + $this->box = new boxclient($options['api_key'], $SESSION->box_token); + } $options['auth_token'] = $SESSION->box_token; if(empty($action)) { $action = 'list'; } } else { - $this->box = new boxclient($options['api_key'], ''); + $this->box = new boxclient($options['api_key']); if(!empty($action)) { $action = ''; } @@ -109,19 +96,18 @@ class repository_boxnet extends repository{ // print list } } else { - // get a ticket from box.net - $ticket_return = $this->box->getTicket(); - $this->ticket = $ticket_return['ticket']; + $t = $this->box->getTicket(); if(empty($this->options['auth_token'])) { $str = ''; $str .= '
    '; - $str .= ''; + $str .= ''; $str .= ''; - $str .= '