Initial Commit

FSyncMS v08
balu-master 0.8.0
balu 12 years ago
commit 5ea8138f2a

@ -0,0 +1,11 @@
Visit http://www.ohnekontur.de/2011/07/24/how-to-install-fsyncms-firefox-sync-eigener-server/ for install instructions
Visit http://www.ohnekontur.de for the newest version
FSyncMS v 08
Should be working with firefox 11 and lower (tested with 11)
Changelog,
Fixed user registration process,
fixed some delete problems

@ -0,0 +1,154 @@
<?php
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Weave Minimal Server
#
# The Initial Developer of the Original Code is
# Mozilla Labs.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Toby Elliott (telliott@mozilla.com)
# Luca Tettamanti
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
#The datasets we might be dealing with here are too large for sticking it all into an array, so
#we need to define a direct-output method for the storage class to use. If we start producing multiples
#(unlikely), we can put them in their own class.
class WBOJsonOutput
{
private $_full = null;
private $_comma_flag = 0;
private $_output_format = 'json';
function __construct ($full = false)
{
$this->_full = $full;
if (array_key_exists('HTTP_ACCEPT', $_SERVER)
&& !preg_match('/\*\/\*/', $_SERVER['HTTP_ACCEPT'])
&& !preg_match('/application\/json/', $_SERVER['HTTP_ACCEPT']))
{
if (preg_match('/application\/whoisi/', $_SERVER['HTTP_ACCEPT']))
{
header("Content-type: application/whoisi");
$this->_output_format = 'whoisi';
}
elseif (preg_match('/application\/newlines/', $_SERVER['HTTP_ACCEPT']))
{
header("Content-type: application/newlines");
$this->_output_format = 'newlines';
}
}
}
function set_format($format)
{
$this->_output_format = $format;
}
function output($sth)
{
if (($rowcount = $sth->rowCount()) > 0)
{
header('X-Weave-Records: ' . $rowcount);
}
if ($this->_output_format == 'newlines')
{
return $this->output_newlines($sth);
}
elseif ($this->_output_format == 'whoisi')
{
return $this->output_whoisi($sth);
}
else
{
return $this->output_json($sth);
}
}
function output_json($sth)
{
echo '[';
while ($result = $sth->fetch(PDO::FETCH_ASSOC))
{
if ($this->_comma_flag) { echo ','; } else { $this->_comma_flag = 1; }
if ($this->_full)
{
$wbo = new wbo();
$wbo->populate($result);
echo $wbo->json();
}
else
echo json_encode($result{'id'});
}
echo ']';
return 1;
}
function output_whoisi($sth)
{
while ($result = $sth->fetch(PDO::FETCH_ASSOC))
{
if ($this->_full)
{
$wbo = new wbo();
$wbo->populate($result);
$output = $wbo->json();
}
else
$output = json_encode($result{'id'});
echo pack('N', mb_strlen($output, '8bit')) . $output;
}
return 1;
}
function output_newlines($sth)
{
while ($result = $sth->fetch(PDO::FETCH_ASSOC))
{
if ($this->_full)
{
$wbo = new wbo();
$wbo->populate($result);
echo preg_replace('/\n/', '\u000a', $wbo->json());
}
else
echo json_encode($result{'id'});
echo "\n";
}
return 1;
}
}
?>

