mirror of
https://github.com/YunoHost-Apps/ffsync_ynh.git
synced 2024-09-03 18:26:38 +02:00
first commit
This commit is contained in:
commit
027ac79654
17 changed files with 2978 additions and 0 deletions
16
conf/nginx.conf
Normal file
16
conf/nginx.conf
Normal file
|
@ -0,0 +1,16 @@
|
|||
location PATHTOCHANGE {
|
||||
alias ALIASTOCHANGE;
|
||||
if ($scheme = http) {
|
||||
rewrite ^ https://$server_name$request_uri? permanent;
|
||||
}
|
||||
index index.php;
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
location ~ [^/]\.php(/|$) {
|
||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||
fastcgi_pass unix:/var/run/php5-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param REMOTE_USER $remote_user;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
}
|
||||
}
|
26
conf/settings.php
Normal file
26
conf/settings.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
// you can disable registration to the firefox sync server here,
|
||||
// by setting ENABLE_REGISTER to false
|
||||
//
|
||||
define("ENABLE_REGISTER", true);
|
||||
|
||||
// firefox sync server url, this should end with a /
|
||||
// e.g. https://YourDomain.de/Folder_und_ggf_/index.php/
|
||||
//
|
||||
define("FSYNCMS_ROOT", "https://URLFFSYNC/");
|
||||
|
||||
// Database connection credentials
|
||||
//
|
||||
define("SQLITE_FILE", "weave_db");
|
||||
define("MYSQL_ENABLE", true);
|
||||
define("MYSQL_HOST", "localhost");
|
||||
define("MYSQL_DB", "yunobase");
|
||||
define("MYSQL_USER", "yunouser");
|
||||
define("MYSQL_PASSWORD", "yunopass");
|
||||
|
||||
// Use bcrypt instead of MD5 for password hashing
|
||||
define("BCRYPT", true);
|
||||
define("BCRYPT_ROUNDS", 12);
|
||||
|
||||
?>
|
33
manifest.json
Normal file
33
manifest.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "Firefox Sync Server",
|
||||
"id": "ffsync",
|
||||
"description": {
|
||||
"en": "",
|
||||
"fr": ""
|
||||
},
|
||||
"developer": {
|
||||
"name": "beudbeud",
|
||||
"email": "beudbeud@beudibox.fr",
|
||||
"url": "https://github.com/balu-/FSyncMS"
|
||||
},
|
||||
"multi_instance": "false",
|
||||
"arguments": {
|
||||
"install" : [
|
||||
{
|
||||
"name": "domain",
|
||||
"ask": {
|
||||
"en": "Choose a domain for Firefox-Sync Server"
|
||||
},
|
||||
"example": "domain.org"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"ask": {
|
||||
"en": "Choose a path for Firefox-Sync Server"
|
||||
},
|
||||
"example": "/ffsync",
|
||||
"default": "/ffsync"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
46
scripts/install
Normal file
46
scripts/install
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Retrieve arguments
|
||||
domain=$1
|
||||
path=$2
|
||||
|
||||
# Check domain/path availability
|
||||
sudo yunohost app checkurl $domain$path -a ffsync
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate random password
|
||||
db_pwd=$(dd if=/dev/urandom bs=1 count=200 2> /dev/null | tr -c -d '[A-Za-z0-9]' | sed -n 's/\(.\{24\}\).*/\1/p')
|
||||
|
||||
# Use 'FSyncMS' as database name and user
|
||||
db_user=ffsync
|
||||
|
||||
# Initialize database and store mysql password for upgrade
|
||||
sudo yunohost app initdb $db_user -p $db_pwd
|
||||
sudo yunohost app setting ffsync mysqlpwd -v $db_pwd
|
||||
|
||||
# Copy files to the right place
|
||||
final_path=/var/www/ffsync
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -a ../sources/* $final_path
|
||||
sudo cp ../conf/settings.php $final_path/
|
||||
|
||||
# Change variables in FSyncMS configuration
|
||||
sudo sed -i "s/yunouser/$db_user/g" $final_path/settings.php
|
||||
sudo sed -i "s/yunopass/$db_pwd/g" $final_path/settings.php
|
||||
sudo sed -i "s/yunobase/$db_user/g" $final_path/settings.php
|
||||
sudo sed -i "s@URLFFSYNC@$domain$path@g" $final_path/settings.php
|
||||
|
||||
# Set permissions to roundcube directory
|
||||
sudo chown -R www-data: $final_path
|
||||
|
||||
# Modify Nginx configuration file and copy it to Nginx conf directory
|
||||
sed -i "s@PATHTOCHANGE@$path@g" ../conf/nginx.conf*
|
||||
sed -i "s@ALIASTOCHANGE@$final_path/@g" ../conf/nginx.conf*
|
||||
sudo cp ../conf/nginx.conf /etc/nginx/conf.d/$domain.d/wordpress.conf
|
||||
|
||||
# Reload Nginx and regenerate SSOwat conf
|
||||
sudo service nginx reload
|
||||
sudo yunohost app setting ffsync skipped_uris -v "/"
|
||||
sudo yunohost app ssowatconf
|
10
scripts/remove
Normal file
10
scripts/remove
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
db_user=wordpress
|
||||
db_name=wordpress
|
||||
root_pwd=$(sudo cat /etc/yunohost/mysql)
|
||||
domain=$(sudo yunohost app setting ffsync domain)
|
||||
|
||||
mysql -u root -p$root_pwd -e "DROP DATABASE $db_name ; DROP USER $db_user@localhost ;"
|
||||
sudo rm -rf /var/www/ffsync
|
||||
sudo rm -f /etc/nginx/conf.d/$domain.d/ffsync.conf
|
2
sources/.gitignore
vendored
Normal file
2
sources/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*~
|
||||
*.swp
|
81
sources/README.md
Normal file
81
sources/README.md
Normal file
|
@ -0,0 +1,81 @@
|
|||
FSyncMS
|
||||
=======
|
||||
|
||||
PHP Sync Server für Firefox Sync
|
||||
Eine Erweiterung des Weave-Minimal Server (dessen Support leider eingestellt wurde).
|
||||
|
||||
Die derzeit aktuelle Versionen,
|
||||
sowie alte Versionen und Anleitungen sind hier:
|
||||
|
||||
https://www.ohnekontur.de/category/technik/sync/fsyncms/
|
||||
|
||||
zu finden.
|
||||
Weitere Erweiterungen sind in Planung.
|
||||
Stay tuned.
|
||||
|
||||
|
||||
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 v013
|
||||
======
|
||||
Database upgrade
|
||||
for more information and some migration notice see
|
||||
http://www.ohnekontur.de/2013/07/05/fsyncms-version-0-13-database-upgrade/
|
||||
|
||||
|
||||
FSyncMS v012
|
||||
======
|
||||
Compatibility update
|
||||
|
||||
FSyncMS v011
|
||||
======
|
||||
Added dedicated setup script, which will create the database and the config file: settings.php
|
||||
|
||||
If you want to create it by your own, just generate the settings.php with the following content
|
||||
|
||||
<?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://DOMAIN.de/Folder_und_ggf_/index.php/");
|
||||
|
||||
//MYSQL Params
|
||||
define("MYSQL_ENABLE", false);
|
||||
define("MYSQL_HOST","localhost");
|
||||
define("MYSQL_DB","databaseName");
|
||||
define("MYSQL_USER", "databaseUserName");
|
||||
define("MYSQL_PASSWORD", "databaseUserPW");
|
||||
|
||||
?>
|
||||
|
||||
|
||||
FSyncMS v010
|
||||
======
|
||||
MYSQL Support
|
||||
|
||||
FSyncMS v 09
|
||||
======
|
||||
Change Password now supported
|
||||
working with firefox 12 (and lower)
|
||||
|
||||
Changelog:
|
||||
Added change Password feature
|
||||
|
||||
FSyncMS v 08
|
||||
======
|
||||
Should be working with firefox 11 and lower (tested with 11)
|
||||
|
||||
Changelog:
|
||||
Fixed user registration process,
|
||||
fixed some delete problems
|
7
sources/TODO
Normal file
7
sources/TODO
Normal file
|
@ -0,0 +1,7 @@
|
|||
== SOME TODOS ==
|
||||
|
||||
- Ein Präfix für die Tabellen, damit sie in eine vorhandene DB gelegt werden können.
|
||||
|
||||
|
||||
- NOTIZ: Update der md5 Spalte der Usertabelle von length 64 auf length 124
|
||||
- >ALTER TABLE `users` CHANGE `md5` `md5` VARCHAR( 124 ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NULL DEFAULT NULL
|
154
sources/WBOJsonOutput.php
Normal file
154
sources/WBOJsonOutput.php
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
||||
?>
|
329
sources/index.php
Normal file
329
sources/index.php
Normal file
|
@ -0,0 +1,329 @@
|
|||
<?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 *****
|
||||
|
||||
if ( ! file_exists("settings.php") && file_exists("setup.php") ) {
|
||||
require_once "setup.php";
|
||||
exit;
|
||||
|
||||
} else if ( ! file_exists("settings.php") ) {
|
||||
echo "<hr><h2>Maybe the setup is not completed, missing settings.php</h2><hr>";
|
||||
exit;
|
||||
|
||||
} else if ( file_exists("setup.php") ) {
|
||||
echo "<hr><h2>Maybe the setup is not completed, else please delete setup.php</h2><hr>";
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'weave_storage.php';
|
||||
require_once 'weave_basic_object.php';
|
||||
require_once 'weave_utils.php';
|
||||
require_once 'weave_hash.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 if (!empty($_SERVER["REQUEST_URI"]))
|
||||
{
|
||||
log_error("experimental path");
|
||||
# this is kind of an experimental try, i needed it so i build it,
|
||||
# but that doesent mean that it does work... well it works for me
|
||||
# and it shouldnt break anything...
|
||||
$path = $_SERVER["REQUEST_URI"];
|
||||
$lastfolder = substr(FSYNCMS_ROOT,strrpos(FSYNCMS_ROOT, "/",-2));
|
||||
$path = substr($path, (strpos($path,$lastfolder) + strlen($lastfolder)-1)); #chop the lead slash
|
||||
if(strpos($path,'?') != false)
|
||||
$path = substr($path, 0, strpos($path,'?')); //remove php arguments
|
||||
log_error("path_exp:".$path);
|
||||
}
|
||||
else
|
||||
report_problem("No path found", 404);
|
||||
|
||||
$path = substr($path, 1); #chop the lead slash
|
||||
log_error("start request_____" . $path);
|
||||
// ensure that we got a valid request
|
||||
if ( !$path )
|
||||
report_problem("Invalid request, this was not a firefox sync request!", 400);
|
||||
|
||||
// split path into parts and make sure that all values are properly initialized
|
||||
list($version, $username, $function, $collection, $id) = array_pad(explode('/', $path.'///'), 5, '');
|
||||
|
||||
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";
|
||||
?>
|
399
sources/setup.php
Normal file
399
sources/setup.php
Normal file
|
@ -0,0 +1,399 @@
|
|||
<?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
|
||||
# Stefan Fischer
|
||||
# Portions created by the Initial Developer are Copyright (C) 2012
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Daniel Triendl <daniel@pew.cc>
|
||||
# balu
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
// --------------------------------------------
|
||||
// variables start
|
||||
// --------------------------------------------
|
||||
$action = null;
|
||||
$dbType = null;
|
||||
|
||||
$dbUser = null;
|
||||
$dbName = null;
|
||||
$dbPass = null;
|
||||
$dbHost = null;
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
// variables end
|
||||
// --------------------------------------------
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
// post handling start
|
||||
// --------------------------------------------
|
||||
if ( isset( $_POST['action'] ) ) {
|
||||
$action = check_input($_POST['action']);
|
||||
}
|
||||
|
||||
if ( isset( $_POST['dbType'] ) ) {
|
||||
$dbType = check_input($_POST['dbType']);
|
||||
}
|
||||
|
||||
if ( isset( $_POST['dbhost'] ) ) {
|
||||
$dbHost = check_input($_POST['dbhost']);
|
||||
}
|
||||
|
||||
if ( isset( $_POST['dbname'] ) ) {
|
||||
$dbName = check_input($_POST['dbname']);
|
||||
}
|
||||
|
||||
if ( isset( $_POST['dbuser'] ) ) {
|
||||
$dbUser = check_input($_POST['dbuser']);
|
||||
}
|
||||
|
||||
if ( isset( $_POST['dbpass'] ) ) {
|
||||
$dbPass = check_input($_POST['dbpass']);
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// post handling end
|
||||
// --------------------------------------------
|
||||
|
||||
|
||||
// --------------------------------------------
|
||||
// functions start
|
||||
// --------------------------------------------
|
||||
|
||||
/*
|
||||
ensure that the input is not total waste
|
||||
*/
|
||||
function check_input( $data ) {
|
||||
$data = trim($data);
|
||||
$data = stripslashes($data);
|
||||
$data = htmlspecialchars($data);
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
create the config file with the database type
|
||||
and the given connection credentials
|
||||
*/
|
||||
function write_config_file($dbt, $dbh, $dbn, $dbu, $dbp, $fsRoot) {
|
||||
|
||||
// construct the name of config file
|
||||
//
|
||||
$path = explode('/', $_SERVER['SCRIPT_FILENAME']);
|
||||
array_pop($path);
|
||||
array_push($path, 'settings.php');
|
||||
$cfg_file_name = implode('/', $path);
|
||||
|
||||
if ( file_exists($cfg_file_name) && filesize( $cfg_file_name ) > 0 ) {
|
||||
echo "<hr>The config file $cfg_file_name is already present</hr>";
|
||||
return;
|
||||
}
|
||||
|
||||
echo "Creating cfg file: " . $cfg_file_name;
|
||||
|
||||
// now build the content of the config file
|
||||
//
|
||||
$cfg_content = "<?php\n\n";
|
||||
$cfg_content .= " // you can disable registration to the firefox sync server here,\n";
|
||||
$cfg_content .= " // by setting ENABLE_REGISTER to false\n";
|
||||
$cfg_content .= " // \n";
|
||||
$cfg_content .= " define(\"ENABLE_REGISTER\", true);\n\n";
|
||||
|
||||
$cfg_content .= " // firefox sync server url, this should end with a /\n";
|
||||
$cfg_content .= " // e.g. https://YourDomain.de/Folder_und_ggf_/index.php/\n";
|
||||
$cfg_content .= " // \n";
|
||||
$cfg_content .= " define(\"FSYNCMS_ROOT\", \"$fsRoot\");\n\n";
|
||||
|
||||
$cfg_content .= " // Database connection credentials\n";
|
||||
$cfg_content .= " // \n";
|
||||
$cfg_content .= " define(\"SQLITE_FILE\", \"weave_db\");\n";
|
||||
if ( $dbt != "mysql" ) {
|
||||
$cfg_content .= " define(\"MYSQL_ENABLE\", false);\n";
|
||||
$cfg_content .= " define(\"MYSQL_HOST\", \"localhost\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_DB\", \"fsync\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_USER\", \"fsyncUserName\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_PASSWORD\", \"fsyncUserPassword\");\n";
|
||||
} else {
|
||||
$cfg_content .= " define(\"MYSQL_ENABLE\", true);\n";
|
||||
$cfg_content .= " define(\"MYSQL_HOST\", \"$dbh\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_DB\", \"$dbn\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_USER\", \"$dbu\");\n";
|
||||
$cfg_content .= " define(\"MYSQL_PASSWORD\", \"$dbp\");\n";
|
||||
}
|
||||
$cfg_content .= "\n";
|
||||
$cfg_content .= " // Use bcrypt instead of MD5 for password hashing\n";
|
||||
$cfg_content .= " define(\"BCRYPT\", true);\n";
|
||||
$cfg_content .= " define(\"BCRYPT_ROUNDS\", 12);\n";
|
||||
|
||||
$cfg_content .= "\n?>\n";
|
||||
|
||||
// now write everything
|
||||
//
|
||||
$cfg_file = fopen($cfg_file_name, "a");
|
||||
fputs($cfg_file, "$cfg_content");
|
||||
fclose($cfg_file);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
print the html header for the form
|
||||
*/
|
||||
function print_header( $title ) {
|
||||
if ( ! isset( $title ) ) {
|
||||
$title = "";
|
||||
}
|
||||
print '<html><header><title>' . $title . '</title><body>
|
||||
<h1>Setup FSyncMS</h1>
|
||||
<form action="setup.php" method="post">';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
print the html footer
|
||||
*/
|
||||
function print_footer() {
|
||||
print '</form></body></html>';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
print the html for for the mysql connection credentials
|
||||
*/
|
||||
function print_mysql_connection_form() {
|
||||
print_header("MySQL database connection setup");
|
||||
print 'MySQL database connection setup
|
||||
<table>
|
||||
<tr>
|
||||
<td>Host</td>
|
||||
<td><input type="text" name="dbhost" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Instance name</td>
|
||||
<td><input type="text" name="dbname" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Username</td>
|
||||
<td><input type="text" name="dbuser" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Password</td>
|
||||
<td><input type="password" name="dbpass" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<input type="hidden" name="action" value="step2">
|
||||
<input type="hidden" name="dbType" value="mysql">
|
||||
<p><input type="submit" value="OK"></p>';
|
||||
print_footer();
|
||||
}
|
||||
// --------------------------------------------
|
||||
// functions end
|
||||
// --------------------------------------------
|
||||
|
||||
// check if we have no configuration at the moment
|
||||
//
|
||||
if ( file_exists("settings.php") && filesize( "settings.php" ) > 0 ) {
|
||||
echo "<hr><h2>The setup looks like it's completed, please delete settings.php</h2><hr>";
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// inital page - select the database type
|
||||
//
|
||||
if ( ! $action ) {
|
||||
|
||||
// first check if we have pdo installed (untested)
|
||||
//
|
||||
if ( ! extension_loaded('PDO') ) {
|
||||
print "ERROR - PDO is missing in the php installation!";
|
||||
exit();
|
||||
}
|
||||
|
||||
$validPdoDriver = 0;
|
||||
|
||||
print_header("Setup FSyncMS - DB Selection");
|
||||
|
||||
print 'Which database type should be used?<br>';
|
||||
if ( extension_loaded('pdo_mysql') ) {
|
||||
print '<input type="radio" name="dbType" value="mysql" /> MySQL <br>';
|
||||
$validPdoDriver++;
|
||||
} else {
|
||||
print 'MySQL not possible (Driver missing) <br>';
|
||||
}
|
||||
|
||||
if ( extension_loaded('pdo_sqlite') ) {
|
||||
print '<input type="radio" name="dbType" value="sqlite" checked="checked" /> SQLite ';
|
||||
$validPdoDriver++;
|
||||
} else {
|
||||
print 'SQLite not possible (Driver missing) <br>';
|
||||
}
|
||||
|
||||
if ( $validPdoDriver < 1 ) {
|
||||
print '<hr> No valid pdo driver found! Please install a valid pdo driver first <hr>';
|
||||
} else {
|
||||
print '<input type="hidden" name="action" value="step1">
|
||||
<p><input type="submit" value="OK" /></p>';
|
||||
}
|
||||
|
||||
// ensure we bail out at this point ;)
|
||||
exit();
|
||||
};
|
||||
|
||||
|
||||
// step 2 (connection data) below
|
||||
//
|
||||
if ( $action == "step1" ) {
|
||||
|
||||
// now check if the database is in place
|
||||
//
|
||||
print_header("Setup FSyncMS - DB Setup: $dbType!");
|
||||
switch ( $dbType ) {
|
||||
case "sqlite":
|
||||
$action = "step2";
|
||||
break;
|
||||
|
||||
case "mysql":
|
||||
print_mysql_connection_form();
|
||||
break;
|
||||
|
||||
default:
|
||||
print "ERROR - This type of database ($dbType) is not valid at the moment!";
|
||||
exit();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// now generate the database
|
||||
//
|
||||
if ( $action == "step2" ) {
|
||||
|
||||
$dbInstalled = false;
|
||||
$dbHandle = null;
|
||||
try {
|
||||
|
||||
if ( $dbType == "sqlite" ) {
|
||||
|
||||
$path = explode('/', $_SERVER['SCRIPT_FILENAME']);
|
||||
$db_name = 'weave_db';
|
||||
array_pop($path);
|
||||
array_push($path, $db_name);
|
||||
$db_name = implode('/', $path);
|
||||
|
||||
if ( file_exists($db_name) && filesize( $db_name ) > 0 ) {
|
||||
$dbInstalled = true;
|
||||
} else {
|
||||
echo("Creating sqlite weave storage: ". $db_name ."<br>");
|
||||
$dbHandle = new PDO('sqlite:' . $db_name);
|
||||
$dbHandle->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
}
|
||||
|
||||
} else if ( $dbType == "mysql" ) {
|
||||
|
||||
$dbHandle = new PDO("mysql:host=". $dbHost .";dbname=". $dbName, $dbUser, $dbPass);
|
||||
$select_stmt = "show tables like 'wbo'";
|
||||
$sth = $dbHandle->prepare($select_stmt);
|
||||
$sth->execute();
|
||||
$count = $sth->rowCount();
|
||||
if ( $count > 0 ) {
|
||||
$dbInstalled = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} catch ( PDOException $exception ) {
|
||||
echo("database unavailable " . $exception->getMessage());
|
||||
throw new Exception("Database unavailable " . $exception->getMessage() , 503);
|
||||
}
|
||||
|
||||
if ( $dbInstalled ) {
|
||||
echo "DB is already installed!<br>";
|
||||
|
||||
} else {
|
||||
echo "Now going to install the new database! Type is: $dbType<br>";
|
||||
|
||||
try {
|
||||
$create_statement = " create table wbo ( username varchar(100), id varchar(65), collection varchar(100),
|
||||
parentid varchar(65), predecessorid int, modified real, sortindex int,
|
||||
payload text, payload_size int, ttl int, primary key (username,collection,id))";
|
||||
$create_statement2 = " create table users ( username varchar(255), md5 varchar(124), 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 = $dbHandle->prepare($create_statement);
|
||||
$sth->execute();
|
||||
$sth = $dbHandle->prepare($create_statement2);
|
||||
$sth->execute();
|
||||
$sth = $dbHandle->prepare($index1);
|
||||
$sth->execute();
|
||||
$sth = $dbHandle->prepare($index2);
|
||||
$sth->execute();
|
||||
$sth = $dbHandle->prepare($index3);
|
||||
$sth->execute();
|
||||
echo "Database created <br>";
|
||||
|
||||
} catch( PDOException $exception ) {
|
||||
throw new Exception("Database unavailable", 503);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//guessing fsroot
|
||||
// get the FSYNC_ROOT url
|
||||
//
|
||||
$fsRoot ="https://";
|
||||
if ( ! isset($_SERVER['HTTPS']) ) {
|
||||
$fsRoot = "http://";
|
||||
}
|
||||
$fsRoot .= $_SERVER['SERVER_NAME'] . dirname($_SERVER['SCRIPT_NAME']) . "/";
|
||||
if( strpos( $_SERVER['REQUEST_URI'], 'index.php') !== 0 ) {
|
||||
$fsRoot .= "index.php/";
|
||||
}
|
||||
|
||||
// write settings.php, if not possible, display the needed contant
|
||||
//
|
||||
write_config_file($dbType, $dbHost, $dbName, $dbUser, $dbPass, $fsRoot);
|
||||
|
||||
echo "<hr><hr> Finished the setup, please delete setup.php and go on with the FFSync<hr><hr>";
|
||||
echo <<<EOT
|
||||
<hr><hr>
|
||||
<h4>This script has guessed the Address of your installation, this might not be accurate,<br/>
|
||||
Please check if this script can be reached by <a href="$fsRoot">$fsRoot</a> .<br/>
|
||||
If thats not the case you have to ajust the settings.php<br />
|
||||
</h4>
|
||||
EOT;
|
||||
}
|
||||
|
||||
?>
|
59
sources/test/hash.php
Normal file
59
sources/test/hash.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
define("BCRYPT", true);
|
||||
define("BCRYPT_ROUNDS", 12);
|
||||
|
||||
require_once __DIR__ . '/../weave_hash.php';
|
||||
|
||||
$pwd = "asdfASDFghjkGHJK2134$%&";
|
||||
|
||||
try {
|
||||
$hash = WeaveHashFactory::factory();
|
||||
$time_start = microtime(true);
|
||||
echo $hash->hash($pwd) . "\n";
|
||||
$time = microtime(true) - $time_start;
|
||||
echo "Hashing took " . $time . " seconds\n";
|
||||
|
||||
if (!$hash->verify($pwd, '$2a$12$O2Bn6lDUYS5NDIJ1uCZjGezSI/jeGTD7Ow0bd3PFMRBcGIqfqI4Oi')) {
|
||||
throw new Exception("bcrypt hash compare failed");
|
||||
}
|
||||
|
||||
if (!$hash->needsUpdate(md5($pwd))) {
|
||||
throw new Exception("bcrypt hash needs update.");
|
||||
}
|
||||
|
||||
if ($hash->needsUpdate('$2a$12$O2Bn6lDUYS5NDIJ1uCZjGezSI/jeGTD7Ow0bd3PFMRBcGIqfqI4Oi')) {
|
||||
throw new Exception("bcrypt hash doesn't needs update.");
|
||||
}
|
||||
|
||||
if (!$hash->verify($pwd, 'a96b71c678b01b98b9f7a0d8ec4b633b')) {
|
||||
throw new Exception("bcrypt hash compare with md5 failed");
|
||||
}
|
||||
|
||||
$hash2 = new WeaveHashBCrypt(6);
|
||||
|
||||
if (!$hash2->needsUpdate('$2a$12$O2Bn6lDUYS5NDIJ1uCZjGezSI/jeGTD7Ow0bd3PFMRBcGIqfqI4Oi')) {
|
||||
throw new Exception("bcrypt hash needs update because of different rounds.");
|
||||
}
|
||||
|
||||
$hashmd5 = new WeaveHashMD5();
|
||||
if (!$hashmd5->verify($pwd, 'a96b71c678b01b98b9f7a0d8ec4b633b')) {
|
||||
throw new Exception("md5 hash compare failed");
|
||||
}
|
||||
|
||||
if (!$hashmd5->needsUpdate('$2a$12$O2Bn6lDUYS5NDIJ1uCZjGezSI/jeGTD7Ow0bd3PFMRBcGIqfqI4Oi')) {
|
||||
throw new Exception("md5 hash needs update.");
|
||||
}
|
||||
|
||||
if ($hashmd5->needsUpdate(md5($pwd))) {
|
||||
throw new Exception("md5 hash doesn't need update.");
|
||||
}
|
||||
|
||||
echo "all tests ok\n";
|
||||
exit(0);
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
?>
|
275
sources/user.php
Normal file
275
sources/user.php
Normal file
|
@ -0,0 +1,275 @@
|
|||
<?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 Initial Developer of the Original Code is balu
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2012
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
|
||||
/*
|
||||
## DESCRIPTION: Implementation of user api v1.0
|
||||
##
|
||||
## AUTHOR: balu
|
||||
##
|
||||
## DATE: 20.02.2012
|
||||
##
|
||||
## VERSION: 0.1
|
||||
*/
|
||||
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 if (!empty($_SERVER["REQUEST_URI"]))
|
||||
{
|
||||
// improved path handling to prevent invalid server url error message in Firefox
|
||||
log_error("experimental path");
|
||||
|
||||
// this is kind of an experimental try, i needed it so i build it,
|
||||
// but that doesent mean that it does work... well it works for me
|
||||
// and it shouldnt break anything...
|
||||
$path = $_SERVER["REQUEST_URI"];
|
||||
$lastfolder = substr(FSYNCMS_ROOT,strrpos(FSYNCMS_ROOT, "/",-2));
|
||||
$path = substr($path, (strpos($path,$lastfolder) + strlen($lastfolder)-1)); // chop the lead slash
|
||||
if(strpos($path,'?') != false)
|
||||
$path = substr($path, 0, strpos($path,'?')); // remove php arguments
|
||||
log_error("path_exp:".$path);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error("user.php: No path found");
|
||||
report_problem("No path found", 404);
|
||||
}
|
||||
$path = substr($path, 1); #chop the lead slash
|
||||
// split path into parts and make sure that all values are properly initialized
|
||||
list($preinstr, $version, $username, $function, $collection, $id) = array_pad(explode('/', $path.'///'), 6, '');
|
||||
|
||||
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
|
||||
{
|
||||
// reply node server for user
|
||||
|
||||
//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/";
|
||||
*/
|
||||
|
||||
// modification to support iPhone/iPod Touch devices
|
||||
// check http://www.rfkd.de/?p=974 for further details
|
||||
if (isset($_SERVER['HTTPS'])) {
|
||||
exit("https://" . parse_url(FSYNCMS_ROOT, PHP_URL_HOST) . parse_url(FSYNCMS_ROOT, PHP_URL_PATH));
|
||||
} else {
|
||||
// allow http requests because use of self-signed certificates
|
||||
// on iPhone/iPod Touch devices doesn't work
|
||||
exit("http://" . parse_url(FSYNCMS_ROOT, PHP_URL_HOST) . parse_url(FSYNCMS_ROOT, PHP_URL_PATH));
|
||||
}
|
||||
}
|
||||
else if($function == 'password_reset')
|
||||
{
|
||||
//email mit neuem pw senden
|
||||
/*
|
||||
Possible errors:
|
||||
|
||||
503: problems with looking up the user or sending the email
|
||||
400: 12 (No email address on file)
|
||||
400: 3 (Incorrect or missing username)
|
||||
400: 2 (Incorrect or missing captcha)
|
||||
*/
|
||||
report_problem(WEAVE_ERROR_NO_EMAIL, 400);
|
||||
}
|
||||
//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_JSON_PARSE, 400);
|
||||
$name = $username;
|
||||
$pwd = fix_utf8_encoding($data['password']);
|
||||
$email = $data['email'];
|
||||
if($email == '')
|
||||
{
|
||||
log_error('create user datenfehler');
|
||||
report_problem(WEAVE_ERROR_NO_EMAIL, 400);
|
||||
}
|
||||
else if ( $pwd == '' )
|
||||
{
|
||||
log_error('create user datenfehler');
|
||||
report_problem(WEAVE_ERROR_MISSING_PASSWORD, 400);
|
||||
}
|
||||
if($name == '' || $pwd == '' || $email == '')
|
||||
{
|
||||
log_error('create user datenfehler');
|
||||
report_problem(WEAVE_ERROR_JSON_PARSE, 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(WEAVE_ERROR_NO_OVERWRITE, 503);
|
||||
}
|
||||
}
|
||||
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
|
||||
else if($_SERVER['REQUEST_METHOD'] == 'POST')
|
||||
{
|
||||
if($username == '')
|
||||
{
|
||||
log_error("user.php : Post no username");
|
||||
report_problem(WEAVE_ERROR_INVALID_USERNAME, 400);
|
||||
}
|
||||
$db = new WeaveStorage($username);
|
||||
log_error("user.php: POST");
|
||||
if($function == "password")
|
||||
{
|
||||
#Auth the user
|
||||
verify_user($username, $db);
|
||||
$new_pwd = get_phpinput();
|
||||
log_error("user.php: POST password ");
|
||||
//to do
|
||||
// change pw in db
|
||||
if($db->change_password($new_pwd))
|
||||
exit("success");
|
||||
else
|
||||
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 503); //server db messed up somehow
|
||||
// return success
|
||||
// report_problem(7, 400);
|
||||
}
|
||||
else if($function == "email")
|
||||
{
|
||||
//change email adr
|
||||
}
|
||||
else
|
||||
{
|
||||
report_problem(WEAVE_ERROR_INVALID_PROTOCOL, 400);
|
||||
}
|
||||
// exit('success');
|
||||
}
|
||||
}
|
||||
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";
|
||||
|
||||
?>
|
249
sources/weave_basic_object.php
Normal file
249
sources/weave_basic_object.php
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
191
sources/weave_hash.php
Normal file
191
sources/weave_hash.php
Normal file
|
@ -0,0 +1,191 @@
|
|||
<?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 http://stackoverflow.com/a/6337021/833893
|
||||
#
|
||||
# Contributor(s):
|
||||
# Daniel Triendl <daniel@pew.cc>
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
interface WeaveHash {
|
||||
public function hash($input);
|
||||
public function verify($input, $existingHash);
|
||||
public function needsUpdate($existingHash);
|
||||
}
|
||||
|
||||
class WeaveHashMD5 implements WeaveHash {
|
||||
public function hash($input) {
|
||||
return md5($input);
|
||||
}
|
||||
|
||||
public function verify($input, $existingHash) {
|
||||
return $this->hash($input) == $existingHash;
|
||||
}
|
||||
|
||||
public function needsUpdate($existingHash) {
|
||||
return substr($existingHash, 0, 4) == "$2a$";
|
||||
}
|
||||
}
|
||||
|
||||
class WeaveHashBCrypt implements WeaveHash {
|
||||
private $_rounds;
|
||||
|
||||
public function __construct($rounds = 12) {
|
||||
if(CRYPT_BLOWFISH != 1) {
|
||||
throw new Exception("bcrypt not available");
|
||||
}
|
||||
|
||||
$this->_rounds = $rounds;
|
||||
}
|
||||
|
||||
public function hash($input) {
|
||||
$hash = crypt($input, $this->getSalt());
|
||||
|
||||
if (strlen($hash) <= 13) {
|
||||
throw new Exception("error while generating hash");
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
public function verify($input, $existingHash) {
|
||||
if ($this->isMD5($existingHash)) {
|
||||
$md5 = new WeaveHashMD5();
|
||||
return $md5->verify($input, $existingHash);
|
||||
}
|
||||
|
||||
$hash = crypt($input, $existingHash);
|
||||
|
||||
return $hash === $existingHash;
|
||||
}
|
||||
|
||||
public function needsUpdate($existingHash) {
|
||||
$identifier = $this->getIdentifier();
|
||||
return substr($existingHash, 0, strlen($identifier)) != $identifier;
|
||||
}
|
||||
|
||||
private function isMD5($existingHash) {
|
||||
return substr($existingHash, 0, 4) != "$2a$";
|
||||
}
|
||||
|
||||
private function getSalt() {
|
||||
$salt = $this->getIdentifier();
|
||||
|
||||
$bytes = $this->getRandomBytes(16);
|
||||
|
||||
$salt .= $this->encodeBytes($bytes);
|
||||
|
||||
return $salt;
|
||||
}
|
||||
|
||||
private function getIdentifier() {
|
||||
return sprintf("$2a$%02d$", $this->_rounds);
|
||||
}
|
||||
|
||||
private $randomState;
|
||||
private function getRandomBytes($count) {
|
||||
$bytes = '';
|
||||
|
||||
if(function_exists('openssl_random_pseudo_bytes') &&
|
||||
(strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')) { // OpenSSL slow on Win
|
||||
$bytes = openssl_random_pseudo_bytes($count);
|
||||
}
|
||||
|
||||
if($bytes === '' && is_readable('/dev/urandom') &&
|
||||
($hRand = @fopen('/dev/urandom', 'rb')) !== FALSE) {
|
||||
$bytes = fread($hRand, $count);
|
||||
fclose($hRand);
|
||||
}
|
||||
|
||||
if(strlen($bytes) < $count) {
|
||||
$bytes = '';
|
||||
|
||||
if($this->randomState === null) {
|
||||
$this->randomState = microtime();
|
||||
if(function_exists('getmypid')) {
|
||||
$this->randomState .= getmypid();
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0; $i < $count; $i += 16) {
|
||||
$this->randomState = md5(microtime() . $this->randomState);
|
||||
|
||||
if (PHP_VERSION >= '5') {
|
||||
$bytes .= md5($this->randomState, true);
|
||||
} else {
|
||||
$bytes .= pack('H*', md5($this->randomState));
|
||||
}
|
||||
}
|
||||
|
||||
$bytes = substr($bytes, 0, $count);
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
private function encodeBytes($input) {
|
||||
// The following is code from the PHP Password Hashing Framework
|
||||
$itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
|
||||
$output = '';
|
||||
$i = 0;
|
||||
do {
|
||||
$c1 = ord($input[$i++]);
|
||||
$output .= $itoa64[$c1 >> 2];
|
||||
$c1 = ($c1 & 0x03) << 4;
|
||||
if ($i >= 16) {
|
||||
$output .= $itoa64[$c1];
|
||||
break;
|
||||
}
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 4;
|
||||
$output .= $itoa64[$c1];
|
||||
$c1 = ($c2 & 0x0f) << 2;
|
||||
|
||||
$c2 = ord($input[$i++]);
|
||||
$c1 |= $c2 >> 6;
|
||||
$output .= $itoa64[$c1];
|
||||
$output .= $itoa64[$c2 & 0x3f];
|
||||
} while (1);
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
|
||||
class WeaveHashFactory {
|
||||
public static function factory() {
|
||||
if (defined("BCRYPT") && BCRYPT) {
|
||||
return new WeaveHashBCrypt(BCRYPT_ROUNDS);
|
||||
} else {
|
||||
return new WeaveHashMD5();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
815
sources/weave_storage.php
Normal file
815
sources/weave_storage.php
Normal file
|
@ -0,0 +1,815 @@
|
|||
<?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)
|
||||
# balu
|
||||
# Daniel Triendl <daniel@pew.cc>
|
||||
#
|
||||
# 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';
|
||||
require_once 'weave_utils.php';
|
||||
require_once 'settings.php';
|
||||
|
||||
class WeaveStorage
|
||||
{
|
||||
private $_username;
|
||||
private $_dbh;
|
||||
|
||||
function __construct($username)
|
||||
{
|
||||
|
||||
$this->_username = $username;
|
||||
|
||||
log_error("Initalizing DB connecion!");
|
||||
|
||||
try
|
||||
{
|
||||
if ( ! MYSQL_ENABLE )
|
||||
{
|
||||
$path = explode('/', $_SERVER['SCRIPT_FILENAME']);
|
||||
$db_name = SQLITE_FILE;
|
||||
array_pop($path);
|
||||
array_push($path, $db_name);
|
||||
$db_name = implode('/', $path);
|
||||
|
||||
if ( ! file_exists($db_name) )
|
||||
{
|
||||
log_error("The required sqllite database is not present! $db_name");
|
||||
}
|
||||
|
||||
log_error("Starting SQLite connection");
|
||||
$this->_dbh = new PDO('sqlite:' . $db_name);
|
||||
$this->_dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
}
|
||||
else if ( MYSQL_ENABLE )
|
||||
{
|
||||
log_error("Starting MySQL connection");
|
||||
$this->_dbh = new PDO("mysql:host=". MYSQL_HOST .";dbname=". MYSQL_DB, MYSQL_USER, MYSQL_PASSWORD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
catch( PDOException $exception )
|
||||
{
|
||||
log_error("database unavailable " . $exception->getMessage());
|
||||
throw new Exception("Database unavailable " . $exception->getMessage() , 503);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
$create_statement = "insert into users values (:username, :md5)";
|
||||
|
||||
$sth = $this->_dbh->prepare($create_statement);
|
||||
$hash = WeaveHashFactory::factory();
|
||||
$password = $hash->hash($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($hash)
|
||||
{
|
||||
try
|
||||
{
|
||||
$update_statement = "update users set md5 = :md5 where username = :username";
|
||||
|
||||
$sth = $this->_dbh->prepare($update_statement);
|
||||
$sth->bindParam(':username', $this->_username);
|
||||
$sth->bindParam(':md5', $hash);
|
||||
$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 get_password_hash()
|
||||
{
|
||||
log_error("auth-user: " . $this->_username);
|
||||
try
|
||||
{
|
||||
$select_stmt = 'select md5 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("get_password_hash: " . $exception->getMessage());
|
||||
throw new Exception("Database unavailable", 503);
|
||||
}
|
||||
|
||||
$result = $sth->fetchColumn();
|
||||
if ($result === FALSE) $result = "";
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
286
sources/weave_utils.php
Normal file
286
sources/weave_utils.php
Normal file
|
@ -0,0 +1,286 @@
|
|||
<?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 Initial Developer of the Original Code is balu
|
||||
#
|
||||
# Portions created by the Initial Developer are Copyright (C) 2012
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Daniel Triendl <daniel@pew.cc>
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
define ('LOG_THE_ERROR', 0);
|
||||
|
||||
function log_error($msg)
|
||||
{
|
||||
if ( LOG_THE_ERROR == 1 )
|
||||
{
|
||||
$datei = fopen("/tmp/FSyncMS-error.txt","a");
|
||||
$fmsg = sprintf("$msg\n");
|
||||
fputs($datei,$fmsg);
|
||||
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_phpinput()
|
||||
{
|
||||
#stupid php being helpful with input data...
|
||||
$putdata = fopen("php://input", "r");
|
||||
$string = '';
|
||||
while ($data = fread($putdata,2048)) {$string .= $data;} //hier will man ein limit einbauen
|
||||
return $string;
|
||||
}
|
||||
function get_json()
|
||||
{
|
||||
$jsonstring = get_phpinput();
|
||||
$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;
|
||||
|
||||
// allow characters '?' and '=' in the collection string which e.g.
|
||||
// appear if the following request is send from firefox:
|
||||
// http://<server>/weave/1.1/<user>/storage/clients?full=1
|
||||
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 1 {");
|
||||
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
|
||||
{
|
||||
$existingHash = $db->get_password_hash();
|
||||
$hash = WeaveHashFactory::factory();
|
||||
|
||||
if ( ! $hash->verify(fix_utf8_encoding($auth_pw), $existingHash) )
|
||||
{
|
||||
log_error("Auth failed 2 {");
|
||||
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(" Existing hash: ".$existingHash);
|
||||
log_error("}");
|
||||
report_problem('Authentication failed', '401');
|
||||
} else {
|
||||
if ( $hash->needsUpdate($existingHash) ) {
|
||||
$db->change_password($hash->hash(fix_utf8_encoding($auth_pw)));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
{
|
||||
header("X-Weave-Backoff: 1800");
|
||||
log_error($e->getMessage(), $e->getCode());
|
||||
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…
Reference in a new issue