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