@ -0,0 +1,298 @@
<?php
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Weave Minimal Server
#
# The Initial Developer of the Original Code is
# Mozilla Labs.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Toby Elliott (telliott@mozilla.com)
# Luca Tettamanti
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
require_once 'weave_storage.php';
require_once 'weave_basic_object.php';
require_once 'weave_utils.php';
require_once "WBOJsonOutput.php";
//header("Content-type: application/json");
$server_time = round(microtime(1), 2);
header("X-Weave-Timestamp: " . $server_time);
#Basic path extraction and validation. No point in going on if these are missing
$path = '/';
if (!empty($_SERVER['PATH_INFO']))
$path = $_SERVER['PATH_INFO'];
else if (!empty($_SERVER['ORIG_PATH_INFO']))
$path = $_SERVER['ORIG_PATH_INFO'];
else
report_problem("No path found", 404);
$path = substr($path, 1); #chop the lead slash
log_error("start request_____" . $path);
list($version, $username, $function, $collection, $id) = explode('/', $path.'///');
if($version == 'user' || $version == 'misc')
{
//asking for userApi -> user.php
$include = true;
require 'user.php';
exit(); // should not get here, but how knows
}
header("Content-type: application/json");
if ($version != '1.0' && $version != '1.1')
report_problem('Function not found', 404);
if ($function != "info" && $function != "storage")
report_problem(WEAVE_ERROR_FUNCTION_NOT_SUPPORTED, 400);
if (!validate_username($username))
report_problem(WEAVE_ERROR_INVALID_USERNAME, 400);
#only a delete has meaning without a collection
if ($collection)
{
if (!validate_collection($collection))
report_problem(WEAVE_ERROR_INVALID_COLLECTION, 400);
}
else if ($_SERVER['REQUEST_METHOD'] != 'DELETE')
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
#quick check to make sure that any non-storage function calls are just using GET
if ($function != 'storage' && $_SERVER['REQUEST_METHOD'] != 'GET')
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
#user passes preliminaries, connections made, onto actually getting the data
try
{
$db = new WeaveStorage($username);
#Auth the user
verify_user($username, $db);
#user passes preliminaries, connections made, onto actually getting the data
if ($_SERVER['REQUEST_METHOD'] == 'GET')
{
if ($function == 'info')
{
switch ($collection)
{
case 'quota':
exit(json_encode(array($db->get_storage_total())));
case 'collections':
exit(json_encode($db->get_collection_list_with_timestamps()));
case 'collection_counts':
exit(json_encode($db->get_collection_list_with_counts()));
case 'collection_usage':
$results = $db->get_collection_storage_totals();
foreach (array_keys($results) as $collection)
{
$results[$collection] = ceil($results[$collection] / 1024); #converting to k from bytes
}
exit(json_encode($results));
default:
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
}
}
elseif ($function == 'storage')
{
log_error("function storage");
if ($id) #retrieve a single record
{
$wbo = $db->retrieve_objects($collection, $id, 1); #get the full contents of one record
if (count($wbo) > 0)
{
$item = array_shift($wbo);
echo $item->json();
}
else
report_problem("record not found", 404);
}
else #retrieve a batch of records. Sadly, due to potential record sizes, have the storage object stream the output...
{
log_error("retrieve a batch");
$full = array_key_exists('full', $_GET) && $_GET['full'];
$outputter = new WBOJsonOutput($full);
$params = validate_search_params();
$ids = $db->retrieve_objects($collection, null, $full, $outputter,
$params['parentid'], $params['predecessorid'],
$params['newer'], $params['older'],
$params['sort'],
$params['limit'], $params['offset'],
$params['ids'],
$params['index_above'], $params['index_below'], $params['depth']
);
}
}
}
else if ($_SERVER['REQUEST_METHOD'] == 'PUT') #add a single record to the server
{
$wbo = new wbo();
if (!$wbo->extract_json(get_json()))
report_problem(WEAVE_ERROR_JSON_PARSE, 400);
check_quota($db);
check_timestamp($collection, $db);
#use the url if the json object doesn't have an id
if (!$wbo->id() && $id) { $wbo->id($id); }
$wbo->collection($collection);
$wbo->modified($server_time); #current microtime
if ($wbo->validate())
{
#if there's no payload (as opposed to blank), then update the metadata
if ($wbo->payload_exists())
$db->store_object($wbo);
else
$db->update_object($wbo);
}
else
{
report_problem(WEAVE_ERROR_INVALID_WBO, 400);
}
echo json_encode($server_time);
}
else if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$json = get_json();
check_quota($db);
check_timestamp($collection, $db);
$success_ids = array();
$failed_ids = array();
$db->begin_transaction();
foreach ($json as $wbo_data)
{
$wbo = new wbo();
if (!$wbo->extract_json($wbo_data))
{
$failed_ids[$wbo->id()] = $wbo->get_error();
continue;
}
$wbo->collection($collection);
$wbo->modified($server_time);
if ($wbo->validate())
{
#if there's no payload (as opposed to blank), then update the metadata
if ($wbo->payload_exists())
{
$db->store_object($wbo);
}
else
{
$db->update_object($wbo);
}
$success_ids[] = $wbo->id();
}
else
{
$failed_ids[$wbo->id()] = $wbo->get_error();
}
}
$db->commit_transaction();
echo json_encode(array('success' => $success_ids, 'failed' => $failed_ids));
}
else if ($_SERVER['REQUEST_METHOD'] == 'DELETE')
{
check_timestamp($collection, $db);
if ($id)
{
$db->delete_object($collection, $id);
}
else if ($collection)
{
$params = validate_search_params();
$db->delete_objects($collection, null,
$params['parentid'], $params['predecessorid'],
$params['newer'], $params['older'],
$params['sort'],
$params['limit'], $params['offset'],
$params['ids'],
$params['index_above'], $params['index_below']
);
}
else if($function == 'storage') // ich vermute mal storage reinigen
{
if (!array_key_exists('HTTP_X_CONFIRM_DELETE', $_SERVER))
report_problem(WEAVE_ERROR_NO_OVERWRITE, 412);
$db->delete_storage($username);
}
else
{
if (!array_key_exists('HTTP_X_CONFIRM_DELETE', $_SERVER))
report_problem(WEAVE_ERROR_NO_OVERWRITE, 412);
log_error("delete "."Server ".print_r( $_SERVER, true));
$db->delete_user($username);
}
echo json_encode($server_time);
}
else
{
#bad protocol. There are protocols left? HEAD, I guess.
report_problem(1, 400);
}
}
catch(Exception $e)
{
report_problem($e->getMessage(), $e->getCode());
}
#The datasets we might be dealing with here are too large for sticking it all into an array, so
#we need to define a direct-output method for the storage class to use. If we start producing multiples
#(unlikely), we can put them in their own class.
#include_once "WBOJsonOutput.php";
?>

@ -0,0 +1,14 @@
<?php
//you can disable registration to the firefox sync server here,
// by setting ENABLE_REGISTER to false
//
//
define("ENABLE_REGISTER",false);
//define("ENABLE_REGISTER", true);
//pleas set the URL where firefox clients find the root of
// firefox sync server
// this should end with a /
define("FSYNCMS_ROOT","https://www.your.domain/sync/");
?>

