summaryrefslogtreecommitdiffstats
path: root/lib/connector
diff options
context:
space:
mode:
authorBart Visscher <bartv@thisnet.nl>2012-07-27 11:40:51 +0200
committerBart Visscher <bartv@thisnet.nl>2012-07-27 11:40:51 +0200
commita7a54331082c41c5b05cd7982c058caf1556f777 (patch)
treebc51551c2430837856cdb1f3a1e04c46e0f664cb /lib/connector
parente8010209bb1ec8ef9ecc1cff7ac2b2d4d414bd74 (diff)
parentd26f87e738314db7820f39f74f42865ff20f7bd7 (diff)
downloadnextcloud-server-a7a54331082c41c5b05cd7982c058caf1556f777.tar.gz
nextcloud-server-a7a54331082c41c5b05cd7982c058caf1556f777.zip
Merge branch 'master' into chunked_upload
Conflicts: lib/connector/sabre/directory.php
Diffstat (limited to 'lib/connector')
-rw-r--r--lib/connector/sabre/auth.php17
-rw-r--r--lib/connector/sabre/client.php83
-rw-r--r--lib/connector/sabre/directory.php47
-rw-r--r--lib/connector/sabre/file.php34
-rw-r--r--lib/connector/sabre/locks.php2
-rw-r--r--lib/connector/sabre/node.php54
6 files changed, 182 insertions, 55 deletions
diff --git a/lib/connector/sabre/auth.php b/lib/connector/sabre/auth.php
index ee680391626..99f696e3a07 100644
--- a/lib/connector/sabre/auth.php
+++ b/lib/connector/sabre/auth.php
@@ -31,13 +31,18 @@ class OC_Connector_Sabre_Auth extends Sabre_DAV_Auth_Backend_AbstractBasic {
* @return bool
*/
protected function validateUserPass($username, $password){
- OC_Util::setUpFS();//login hooks may need early access to the filesystem
- if(OC_User::login($username,$password)){
- OC_Util::setUpFS($username);
+ if (OC_User::isLoggedIn()) {
+ OC_Util::setupFS($username);
return true;
- }
- else{
- return false;
+ } else {
+ OC_Util::setUpFS();//login hooks may need early access to the filesystem
+ if(OC_User::login($username,$password)){
+ OC_Util::setUpFS($username);
+ return true;
+ }
+ else{
+ return false;
+ }
}
}
}
diff --git a/lib/connector/sabre/client.php b/lib/connector/sabre/client.php
index b799b541a05..7e8f21264f9 100644
--- a/lib/connector/sabre/client.php
+++ b/lib/connector/sabre/client.php
@@ -23,29 +23,18 @@
class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
- protected $curlSettings;
-
- public function __construct(array $settings) {
- //set default curl settings
- $this->curlSettings = array(
- CURLOPT_RETURNTRANSFER => true,
- // Return headers as part of the response
- CURLOPT_HEADER => true,
- // Automatically follow redirects
- CURLOPT_FOLLOWLOCATION => true,
- CURLOPT_MAXREDIRS => 5,
- CURLOPT_SSL_VERIFYPEER => true,
- //CURLOPT_SSL_VERIFYPEER => false,
- );
- parent::__construct($settings);
- }
-
- public function setCurlSettings($settings) {
- if (is_array($settings)) {
- foreach ($settings as $k => $v) {
- $this->curlSettings[$k] = $v;
- }
- }
+ protected $trustedCertificates;
+
+ /**
+ * Add trusted root certificates to the webdav client.
+ *
+ * The parameter certificates should be a absulute path to a file which contains
+ * all trusted certificates
+ *
+ * @param string $certificates
+ */
+ public function addTrustedCertificates($certificates) {
+ $this->trustedCertificates = $certificates;
}
/**
@@ -68,14 +57,24 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
* @return array
*/
public function request($method, $url = '', $body = null, $headers = array()) {
-
- $this->curlSettings[CURLOPT_POSTFIELDS] = $body;
+
$url = $this->getAbsoluteUrl($url);
+ $curlSettings = array(
+ CURLOPT_RETURNTRANSFER => true,
+ // Return headers as part of the response
+ CURLOPT_HEADER => true,
+ CURLOPT_POSTFIELDS => $body,
+ // Automatically follow redirects
+ CURLOPT_FOLLOWLOCATION => true,
+ CURLOPT_MAXREDIRS => 5,
+ );
+
+ if($this->trustedCertificates) {
+ $curlSettings[CURLOPT_CAINFO] = $this->trustedCertificates;
+ }
+
switch ($method) {
- case 'PUT':
- $this->curlSettings[CURLOPT_PUT] = true;
- break;
case 'HEAD' :
// do not read body with HEAD requests (this is neccessary because cURL does not ignore the body with HEAD
@@ -83,12 +82,12 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
// specs...) cURL does unfortunately return an error in this case ("transfer closed transfer closed with
// ... bytes remaining to read") this can be circumvented by explicitly telling cURL to ignore the
// response body
- $this->curlSettings[CURLOPT_NOBODY] = true;
- $this->curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
+ $curlSettings[CURLOPT_NOBODY] = true;
+ $curlSettings[CURLOPT_CUSTOMREQUEST] = 'HEAD';
break;
default:
- $this->curlSettings[CURLOPT_CUSTOMREQUEST] = $method;
+ $curlSettings[CURLOPT_CUSTOMREQUEST] = $method;
break;
}
@@ -100,15 +99,22 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
$nHeaders[] = $key . ': ' . $value;
}
- $this->curlSettings[CURLOPT_HTTPHEADER] = $nHeaders;
+ $curlSettings[CURLOPT_HTTPHEADER] = $nHeaders;
if ($this->proxy) {
- $this->curlSettings[CURLOPT_PROXY] = $this->proxy;
+ $curlSettings[CURLOPT_PROXY] = $this->proxy;
}
- if ($this->userName) {
- $this->curlSettings[CURLOPT_HTTPAUTH] = CURLAUTH_BASIC | CURLAUTH_DIGEST;
- $this->curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
+ if ($this->userName && $this->authType) {
+ $curlType = 0;
+ if ($this->authType & self::AUTH_BASIC) {
+ $curlType |= CURLAUTH_BASIC;
+ }
+ if ($this->authType & self::AUTH_DIGEST) {
+ $curlType |= CURLAUTH_DIGEST;
+ }
+ $curlSettings[CURLOPT_HTTPAUTH] = $curlType;
+ $curlSettings[CURLOPT_USERPWD] = $this->userName . ':' . $this->password;
}
list(
@@ -116,7 +122,7 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
$curlInfo,
$curlErrNo,
$curlError
- ) = $this->curlRequest($url, $this->curlSettings);
+ ) = $this->curlRequest($url, $curlSettings);
$headerBlob = substr($response, 0, $curlInfo['header_size']);
$response = substr($response, $curlInfo['header_size']);
@@ -163,6 +169,5 @@ class OC_Connector_Sabre_Client extends Sabre_DAV_Client {
return $response;
- }
-
+ }
} \ No newline at end of file
diff --git a/lib/connector/sabre/directory.php b/lib/connector/sabre/directory.php
index 894256d5b2a..bed75015aef 100644
--- a/lib/connector/sabre/directory.php
+++ b/lib/connector/sabre/directory.php
@@ -26,11 +26,26 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
/**
* Creates a new file in the directory
*
- * data is a readable stream resource
+ * Data will either be supplied as a stream resource, or in certain cases
+ * as a string. Keep in mind that you may have to support either.
+ *
+ * After succesful creation of the file, you may choose to return the ETag
+ * of the new file here.
+ *
+ * The returned ETag must be surrounded by double-quotes (The quotes should
+ * be part of the actual string).
+ *
+ * If you cannot accurately determine the ETag, you should not return it.
+ * If you don't store the file exactly as-is (you're transforming it
+ * somehow) you should also not return an ETag.
+ *
+ * This means that if a subsequent GET to this new file does not exactly
+ * return the same contents of what was submitted here, you are strongly
+ * recommended to omit the ETag.
*
* @param string $name Name of the file
- * @param resource $data Initial payload
- * @return void
+ * @param resource|string $data Initial payload
+ * @return null|string
*/
public function createFile($name, $data = null) {
if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
@@ -53,11 +68,15 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
fwrite($f,$chunk);
}
fclose($f);
+ return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
}
} else {
$newPath = $this->path . '/' . $name;
OC_Filesystem::file_put_contents($newPath,$data);
+ return OC_Connector_Sabre_Node::getETagPropertyForPath($newPath);
}
+
+ return null;
}
/**
@@ -167,7 +186,7 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
* @return array
*/
public function getQuotaInfo() {
- $rootInfo=OC_FileCache::get('');
+ $rootInfo=OC_FileCache_Cached::get('');
return array(
$rootInfo['size'],
OC_Filesystem::free_space()
@@ -175,5 +194,25 @@ class OC_Connector_Sabre_Directory extends OC_Connector_Sabre_Node implements Sa
}
+ /**
+ * Returns a list of properties for this nodes.;
+ *
+ * The properties list is a list of propertynames the client requested,
+ * encoded as xmlnamespace#tagName, for example:
+ * http://www.example.org/namespace#author
+ * If the array is empty, all properties should be returned
+ *
+ * @param array $properties
+ * @return void
+ */
+ public function getProperties($properties) {
+ $props = parent::getProperties($properties);
+ if (in_array(self::GETETAG_PROPERTYNAME, $properties)
+ && !isset($props[self::GETETAG_PROPERTYNAME])) {
+ $props[self::GETETAG_PROPERTYNAME] =
+ OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
+ }
+ return $props;
+ }
}
diff --git a/lib/connector/sabre/file.php b/lib/connector/sabre/file.php
index dd25df78c29..9d571fceb0d 100644
--- a/lib/connector/sabre/file.php
+++ b/lib/connector/sabre/file.php
@@ -26,13 +26,28 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
/**
* Updates the data
*
+ * The data argument is a readable stream resource.
+ *
+ * After a succesful put operation, you may choose to return an ETag. The
+ * etag must always be surrounded by double-quotes. These quotes must
+ * appear in the actual string you're returning.
+ *
+ * Clients may use the ETag from a PUT request to later on make sure that
+ * when they update the file, the contents haven't changed in the mean
+ * time.
+ *
+ * If you don't plan to store the file byte-by-byte, and you return a
+ * different object on a subsequent GET you are strongly recommended to not
+ * return an ETag, and just return null.
+ *
* @param resource $data
- * @return void
+ * @return string|null
*/
public function put($data) {
OC_Filesystem::file_put_contents($this->path,$data);
+ return OC_Connector_Sabre_Node::getETagPropertyForPath($this->path);
}
/**
@@ -42,7 +57,7 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
*/
public function get() {
- return OC_Filesystem::fopen($this->path,'r');
+ return OC_Filesystem::fopen($this->path,'rb');
}
@@ -79,9 +94,20 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
* @return mixed
*/
public function getETag() {
+ $properties = $this->getProperties(array(self::GETETAG_PROPERTYNAME));
+ if (isset($properties[self::GETETAG_PROPERTYNAME])) {
+ return $properties[self::GETETAG_PROPERTYNAME];
+ }
+ return $this->getETagPropertyForPath($this->path);
+ }
- return null;
-
+ /**
+ * Creates a ETag for this path.
+ * @param string $path Path of the file
+ * @return string|null Returns null if the ETag can not effectively be determined
+ */
+ static protected function createETag($path) {
+ return OC_Filesystem::hash('md5', $path);
}
/**
diff --git a/lib/connector/sabre/locks.php b/lib/connector/sabre/locks.php
index 94382e68a1a..e95dcf02d27 100644
--- a/lib/connector/sabre/locks.php
+++ b/lib/connector/sabre/locks.php
@@ -108,7 +108,7 @@ class OC_Connector_Sabre_Locks extends Sabre_DAV_Locks_Backend_Abstract {
$locks = $this->getLocks($uri,false);
$exists = false;
- foreach($locks as $k=>$lock) {
+ foreach($locks as $lock) {
if ($lock->token == $lockInfo->token) $exists = true;
}
diff --git a/lib/connector/sabre/node.php b/lib/connector/sabre/node.php
index be315a0ffd9..f268f8b57c4 100644
--- a/lib/connector/sabre/node.php
+++ b/lib/connector/sabre/node.php
@@ -22,6 +22,7 @@
*/
abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IProperties {
+ const GETETAG_PROPERTYNAME = '{DAV:}getetag';
/**
* The path to the current node
@@ -141,6 +142,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
public function updateProperties($properties) {
$existing = $this->getProperties(array());
foreach($properties as $propertyName => $propertyValue) {
+ $propertyName = preg_replace("/^{.*}/", "", $propertyName); // remove leading namespace from property name
// If it was null, we need to delete the property
if (is_null($propertyValue)) {
if(array_key_exists( $propertyName, $existing )){
@@ -178,7 +180,7 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @param array $properties
* @return void
*/
- function getProperties($properties) {
+ public function getProperties($properties) {
if (is_null($this->property_cache)) {
$query = OC_DB::prepare( 'SELECT * FROM *PREFIX*properties WHERE userid = ? AND propertypath = ?' );
$result = $query->execute( array( OC_User::getUser(), $this->path ));
@@ -200,4 +202,54 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
}
return $props;
}
+
+ /**
+ * Creates a ETag for this path.
+ * @param string $path Path of the file
+ * @return string|null Returns null if the ETag can not effectively be determined
+ */
+ static protected function createETag($path) {
+ return uniqid('', true);
+ }
+
+ /**
+ * Returns the ETag surrounded by double-quotes for this path.
+ * @param string $path Path of the file
+ * @return string|null Returns null if the ETag can not effectively be determined
+ */
+ static public function getETagPropertyForPath($path) {
+ $tag = self::createETag($path);
+ if (empty($tag)) {
+ return null;
+ }
+ $etag = '"'.$tag.'"';
+ $query = OC_DB::prepare( 'INSERT INTO *PREFIX*properties (userid,propertypath,propertyname,propertyvalue) VALUES(?,?,?,?)' );
+ $query->execute( array( OC_User::getUser(), $path, self::GETETAG_PROPERTYNAME, $etag ));
+ return $etag;
+ }
+
+ /**
+ * Remove the ETag from the cache.
+ * @param string $path Path of the file
+ */
+ static public function removeETagPropertyForPath($path) {
+ // remove tags from this and parent paths
+ $paths = array();
+ while ($path != '/' && $path != '') {
+ $paths[] = $path;
+ $path = dirname($path);
+ }
+ if (empty($paths)) {
+ return;
+ }
+ $paths[] = $path;
+ $path_placeholders = join(',', array_fill(0, count($paths), '?'));
+ $query = OC_DB::prepare( 'DELETE FROM *PREFIX*properties'
+ .' WHERE userid = ?'
+ .' AND propertyname = ?'
+ .' AND propertypath IN ('.$path_placeholders.')'
+ );
+ $vals = array( OC_User::getUser(), self::GETETAG_PROPERTYNAME );
+ $query->execute(array_merge( $vals, $paths ));
+ }
}