@ -0,0 +1,152 @@
<?php
require_once 'weave_utils.php';
if(!$include) //file should only be used in context of index.php
{
log_error("include error");
report_problem('Function not found', 404);
}
require_once "settings.php";
#Basic path extraction and validation. No point in going on if these are missing
$path = '/';
if (!empty($_SERVER['PATH_INFO']))
$path = $_SERVER['PATH_INFO'];
else if (!empty($_SERVER['ORIG_PATH_INFO']))
$path = $_SERVER['ORIG_PATH_INFO'];
else
{
log_error("user.php: No path found");
report_problem("No path found", 404);
}
$path = substr($path, 1); #chop the lead slash
list($preinstr,$version, $username, $function, $collection, $id) = explode('/', $path.'///');
log_error("Pfad:".$path);
if( $preinstr != 'user' && $preinstr!='misc')
report_problem('Function not found', 404);
if ($version != '1.0')
report_problem('Function not found', 404);
//if captcha
if(($preinstr =='misc') && ($_SERVER['REQUEST_METHOD'] == 'GET') && ($username =='captcha_html'))
{
if(ENABLE_REGISTER)
exit("And click to the next page");
else
exit("Register to this Server is not permitted, sorry");
}
//probably no need but...
header("Content-type: application/json");
//if ($function != "info" && $function != "storage")
// report_problem(WEAVE_ERROR_FUNCTION_NOT_SUPPORTED, 400);
if (!validate_username($username))
{
log_error( "invalid user");
report_problem(WEAVE_ERROR_INVALID_USERNAME, 400);
}
#user passes preliminaries, connections made, onto actually getting the data
try
{
if ($_SERVER['REQUEST_METHOD'] == 'GET')
{
$db = new WeaveStorage($username);
log_error("user.php: GET");
if($function == 'node' && $collection == 'weave') //client fragt node an
{
//to be compatible with users how use /index.php/ in their path
/*$index ="https://";
if (!isset($_SERVER['HTTPS']))
$index = "http://";
$index .= $_SERVER['SERVER_NAME']. dirname($_SERVER['SCRIPT_NAME']) . "/";
if(strpos($_SERVER['REQUEST_URI'],'index.php') !== 0)
$index .= "index.php/";
//antwort (self)i*/
exit(FSYNCMS_ROOT);
}
else if($function == 'password_reset')
{
//email mit neuem pw senden
}
//node/weave
else if($function == '' && $collection == '' && $id =='') //frage nach freiem usernamen
//User exists
{
//$db = new WeaveStorage($username);
if(exists_user($db))
exit(json_encode(1));
else
exit(json_encode(0));
}
else
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
}
else if($_SERVER['REQUEST_METHOD'] == 'PUT')
{
if(ENABLE_REGISTER)
{
$db = new WeaveStorage(null);
//Requests that an account be created for username.
/*
The JSON payload should include
Field Description
password The password to be associated with the account.
email Email address associated with the account
captcha-challenge The challenge string from the captcha (see miscellaneous functions below)
captcha-response The response to the captcha. Only required if WEAVE_REGISTER_USE_CAPTCHA is set
*/
log_error("PUT");
$data = get_json();
log_error(print_r($data,true));
//werte vorhanden
if($data == NULL)
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
$name = $username;
$pwd = fix_utf8_encoding($data['password']);
$email = $data['email'];
if($name == '' || $pwd == '' || $email == '')
{
log_error('create user datenfehler');
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
}
log_error("create user ".$name." pw : ".$pwd);
try{
if ($db->create_user($name, $pwd))
{
log_error("successfully created user");
exit(json_encode(strtolower($name)));
}
else
{
log_error("create user failed");
report_problem('Authentication failed', '401');
}
}
catch(Exception $e)
{
log_error("db exception create user");
header("X-Weave-Backoff: 1800");
report_problem($e->getMessage(), $e->getCode());
}
}
else
{
log_error("register not enabled");
report_problem(WEAVE_ERROR_FUNCTION_NOT_SUPPORTED,400);
}
} // ende put
}
catch(Exception $e)
{
report_problem($e->getMessage(), $e->getCode());
}
#The datasets we might be dealing with here are too large for sticking it all into an array, so
#we need to define a direct-output method for the storage class to use. If we start producing multiples
#(unlikely), we can put them in their own class.
#include_once "WBOJsonOutput.php";
?>

@ -0,0 +1,249 @@
<?php
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Weave Basic Object Server
#
# The Initial Developer of the Original Code is
# Mozilla Labs.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Toby Elliott (telliott@mozilla.com)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
class wbo
{
var $wbo_hash = array();
var $_collection;
var $_error = array();
function extract_json(&$json)
{
$extracted = is_string($json) ? json_decode($json, true) : $json;
#need to check the json was valid here...
if ($extracted === null)
{
$this->_error[] = "unable to extract from json";
return false;
}
#must have an id, or all sorts of badness happens. However, it can be added later
if (array_key_exists('id', $extracted))
{
$this->id($extracted['id']);
}
if (array_key_exists('parentid', $extracted))
{
$this->parentid($extracted['parentid']);
}
if (array_key_exists('predecessorid', $extracted))
{
$this->predecessorid($extracted['predecessorid']);
}
if (array_key_exists('sortindex', $extracted))
{
# Due to complicated logic in the getter, we need to validate
# the value space of sortindex here.
if (!is_numeric($extracted['sortindex'])) {
$this->_error[] = "invalid sortindex";
return false;
}
$this->sortindex($extracted['sortindex']);
}
if (array_key_exists('payload', $extracted))
{
$this->payload($extracted['payload']);
}
return true;
}
function populate(&$datahash)
{
if (array_key_exists('id', $datahash))
$this->id($datahash['id']);
if (array_key_exists('collection', $datahash))
$this->collection($datahash['collection']);
if (array_key_exists('parentid', $datahash))
$this->parentid($datahash['parentid']);
if (array_key_exists('modified', $datahash))
$this->modified($datahash['modified']);
if (array_key_exists('predecessorid', $datahash))
$this->predecessorid($datahash['predecessorid']);
if (array_key_exists('sortindex', $datahash))
$this->sortindex($datahash['sortindex']);
if (array_key_exists('payload', $datahash))
$this->payload($datahash['payload']);
}
function id($id = null)
{
if (!is_null($id)) { $this->wbo_hash['id'] = (string)$id; }
return array_key_exists('id', $this->wbo_hash) ? $this->wbo_hash['id'] : null;
}
function collection($collection = null)
{
if (!is_null($collection)){ $this->_collection = $collection; }
return $this->_collection;
}
function parentid($parentid = null)
{
if (!is_null($parentid)){ $this->wbo_hash['parentid'] = (string)$parentid; }
return array_key_exists('parentid', $this->wbo_hash) ? $this->wbo_hash['parentid'] : null;
}
function parentid_exists()
{
return array_key_exists('parentid', $this->wbo_hash);
}
function predecessorid($predecessorid = null)
{
if (!is_null($predecessorid)){ $this->wbo_hash['predecessorid'] = (string)$predecessorid; }
return array_key_exists('predecessorid', $this->wbo_hash) ? $this->wbo_hash['predecessorid'] : null;
}
function predecessorid_exists()
{
return array_key_exists('predecessorid', $this->wbo_hash);
}
function modified($modified = null)
{
if (!is_null($modified)){ $this->wbo_hash['modified'] = round((float)$modified, 2); }
return array_key_exists('modified', $this->wbo_hash) ? $this->wbo_hash['modified'] : null;
}
function modified_exists()
{
return array_key_exists('modified', $this->wbo_hash);
}
function payload($payload = null)
{
if (!is_null($payload)){ $this->wbo_hash['payload'] = $payload; }
return array_key_exists('payload', $this->wbo_hash) ? $this->wbo_hash['payload'] : null;
}
function payload_exists()
{
return array_key_exists('payload', $this->wbo_hash);
}
function payload_size()
{
return mb_strlen($this->wbo_hash['payload'], '8bit');
}
function sortindex($index = null)
{
if (!is_null($index)){
$this->wbo_hash['sortindex'] = (int)($index);
}
return array_key_exists('sortindex', $this->wbo_hash) ? $this->wbo_hash['sortindex'] : null;
}
function sortindex_exists()
{
return array_key_exists('sortindex', $this->wbo_hash);
}
function validate()
{
if (!$this->id() || mb_strlen($this->id(), '8bit') > 64 || strpos($this->id(), '/') !== false)
{ $this->_error[] = "invalid id"; }
if ($this->parentid_exists() && mb_strlen($this->parentid(), '8bit') > 64)
{ $this->_error[] = "invalid parentid"; }
if ($this->predecessorid_exists() && mb_strlen($this->predecessorid(), '8bit') > 64)
{ $this->_error[] = "invalid predecessorid"; }
if (!is_numeric($this->modified()))
{ $this->_error[] = "invalid modified date"; }
if (!$this->modified())
{ $this->_error[] = "no modification date"; }
if (!$this->_collection || mb_strlen($this->_collection, '8bit') > 64)
{ $this->_error[] = "invalid collection"; }
if ($this->sortindex_exists() &&
(!is_numeric($this->wbo_hash['sortindex']) ||
intval($this->sortindex()) > 999999999 ||
intval($this->sortindex()) < -999999999 ))
{ $this->_error[] = "invalid sortindex"; }
if ($this->payload_exists())
{
if (!is_string($this->wbo_hash['payload']))
{ $this->_error[] = "payload needs to be json-encoded"; }
}
return !$this->get_error();
}
function get_error()
{
return $this->_error;
}
function clear_error()
{
$this->_error = array();
}
function raw_hash()
{
return $this->wbo_hash;
}
function json()
{
return json_encode($this->wbo_hash);
}
}
?>

@ -0,0 +1,864 @@
<?php
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Weave Basic Object Server
#
# The Initial Developer of the Original Code is
# Mozilla Labs.
# Portions created by the Initial Developer are Copyright (C) 2008
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Toby Elliott (telliott@mozilla.com)
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
require_once 'weave_basic_object.php';
class WeaveStorage
{
private $_username;
private $_dbh;
function __construct($username)
{
$this->_username = $username;
$path = explode('/', $_SERVER['SCRIPT_FILENAME']);
$db_name = 'weave_db';
array_pop($path);
array_push($path, $db_name);
$db_name = implode('/', $path);
$create_tables = !file_exists($db_name);
log_error("Weaave Storage created : DBname".$db_name." | username:".$username);
try
{
$this->_dbh = new PDO('sqlite:' . $db_name);
$this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch( PDOException $exception )
{
log_error("database unavailable");
throw new Exception("Database unavailable", 503);
}
if ($create_tables)
{
log_error("sqlite db create");
$this->setup_db();
}
}
function get_connection()
{
return $this->_dbh;
}
function begin_transaction()
{
try
{
$this->_dbh->beginTransaction();
}
catch( PDOException $exception )
{
error_log("begin_transaction: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return 1;
}
function commit_transaction()
{
$this->_dbh->commit();
return 1;
}
function get_max_timestamp($collection)
{
if (!$collection)
{
return 0;
}
try
{
$select_stmt = 'select max(modified) from wbo where username = :username and collection = :collection';
$sth = $this->_dbh->prepare($select_stmt);
$sth->bindParam(':username', $this->_username);
$sth->bindParam(':collection', $collection);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_max_timestamp: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$result = $sth->fetchColumn();
return round((float)$result, 2);
}
function get_collection_list()
{
try
{
$select_stmt = 'select distinct(collection) from wbo where username = :username';
$sth = $this->_dbh->prepare($select_stmt);
$sth->bindParam(':username', $this->_username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_collection_list: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$collections = array();
while ($result = $sth->fetchColumn())
{
$collections[] = $result;
}
return $collections;
}
function get_collection_list_with_timestamps()
{
try
{
$select_stmt = 'select collection, max(modified) as timestamp from wbo where username = :username group by collection';
$sth = $this->_dbh->prepare($select_stmt);
$sth->bindParam(':username', $this->_username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_collection_list: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$collections = array();
while ($result = $sth->fetch(PDO::FETCH_NUM))
{
$collections[$result[0]] = (float)$result[1];
}
return $collections;
}
function get_collection_list_with_counts()
{
try
{
$select_stmt = 'select collection, count(*) as ct from wbo where username = :username group by collection';
$sth = $this->_dbh->prepare($select_stmt);
$sth->bindParam(':username', $this->_username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_collection_list_with_counts: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$collections = array();
while ($result = $sth->fetch(PDO::FETCH_NUM))
{
$collections[$result[0]] = (int)$result[1];
}
return $collections;
}
function store_object(&$wbo)
{
try
{
$insert_stmt = 'replace into wbo (username, id, collection, parentid, predecessorid, sortindex, modified, payload, payload_size)
values (:username, :id, :collection, :parentid, :predecessorid, :sortindex, :modified, :payload, :payload_size)';
$sth = $this->_dbh->prepare($insert_stmt);
$username = $this->_username;
$id = $wbo->id();
$collection = $wbo->collection();
$parentid = $wbo->parentid();
$predecessorid = $wbo->predecessorid();
$sortindex = $wbo->sortindex();
$modified = $wbo->modified();
$payload = $wbo->payload();
$payload_size = $wbo->payload_size();
$sth->bindParam(':username', $username);
$sth->bindParam(':id', $id);
$sth->bindParam(':collection', $collection);
$sth->bindParam(':parentid', $parentid);
$sth->bindParam(':predecessorid', $predecessorid);
$sth->bindParam(':sortindex', $sortindex);
$sth->bindParam(':modified', $modified);
$sth->bindParam(':payload', $payload);
$sth->bindParam(':payload_size', $payload_size);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("store_object: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return 1;
}
function update_object(&$wbo)
{
$update = "update wbo set ";
$params = array();
$update_list = array();
#make sure we have an id and collection. No point in continuing otherwise
if (!$wbo->id() || !$wbo->collection())
{
error_log('Trying to update without a valid id or collection!');
return 0;
}
if ($wbo->parentid_exists())
{
$update_list[] = "parentid = ?";
$params[] = $wbo->parentid();
}
if ($wbo->predecessorid_exists())
{
$update_list[] = "predecessorid = ?";
$params[] = $wbo->predecessorid();
}
if ($wbo->sortindex_exists())
{
$update_list[] = "sortindex = ?";
$params[] = $wbo->sortindex();
}
if ($wbo->payload_exists())
{
$update_list[] = "payload = ?";
$update_list[] = "payload_size = ?";
$params[] = $wbo->payload();
$params[] = $wbo->payload_size();
}
# Don't modify the timestamp on a non-payload/non-parent change change
if ($wbo->parentid_exists() || $wbo->payload_exists())
{
#better make sure we have a modified date. Should have been handled earlier
if (!$wbo->modified_exists())
{
error_log("Called update_object with no defined timestamp. Please check");
$wbo->modified(microtime(1));
}
$update_list[] = "modified = ?";
$params[] = $wbo->modified();
}
if (count($params) == 0)
{
return 0;
}
$update .= join($update_list, ",");
$update .= " where username = ? and collection = ? and id = ?";
$params[] = $this->_username;
$params[] = $wbo->collection();
$params[] = $wbo->id();
try
{
$sth = $this->_dbh->prepare($update);
$sth->execute($params);
}
catch( PDOException $exception )
{
error_log("update_object: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return 1;
}
function delete_object($collection, $id)
{
try
{
$delete_stmt = 'delete from wbo where username = :username and collection = :collection and id = :id';
$sth = $this->_dbh->prepare($delete_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->bindParam(':collection', $collection);
$sth->bindParam(':id', $id);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("delete_object: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return 1;
}
function delete_objects($collection, $id = null, $parentid = null, $predecessorid = null, $newer = null,
$older = null, $sort = null, $limit = null, $offset = null, $ids = null,
$index_above = null, $index_below = null)
{
$params = array();
$select_stmt = '';
if ($limit || $offset || $sort)
{
#sqlite can't do sort or limit deletes without special compiled versions
#so, we need to grab the set, then delete it manually.
$params = $this->retrieve_objects($collection, $id, 0, 0, $parentid, $predecessorid, $newer, $older, $sort, $limit, $offset, $ids, $index_above, $index_below);
if (!count($params))
{
return 1; #nothing to delete
}
$paramqs = array();
$select_stmt = "delete from wbo where username = ? and collection = ? and id in (" . join(", ", array_pad($paramqs, count($params), '?')) . ")";
array_unshift($params, $collection);
array_unshift($params, $username);
}
else
{
$select_stmt = "delete from wbo where username = ? and collection = ?";
$params[] = $this->_username;
$params[] = $collection;
if ($id)
{
$select_stmt .= " and id = ?";
$params[] = $id;
}
if ($ids && count($ids) > 0)
{
$qmarks = array();
$select_stmt .= " and id in (";
foreach ($ids as $temp)
{
$params[] = $temp;
$qmarks[] = '?';
}
$select_stmt .= implode(",", $qmarks);
$select_stmt .= ')';
}
if ($parentid)
{
$select_stmt .= " and parentid = ?";
$params[] = $parentid;
}
if ($predecessorid)
{
$select_stmt .= " and predecessorid = ?";
$params[] = $parentid;
}
if ($index_above)
{
$select_stmt .= " and sortindex > ?";
$params[] = $parentid;
}
if ($index_below)
{
$select_stmt .= " and sortindex < ?";
$params[] = $parentid;
}
if ($newer)
{
$select_stmt .= " and modified > ?";
$params[] = $newer;
}
if ($older)
{
$select_stmt .= " and modified < ?";
$params[] = $older;
}
if ($sort == 'index')
{
$select_stmt .= " order by sortindex desc";
}
else if ($sort == 'newest')
{
$select_stmt .= " order by modified desc";
}
else if ($sort == 'oldest')
{
$select_stmt .= " order by modified";
}
}
try
{
$sth = $this->_dbh->prepare($select_stmt);
$sth->execute($params);
}
catch( PDOException $exception )
{
error_log("delete_objects: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return 1;
}
function retrieve_object($collection, $id)
{
try
{
$select_stmt = 'select * from wbo where username = :username and collection = :collection and id = :id';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->bindParam(':collection', $collection);
$sth->bindParam(':id', $id);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("retrieve_object: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$result = $sth->fetch(PDO::FETCH_ASSOC);
$wbo = new wbo();
$wbo->populate($result);
return $wbo;
}
function retrieve_objects($collection, $id = null, $full = null, $direct_output = null, $parentid = null,
$predecessorid = null, $newer = null, $older = null, $sort = null,
$limit = null, $offset = null, $ids = null,
$index_above = null, $index_below = null)
{
$full_list = $full ? '*' : 'id';
$select_stmt = "select $full_list from wbo where username = ? and collection = ?";
$params[] = $this->_username;
$params[] = $collection;
if ($id)
{
$select_stmt .= " and id = ?";
$params[] = $id;
}
if ($ids && count($ids) > 0)
{
$qmarks = array();
$select_stmt .= " and id in (";
foreach ($ids as $temp)
{
$params[] = $temp;
$qmarks[] = '?';
}
$select_stmt .= implode(",", $qmarks);
$select_stmt .= ')';
}
if ($parentid)
{
$select_stmt .= " and parentid = ?";
$params[] = $parentid;
}
if ($predecessorid)
{
$select_stmt .= " and predecessorid = ?";
$params[] = $predecessorid;
}
if ($index_above)
{
$select_stmt .= " and sortindex > ?";
$params[] = $parentid;
}
if ($index_below)
{
$select_stmt .= " and sortindex < ?";
$params[] = $parentid;
}
if ($newer)
{
$select_stmt .= " and modified > ?";
$params[] = $newer;
}
if ($older)
{
$select_stmt .= " and modified < ?";
$params[] = $older;
}
if ($sort == 'index')
{
$select_stmt .= " order by sortindex desc";
}
else if ($sort == 'newest')
{
$select_stmt .= " order by modified desc";
}
else if ($sort == 'oldest')
{
$select_stmt .= " order by modified";
}
if ($limit)
{
$select_stmt .= " limit " . intval($limit);
if ($offset)
{
$select_stmt .= " offset " . intval($offset);
}
}
try
{
$sth = $this->_dbh->prepare($select_stmt);
$sth->execute($params);
}
catch( PDOException $exception )
{
error_log("retrieve_collection: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
if ($direct_output)
return $direct_output->output($sth);
$ids = array();
while ($result = $sth->fetch(PDO::FETCH_ASSOC))
{
if ($full)
{
$wbo = new wbo();
$wbo->populate($result);
$ids[] = $wbo;
}
else
$ids[] = $result{'id'};
}
return $ids;
}
function get_storage_total()
{
try
{
$select_stmt = 'select round(sum(length(payload))/1024) from wbo where username = :username';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_storage_total: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
return (int)$sth->fetchColumn();
}
function get_collection_storage_totals()
{
try
{
$select_stmt = 'select collection, sum(payload_size) from wbo where username = :username group by collection';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("get_storage_total (" . $this->connection_details_string() . "): " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
$results = $sth->fetchAll(PDO::FETCH_NUM);
$sth->closeCursor();
$collections = array();
foreach ($results as $result)
{
$collections[$result[0]] = (int)$result[1];
}
return $collections;
}
function get_user_quota()
{
return null;
}
function delete_storage($username)
{
log_error("delete storage");
if (!$username)
{
throw new Exception("3", 404);
}
try
{
$delete_stmt = 'delete from wbo where username = :username';
$sth = $this->_dbh->prepare($delete_stmt);
$sth->bindParam(':username', $username);
$sth->execute();
$sth->closeCursor();
}
catch( PDOException $exception )
{
error_log("delete_user: " . $exception->getMessage());
return 0;
}
return 1;
}
function delete_user($username)
{
log_error("delete User");
if (!$username)
{
throw new Exception("3", 404);
}
try
{
$delete_stmt = 'delete from users where username = :username';
$sth = $this->_dbh->prepare($delete_stmt);
$sth->bindParam(':username', $username);
$sth->execute();
$sth->closeCursor();
$delete_wbo_stmt = 'delete from wbo where username = :username';
$sth = $this->_dbh->prepare($delete_wbo_stmt);
$sth->bindParam(':username', $username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("delete_user: " . $exception->getMessage());
return 0;
}
return 1;
}
function create_user($username, $password)
{
log_error("Create User - Username: ".$username."|".$password);
/*try
{
$select_stmt = 'select username from users where username = :username';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("exists_user: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}*/
try
{
$create_statement = "insert into users values (:username, :md5)";
$sth = $this->_dbh->prepare($create_statement);
$password = md5($password);
$sth->bindParam(':username', $username);
$sth->bindParam(':md5', $password);
$sth->execute();
}
catch( PDOException $exception )
{
log_error("create_user:" . $exception->getMessage());
error_log("create_user:" . $exception->getMessage());
return 0;
}
return 1;
}
function change_password($username, $password)
{
try
{
$update_statement = "update users set md5 = :md5 where username = :username";
$sth = $this->_dbh->prepare($update_statement);
$password = md5($password);
$sth->bindParam(':username', $username);
$sth->bindParam(':md5', $password);
$sth->execute();
}
catch( PDOException $exception )
{
log_error("change_password:" . $exception->getMessage());
return 0;
}
return 1;
}
#function checks if user exists
function exists_user()
{
try
{
$select_stmt = 'select username from users where username = :username';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$sth->bindParam(':username', $username);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("exists_user: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
if (!$result = $sth->fetch(PDO::FETCH_ASSOC))
{
return null;
}
return 1;
}
function authenticate_user($password)
{
try
{
$select_stmt = 'select username from users where username = :username and md5 = :md5';
$sth = $this->_dbh->prepare($select_stmt);
$username = $this->_username;
$password = md5($password);
$sth->bindParam(':username', $username);
$sth->bindParam(':md5', $password);
$sth->execute();
}
catch( PDOException $exception )
{
error_log("authenticate_user: " . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
if (!$result = $sth->fetch(PDO::FETCH_ASSOC))
{
return null;
}
return 1;
}
function setup_db()
{
try
{
$create_statement ="
create table wbo
(
username text,
id text,
collection text,
parentid text,
predecessorid int,
modified real,
sortindex int,
payload text,
payload_size int,
ttl int,
primary key (username,collection,id)
)";
$create_statement2 = "
create table users
(
username text,
md5 text,
primary key (username)
)
";
$index1 = 'create index parentindex on wbo (username, parentid)';
$index2 = 'create index predecessorindex on wbo (username, predecessorid)';
$index3 = 'create index modifiedindex on wbo (username, collection, modified)';
$sth = $this->_dbh->prepare($create_statement);
$sth->execute();
$sth = $this->_dbh->prepare($create_statement2);
$sth->execute();
$sth = $this->_dbh->prepare($index1);
$sth->execute();
$sth = $this->_dbh->prepare($index2);
$sth->execute();
$sth = $this->_dbh->prepare($index3);
$sth->execute();
}
catch( PDOException $exception )
{
log_error("initialize_user_db:" . $exception->getMessage());
throw new Exception("Database unavailable", 503);
}
}
}
?>

@ -0,0 +1,228 @@
<?php
#Error constants
define ('WEAVE_ERROR_INVALID_PROTOCOL', 1);
define ('WEAVE_ERROR_INCORRECT_CAPTCHA', 2);
define ('WEAVE_ERROR_INVALID_USERNAME', 3);
define ('WEAVE_ERROR_NO_OVERWRITE', 4);
define ('WEAVE_ERROR_USERID_PATH_MISMATCH', 5);
define ('WEAVE_ERROR_JSON_PARSE', 6);
define ('WEAVE_ERROR_MISSING_PASSWORD', 7);
define ('WEAVE_ERROR_INVALID_WBO', 8);
define ('WEAVE_ERROR_BAD_PASSWORD_STRENGTH', 9);
define ('WEAVE_ERROR_INVALID_RESET_CODE', 10);
define ('WEAVE_ERROR_FUNCTION_NOT_SUPPORTED', 11);
define ('WEAVE_ERROR_NO_EMAIL', 12);
define ('WEAVE_ERROR_INVALID_COLLECTION', 13);
function log_error($msg)
{
#$datei = fopen("error.txt","a");
#fputs($datei,$msg."
#");
#fputs($datei,"Server ".print_r( $_SERVER, true));
#fclose($datei);
}
function report_problem($message, $code = 503)
{
$headers = array('400' => '400 Bad Request',
'401' => '401 Unauthorized',
'403' => '403 Forbidden',
'404' => '404 Not Found',
'412' => '412 Precondition Failed',
'503' => '503 Service Unavailable');
header('HTTP/1.1 ' . $headers{$code},true,$code);
if ($code == 401)
{
header('WWW-Authenticate: Basic realm="Weave"');
}
log_error($message);
exit(json_encode($message));
}
function fix_utf8_encoding($string)
{
if(mb_detect_encoding($string . " ", 'UTF-8,ISO-8859-1') == 'UTF-8')
return $string;
else
return utf8_encode($string);
}
function get_json()
{
#stupid php being helpful with input data...
$putdata = fopen("php://input", "r");
$jsonstring = '';
while ($data = fread($putdata,2048)) {$jsonstring .= $data;}
$json = json_decode(fix_utf8_encoding($jsonstring), true);
if ($json === null)
report_problem(WEAVE_ERROR_JSON_PARSE, 400);
return $json;
}
function validate_username($username)
{
if (!$username)
return false;
if (strlen($username) > 32)
return false;
return preg_match('/[^A-Z0-9._-]/i', $username) ? false : true;
}
function validate_collection($collection)
{
if (!$collection)
return false;
if (strlen($collection) > 32)
return false;
return preg_match('/[^A-Z0-9._-]/i', $collection) ? false : true;
}
#user exitsts
function exists_user( $db)
{
#$user = strtolower($user);
try{
if(!$db->exists_user())
return 0;
return 1;
}
catch(Exception $e)
{
header("X-Weave-Backoff: 1800");
report_problem($e->getMessage(), $e->getCode());
}
}
# Gets the username and password out of the http headers, and checks them against the auth
function verify_user($url_user, $db)
{
if (!$url_user || !preg_match('/^[A-Z0-9._-]+$/i', $url_user))
report_problem(WEAVE_ERROR_INVALID_USERNAME, 400);
$auth_user = array_key_exists('PHP_AUTH_USER', $_SERVER) ? $_SERVER['PHP_AUTH_USER'] : null;
$auth_pw = array_key_exists('PHP_AUTH_PW', $_SERVER) ? $_SERVER['PHP_AUTH_PW'] : null;
if (is_null($auth_user) || is_null($auth_pw))
{
/* CGI/FCGI auth workarounds */
$auth_str = null;
if (array_key_exists('Authorization', $_SERVER))
/* Standard fastcgi configuration */
$auth_str = $_SERVER['Authorization'];
else if (array_key_exists('AUTHORIZATION', $_SERVER))
/* Alternate fastcgi configuration */
$auth_str = $_SERVER['AUTHORIZATION'];
else if (array_key_exists('HTTP_AUTHORIZATION', $_SERVER))
/* IIS/ISAPI and newer (yet to be released) fastcgi */
$auth_str = $_SERVER['HTTP_AUTHORIZATION'];
else if (array_key_exists('REDIRECT_HTTP_AUTHORIZATION', $_SERVER))
/* mod_rewrite - per-directory internal redirect */
$auth_str = $_SERVER['REDIRECT_HTTP_AUTHORIZATION'];
if (!is_null($auth_str))
{
/* Basic base64 auth string */
if (preg_match('/Basic\s+(.*)$/', $auth_str))
{
$auth_str = substr($auth_str, 6);
$auth_str = base64_decode($auth_str, true);
if ($auth_str != FALSE) {
$tmp = explode(':', $auth_str);
if (count($tmp) == 2)
{
$auth_user = $tmp[0];
$auth_pw = $tmp[1];
}
}
}
}
}
if (!$auth_user || !$auth_pw) #do this first to avoid the cryptic error message if auth is missing
{
log_error("Auth failed{");
log_error(" User pw:".$auth_user."|".$auth_pw);
log_error(" Url_user:".$url_user);
log_error("}");
report_problem('Authentication failed', '401');
}
$url_user = strtolower($url_user);
if (strtolower($auth_user) != $url_user)
{
log_error("(140) Missmatch:".strtolower($auth_user)."|".$url_user);
report_problem(WEAVE_ERROR_USERID_PATH_MISMATCH, 400);
}
try
{
if (!$db->authenticate_user(fix_utf8_encoding($auth_pw)))
{
log_error("Auth failed{");
log_error(" User pw:".$auth_user."|".$auth_pw ."|md5:".md5($auth_pw)."|fix:".fix_utf8_encoding($auth_pw)."|fix md5". md5(fix_utf8_encoding($auth_pw)));
log_error(" Url_user:".$url_user);
log_error("}");
report_problem('Authentication failed', '401');
}
}
catch(Exception $e)
{
header("X-Weave-Backoff: 1800");
report_problem($e->getMessage(), $e->getCode());
}
return true;
}
function check_quota(&$db)
{
return;
}
function check_timestamp($collection, &$db)
{
if (array_key_exists('HTTP_X_IF_UNMODIFIED_SINCE', $_SERVER)
&& $db->get_max_timestamp($collection) > $_SERVER['HTTP_X_IF_UNMODIFIED_SINCE'])
report_problem(WEAVE_ERROR_NO_OVERWRITE, 412);
}
function validate_search_params()
{
$params = array();
$params['parentid'] = (array_key_exists('parentid', $_GET) && mb_strlen($_GET['parentid'], '8bit') <= 64 && strpos($_GET['parentid'], '/') === false) ? $_GET['parentid'] : null;
$params['predecessorid'] = (array_key_exists('predecessorid', $_GET) && mb_strlen($_GET['predecessorid'], '8bit') <= 64 && strpos($_GET['predecessorid'], '/') === false) ? $_GET['predecessorid'] : null;
$params['newer'] = (array_key_exists('newer', $_GET) && is_numeric($_GET['newer'])) ? round($_GET['newer'],2) : null;
$params['older'] = (array_key_exists('older', $_GET) && is_numeric($_GET['older'])) ? round($_GET['older'],2) : null;
$params['sort'] = (array_key_exists('sort', $_GET) && ($_GET['sort'] == 'oldest' || $_GET['sort'] == 'newest' || $_GET['sort'] == 'index')) ? $_GET['sort'] : null;
$params['limit'] = (array_key_exists('limit', $_GET) && is_numeric($_GET['limit']) && $_GET['limit'] > 0) ? (int)$_GET['limit'] : null;
$params['offset'] = (array_key_exists('offset', $_GET) && is_numeric($_GET['offset']) && $_GET['offset'] > 0) ? (int)$_GET['offset'] : null;
$params['ids'] = null;
if (array_key_exists('ids', $_GET))
{
$params['ids'] = array();
foreach(explode(',', $_GET['ids']) as $id)
{
if (mb_strlen($id, '8bit') <= 64 && strpos($id, '/') === false)
$params['ids'][] = $id;
}
}
$params['index_above'] = (array_key_exists('index_above', $_GET) && is_numeric($_GET['index_above']) && $_GET['index_above'] > 0) ? (int)$_GET['index_above'] : null;
$params['index_below'] = (array_key_exists('index_below', $_GET) && is_numeric($_GET['index_below']) && $_GET['index_below'] > 0) ? (int)$_GET['index_below'] : null;
$params['depth'] = (array_key_exists('depth', $_GET) && is_numeric($_GET['depth']) && $_GET['depth'] > 0) ? (int)$_GET['depth'] : null;
return $params;
}
?>
Loading…
Cancel
Save