diff options
33 files changed, 364 insertions, 145 deletions
diff --git a/doc/registration.bb b/doc/registration.bb index 1649db62e..0aaa679c2 100644 --- a/doc/registration.bb +++ b/doc/registration.bb @@ -4,7 +4,7 @@ Not all Red Matrix sites allow open registration. If registration is allowed, yo [b]Your Email Address[/b]
-Please provide a valid email address. Your email address is never published. This address will be used to activate your account, to (optionally) send email notifications for incoming messages or items, [/i]and to recover lost passwords[/i].
+Please provide a valid email address. Your email address is never published. This address will be used to activate your account, to (optionally) send email notifications for incoming messages or items, [i]and to recover lost passwords[/i].
[b]Password[/b]
diff --git a/images/default_profile_photos/alpha/175.png b/images/default_profile_photos/alpha/175.png Binary files differnew file mode 100644 index 000000000..17211ee27 --- /dev/null +++ b/images/default_profile_photos/alpha/175.png diff --git a/images/default_profile_photos/alpha/48.png b/images/default_profile_photos/alpha/48.png Binary files differnew file mode 100644 index 000000000..b8212131c --- /dev/null +++ b/images/default_profile_photos/alpha/48.png diff --git a/images/default_profile_photos/alpha/80.png b/images/default_profile_photos/alpha/80.png Binary files differnew file mode 100644 index 000000000..19da3ffc1 --- /dev/null +++ b/images/default_profile_photos/alpha/80.png diff --git a/images/default_profile_photos/black_avatar_1/175.png b/images/default_profile_photos/black_avatar_1/175.png Binary files differnew file mode 100644 index 000000000..d8e49d43c --- /dev/null +++ b/images/default_profile_photos/black_avatar_1/175.png diff --git a/images/default_profile_photos/black_avatar_1/48.png b/images/default_profile_photos/black_avatar_1/48.png Binary files differnew file mode 100644 index 000000000..c616776b6 --- /dev/null +++ b/images/default_profile_photos/black_avatar_1/48.png diff --git a/images/default_profile_photos/black_avatar_1/80.png b/images/default_profile_photos/black_avatar_1/80.png Binary files differnew file mode 100644 index 000000000..29eb8fb5d --- /dev/null +++ b/images/default_profile_photos/black_avatar_1/80.png diff --git a/images/default_profile_photos/black_avatar_2/175.png b/images/default_profile_photos/black_avatar_2/175.png Binary files differnew file mode 100644 index 000000000..1a9473300 --- /dev/null +++ b/images/default_profile_photos/black_avatar_2/175.png diff --git a/images/default_profile_photos/black_avatar_2/48.png b/images/default_profile_photos/black_avatar_2/48.png Binary files differnew file mode 100644 index 000000000..073e0323a --- /dev/null +++ b/images/default_profile_photos/black_avatar_2/48.png diff --git a/images/default_profile_photos/black_avatar_2/80.png b/images/default_profile_photos/black_avatar_2/80.png Binary files differnew file mode 100644 index 000000000..fa7d92a91 --- /dev/null +++ b/images/default_profile_photos/black_avatar_2/80.png diff --git a/images/default_profile_photos/blank/175.png b/images/default_profile_photos/blank/175.png Binary files differnew file mode 100644 index 000000000..1edb25b76 --- /dev/null +++ b/images/default_profile_photos/blank/175.png diff --git a/images/default_profile_photos/blank/48.png b/images/default_profile_photos/blank/48.png Binary files differnew file mode 100644 index 000000000..cbff2264d --- /dev/null +++ b/images/default_profile_photos/blank/48.png diff --git a/images/default_profile_photos/blank/80.png b/images/default_profile_photos/blank/80.png Binary files differnew file mode 100644 index 000000000..e7eb91fd3 --- /dev/null +++ b/images/default_profile_photos/blank/80.png diff --git a/images/default_profile_photos/rainbow_man/175.png b/images/default_profile_photos/rainbow_man/175.png Binary files differnew file mode 100644 index 000000000..a0a236841 --- /dev/null +++ b/images/default_profile_photos/rainbow_man/175.png diff --git a/images/default_profile_photos/rainbow_man/48.png b/images/default_profile_photos/rainbow_man/48.png Binary files differnew file mode 100644 index 000000000..9e3399598 --- /dev/null +++ b/images/default_profile_photos/rainbow_man/48.png diff --git a/images/default_profile_photos/rainbow_man/80.png b/images/default_profile_photos/rainbow_man/80.png Binary files differnew file mode 100644 index 000000000..b0b1ca784 --- /dev/null +++ b/images/default_profile_photos/rainbow_man/80.png diff --git a/images/default_profile_photos/red_avatar/175.png b/images/default_profile_photos/red_avatar/175.png Binary files differnew file mode 100644 index 000000000..8251149a0 --- /dev/null +++ b/images/default_profile_photos/red_avatar/175.png diff --git a/images/default_profile_photos/red_avatar/48.png b/images/default_profile_photos/red_avatar/48.png Binary files differnew file mode 100644 index 000000000..a889651ec --- /dev/null +++ b/images/default_profile_photos/red_avatar/48.png diff --git a/images/default_profile_photos/red_avatar/80.png b/images/default_profile_photos/red_avatar/80.png Binary files differnew file mode 100644 index 000000000..7ddea61c2 --- /dev/null +++ b/images/default_profile_photos/red_avatar/80.png diff --git a/images/default_profile_photos/red_koala/175.png b/images/default_profile_photos/red_koala/175.png Binary files differnew file mode 100644 index 000000000..4e51c80e2 --- /dev/null +++ b/images/default_profile_photos/red_koala/175.png diff --git a/images/default_profile_photos/red_koala/48.png b/images/default_profile_photos/red_koala/48.png Binary files differnew file mode 100644 index 000000000..69ecfebd9 --- /dev/null +++ b/images/default_profile_photos/red_koala/48.png diff --git a/images/default_profile_photos/red_koala/80.png b/images/default_profile_photos/red_koala/80.png Binary files differnew file mode 100644 index 000000000..48c161fc7 --- /dev/null +++ b/images/default_profile_photos/red_koala/80.png diff --git a/images/default_profile_photos/redmatrix_logo_smiley/175.png b/images/default_profile_photos/redmatrix_logo_smiley/175.png Binary files differnew file mode 100644 index 000000000..daa15d8f8 --- /dev/null +++ b/images/default_profile_photos/redmatrix_logo_smiley/175.png diff --git a/images/default_profile_photos/redmatrix_logo_smiley/48.png b/images/default_profile_photos/redmatrix_logo_smiley/48.png Binary files differnew file mode 100644 index 000000000..20704bc98 --- /dev/null +++ b/images/default_profile_photos/redmatrix_logo_smiley/48.png diff --git a/images/default_profile_photos/redmatrix_logo_smiley/80.png b/images/default_profile_photos/redmatrix_logo_smiley/80.png Binary files differnew file mode 100644 index 000000000..30e0abbbd --- /dev/null +++ b/images/default_profile_photos/redmatrix_logo_smiley/80.png diff --git a/images/redmatrix_logo.svg b/images/redmatrix_logo.svg new file mode 100644 index 000000000..cb98a7fb5 --- /dev/null +++ b/images/redmatrix_logo.svg @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="200" + height="200" + id="svg3053" + version="1.1" + inkscape:version="0.48.4 r9939" + sodipodi:docname="redmatrix.svg"> + <defs + id="defs3055" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="1.979899" + inkscape:cx="35.049163" + inkscape:cy="27.799654" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0" + inkscape:window-width="1871" + inkscape:window-height="1056" + inkscape:window-x="49" + inkscape:window-y="24" + inkscape:window-maximized="1" /> + <metadata + id="metadata3058"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Laag 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(-315.00002,-392.36223)" + style="display:inline"> + <g + id="g2985" + transform="matrix(4.7619048,0,0,4.7619048,-1370.7143,-2042.6958)"> + <path + style="fill:#c60032;fill-opacity:1" + d="m 218.0851,397.84091 c 0,12.77893 -10.00215,23.1383 -22.34043,23.1383 -12.33827,0 -22.34042,-10.35937 -22.34042,-23.1383 0,-12.77893 10.00215,-23.1383 22.34042,-23.1383 12.33828,0 22.34043,10.35937 22.34043,23.1383 z" + sodipodi:ry="23.138298" + sodipodi:rx="22.340425" + sodipodi:cy="397.84091" + sodipodi:cx="195.74467" + id="path3028-4-5-3" + sodipodi:type="arc" + transform="matrix(0.94,0,0,0.9075862,191.00001,171.28726)" /> + <g + id="text3003-0-4-0" + style="font-size:46px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Sans" + transform="translate(52.138256,-208.57143)"> + <path + inkscape:connector-curvature="0" + id="path3008" + style="font-size:45.09999847px;font-variant:normal;font-weight:bold;font-stretch:normal;fill:#ffffff;font-family:generic;-inkscape-font-specification:generic Bold" + d="m 322.85053,756.03406 4.7355,0 1.3079,-7.9827 4.8708,0 0,-4.4649 -4.1492,0 1.0373,-6.4944 4.9159,0 0,-4.4649 -4.1492,0 1.1275,-7.0356 -4.7355,0 -1.1275,7.0356 -5.1865,0 1.1275,-7.0356 -4.7355,0 -1.1275,7.0356 -5.0963,0 0,4.4649 4.3296,0 -1.0373,6.4944 -5.0963,0 0,4.4649 4.3747,0 -1.3079,7.9827 4.7355,0 1.3079,-7.9827 5.1865,0 -1.3079,7.9827 m 2.0295,-12.4476 -5.1865,0 1.0373,-6.4944 5.1865,0 -1.0373,6.4944" /> + </g> + </g> + </g> +</svg> diff --git a/include/auth.php b/include/auth.php index f8188f443..8f68fc562 100644 --- a/include/auth.php +++ b/include/auth.php @@ -1,11 +1,23 @@ -<?php /** @file */ - +<?php +/** + * @file include/auth.php + * @brief Functions and inline functionality for authentication. + * + * This file provides some functions for authentication handling and inline + * functionality. Look for auth parameters or re-validate an existing session + * also handles logout. + * Also provides a function for OpenID identiy matching. + */ require_once('include/security.php'); +/** + * @brief Resets the current session. + * + * @return void + */ function nuke_session() { - - new_cookie(0); + new_cookie(0); // 0 means delete on browser exit unset($_SESSION['authenticated']); unset($_SESSION['account_id']); @@ -27,21 +39,24 @@ function nuke_session() { } /** - * Verify login credentials - * - * Returns account record on success, null on failure + * @brief Verify login credentials. * + * @param string $email + * The email address to verify. + * @param string $pass + * The provided password to verify. + * @return array|null + * Returns account record on success, null on failure. */ +function account_verify_password($email, $pass) { -function account_verify_password($email,$pass) { - - $email_verify = get_config('system','verify_email'); - $register_policy = get_config('system','register_policy'); + $email_verify = get_config('system', 'verify_email'); + $register_policy = get_config('system', 'register_policy'); // Currently we only verify email address if there is an open registration policy. // This isn't because of any policy - it's because the workflow gets too complicated if // you have to verify the email and then go through the account approval workflow before - // letting them login. + // letting them login. if(($email_verify) && ($register_policy == REGISTER_OPEN) && ($record['account_flags'] & ACCOUNT_UNVERIFIED)) return null; @@ -51,9 +66,10 @@ function account_verify_password($email,$pass) { ); if(! ($r && count($r))) return null; + foreach($r as $record) { if(($record['account_flags'] == ACCOUNT_OK) - && (hash('whirlpool',$record['account_salt'] . $pass) === $record['account_password'])) { + && (hash('whirlpool', $record['account_salt'] . $pass) === $record['account_password'])) { logger('password verified for ' . $email); return $record; } @@ -61,7 +77,6 @@ function account_verify_password($email,$pass) { $error = 'password failed for ' . $email; logger($error); - if($record['account_flags'] & ACCOUNT_UNVERIFIED) logger('Account is unverified. account_flags = ' . $record['account_flags']); if($record['account_flags'] & ACCOUNT_BLOCKED) @@ -88,14 +103,12 @@ function account_verify_password($email,$pass) { * also handles logout */ - -if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-params'))) || ($_POST['auth-params'] !== 'login'))) { - +if((isset($_SESSION)) && (x($_SESSION, 'authenticated')) && + ((! (x($_POST, 'auth-params'))) || ($_POST['auth-params'] !== 'login'))) { // process a logout request - if(((x($_POST,'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) { - + if(((x($_POST, 'auth-params')) && ($_POST['auth-params'] === 'logout')) || ($a->module === 'logout')) { // process logout request $args = array('channel_id' => local_user()); call_hooks('logging_out', $args); @@ -106,16 +119,16 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p // re-validate a visitor, optionally invoke "su" if permitted to do so - if(x($_SESSION,'visitor_id') && (! x($_SESSION,'uid'))) { + if(x($_SESSION, 'visitor_id') && (! x($_SESSION, 'uid'))) { // if our authenticated guest is allowed to take control of the admin channel, make it so. - $admins = get_config('system','remote_admin'); - if($admins && is_array($admins) && in_array($_SESSION['visitor_id'],$admins)) { + $admins = get_config('system', 'remote_admin'); + if($admins && is_array($admins) && in_array($_SESSION['visitor_id'], $admins)) { $x = q("select * from account where account_email = '%s' and account_email != '' and ( account_flags & %d ) limit 1", - dbesc(get_config('system','admin_email')), + dbesc(get_config('system', 'admin_email')), intval(ACCOUNT_ROLE_ADMIN) ); if($x) { - new_cookie(60*60*24); // one day + new_cookie(60 * 60 * 24); // one day $_SESSION['last_login_date'] = datetime_convert(); unset($_SESSION['visitor_id']); // no longer a visitor authenticate_success($x[0], true, true); @@ -137,20 +150,19 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p // already logged in user returning - if(x($_SESSION,'uid') || x($_SESSION,'account_id')) { + if(x($_SESSION, 'uid') || x($_SESSION, 'account_id')) { // first check if we're enforcing that sessions can't change IP address - + // @todo what to do with IPv6 addresses if($_SESSION['addr'] && $_SESSION['addr'] != $_SERVER['REMOTE_ADDR']) { logger('SECURITY: Session IP address changed: ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); - $partial1 = substr($_SESSION['addr'],0,strrpos($_SESSION['addr'],'.')); - $partial2 = substr($_SERVER['REMOTE_ADDR'],0,strrpos($_SERVER['REMOTE_ADDR'],'.')); + $partial1 = substr($_SESSION['addr'], 0, strrpos($_SESSION['addr'], '.')); + $partial2 = substr($_SERVER['REMOTE_ADDR'], 0, strrpos($_SERVER['REMOTE_ADDR'], '.')); - - $paranoia = intval(get_pconfig($_SESSION['uid'],'system','paranoia')); + $paranoia = intval(get_pconfig($_SESSION['uid'], 'system', 'paranoia')); if(! $paranoia) - $paranoia = intval(get_config('system','paranoia')); + $paranoia = intval(get_config('system', 'paranoia')); switch($paranoia) { case 0: @@ -158,8 +170,8 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p break; case 2: // check 2 octets - $partial1 = substr($partial1,0,strrpos($partial1,'.')); - $partial2 = substr($partial2,0,strrpos($partial2,'.')); + $partial1 = substr($partial1, 0, strrpos($partial1, '.')); + $partial2 = substr($partial2, 0, strrpos($partial2, '.')); if($partial1 == $partial2) break; case 1: @@ -169,12 +181,11 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p case 3: default: // check any difference at all - logger('Session address changed. Paranoid setting in effect, blocking session. ' + logger('Session address changed. Paranoid setting in effect, blocking session. ' . $_SESSION['addr'] . ' != ' . $_SERVER['REMOTE_ADDR']); nuke_session(); goaway(z_root()); break; - } } @@ -191,17 +202,15 @@ if((isset($_SESSION)) && (x($_SESSION,'authenticated')) && ((! (x($_POST,'auth-p if(strcmp(datetime_convert('UTC','UTC','now - 12 hours'), $_SESSION['last_login_date']) > 0 ) { $_SESSION['last_login_date'] = datetime_convert(); $login_refresh = true; - } - authenticate_success($r[0], false, false, false, $login_refresh); + } + authenticate_success($r[0], false, false, false, $login_refresh); } else { $_SESSION['account_id'] = 0; nuke_session(); goaway(z_root()); } - - } - + } // end logged in user returning } else { @@ -211,10 +220,10 @@ else { // handle a fresh login request - if((x($_POST,'password')) && strlen($_POST['password'])) - $encrypted = hash('whirlpool',trim($_POST['password'])); + if((x($_POST, 'password')) && strlen($_POST['password'])) + $encrypted = hash('whirlpool', trim($_POST['password'])); - if((x($_POST,'auth-params')) && $_POST['auth-params'] === 'login') { + if((x($_POST, 'auth-params')) && $_POST['auth-params'] === 'login') { $record = null; @@ -239,8 +248,7 @@ else { $record = $addon_auth['user_record']; } else { - - $record = get_app()->account = account_verify_password($_POST['username'],$_POST['password']); + $record = get_app()->account = account_verify_password($_POST['username'], $_POST['password']); if(get_app()->account) { $_SESSION['account_id'] = get_app()->account['account_id']; @@ -249,21 +257,20 @@ else { notice( t('Failed authentication') . EOL); } - logger('authenticate: ' . print_r(get_app()->account,true), LOGGER_DEBUG); - + logger('authenticate: ' . print_r(get_app()->account, true), LOGGER_DEBUG); } if((! $record) || (! count($record))) { $error = 'authenticate: failed login attempt: ' . notags(trim($_POST['username'])) . ' from IP ' . $_SERVER['REMOTE_ADDR']; logger($error); // Also log failed logins to a separate auth log to reduce overhead for server side intrusion prevention - $authlog = get_config('system', 'authlog'); - if ($authlog) - @file_put_contents($authlog, datetime_convert() . ':' . session_id() . ' ' . $error . "\n", FILE_APPEND); + $authlog = get_config('system', 'authlog'); + if ($authlog) + @file_put_contents($authlog, datetime_convert() . ':' . session_id() . ' ' . $error . "\n", FILE_APPEND); notice( t('Login failed.') . EOL ); goaway(z_root()); - } + } // If the user specified to remember the authentication, then change the cookie // to expire after one year (the default is when the browser is closed). @@ -293,11 +300,25 @@ else { } +/** + * @brief Returns the channel_id for a given openid_identity. + * + * Queries the values from pconfig configuration for the given openid_identity + * and returns the corresponding channel_id. + * + * @fixme How do we prevent that an OpenID identity is used more than once? + * + * @param string $authid + * The given openid_identity + * @return int|bool + * Return channel_id from pconfig or false. + */ function match_openid($authid) { - $r = q("select * from pconfig where cat = 'system' and k = 'openid' and v = '%s' limit 1", + // Query the uid/channel_id from pconfig for a given value. + $r = q("SELECT uid FROM pconfig WHERE cat = 'system' AND k = 'openid' AND v = '%s' LIMIT 1", dbesc($authid) ); if($r) return $r[0]['uid']; return false; -} +} diff --git a/include/identity.php b/include/identity.php index fc07bd4e4..fafb97bbb 100644 --- a/include/identity.php +++ b/include/identity.php @@ -1369,7 +1369,7 @@ function get_default_profile_photo($size = 175) { $scheme = get_config('system','default_profile_photo'); if(! $scheme) $scheme = 'rainbow_man'; - return 'images/default_profile_photos/' . $scheme . '/' . $size . '.jpg'; + return 'images/default_profile_photos/' . $scheme . '/' . $size . '.png'; } diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php index daf1bfc25..d9777b1c4 100644 --- a/include/photo/photo_driver.php +++ b/include/photo/photo_driver.php @@ -623,7 +623,7 @@ function import_profile_photo($photo,$xchan,$thing = false) { $photo = $a->get_baseurl() . '/' . get_default_profile_photo(); $thumb = $a->get_baseurl() . '/' . get_default_profile_photo(80); $micro = $a->get_baseurl() . '/' . get_default_profile_photo(48); - $type = 'image/jpeg'; + $type = 'image/png'; } return(array($photo,$thumb,$micro,$type,$photo_failure)); diff --git a/include/reddav.php b/include/reddav.php index c4ef5bd08..3de24661e 100644 --- a/include/reddav.php +++ b/include/reddav.php @@ -9,6 +9,8 @@ * You find the original SabreDAV classes under @ref vendor/sabre/dav/. * We need to use SabreDAV 1.8.x for PHP5.3 compatibility. SabreDAV >= 2.0 * requires PHP >= 5.4. + * + * @todo split up the classes into own files. */ use Sabre\DAV; @@ -25,6 +27,8 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { /** * @brief The path inside /cloud + * + * @var string */ private $red_path; private $folder_hash; @@ -32,6 +36,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { * @brief The full path as seen in the browser. * /cloud + $red_path * @todo I think this is not used anywhere, we always strip '/cloud' and only use it in debug + * @var string */ private $ext_path; private $root_dir = ''; @@ -39,6 +44,8 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { /** * @brief The real path on the filesystem. * The actual path in store/ with the hashed names. + * + * @var string */ private $os_path = ''; @@ -107,7 +114,7 @@ class RedDirectory extends DAV\Node implements DAV\ICollection, DAV\IQuota { if (get_config('system', 'block_public') && (! $this->auth->channel_id) && (! $this->auth->observer)) { throw new DAV\Exception\Forbidden('Permission denied.'); } - + if (($this->auth->owner_id) && (! perm_is_allowed($this->auth->owner_id, $this->auth->observer, 'view_storage'))) { throw new DAV\Exception\Forbidden('Permission denied.'); } @@ -971,78 +978,111 @@ function RedFileData($file, &$auth, $test = false) { /** - * RedBasicAuth class. + * @brief Authentication backend class for RedDAV. + * + * This class also contains some data which is not necessary for authentication + * like timezone settings. * */ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic { - // @fixme mod/cloud.php:61 - public $channel_name = ''; - // @fixme mod/cloud.php:62 + /** + * @brief This variable holds the currently logged-in channel_address. + * + * It is used for building path in filestorage/. + * + * @var string|null + */ + protected $channel_name = null; + /** + * channel_id of the current channel of the logged-in account. + * + * @var int + */ public $channel_id = 0; - // @fixme mod/cloud.php:63 + /** + * channel_hash of the current channel of the logged-in account. + * + * @var string + */ public $channel_hash = ''; - // @fixme mod/cloud.php:68 + /** + * Set in mod/cloud.php to observer_hash. + * + * @var string + */ public $observer = ''; - // @fixme include/reddav.php:51 + /** + * + * @see RedBrowser::set_writeable() + * @var DAV\Browser\Plugin + */ public $browser; - // @fixme include/reddav.php:92 - public $owner_id; - // @fixme include/reddav.php:283 + /** + * channel_id of the current visited path. Set in RedDirectory::getDir(). + * + * @var int + */ + public $owner_id = 0; + /** + * channel_name of the current visited path. Set in RedDirectory::getDir(). + * + * Used for creating the path in cloud/ + * + * @var string + */ public $owner_nick = ''; - // @fixme mod/cloud.php:66 - public $timezone; + /** + * Timezone from the visiting channel's channel_timezone. + * + * Used in @ref RedBrowser + * + * @var string + */ + protected $timezone = ''; + /** + * @brief Validates a username and password. + * + * Guest access is granted with the password "+++". * + * @see DAV\Auth\Backend\AbstractBasic::validateUserPass * @param string $username * @param string $password + * @return bool */ protected function validateUserPass($username, $password) { - if (trim($password) === '+++') { - logger('reddav: validateUserPass: guest ' . $username); + logger('(DAV): RedBasicAuth::validateUserPass(): guest ' . $username); return true; } require_once('include/auth.php'); $record = account_verify_password($username, $password); if ($record && $record['account_default_channel']) { - $r = q("select * from channel where channel_account_id = %d and channel_id = %d limit 1", + $r = q("SELECT * FROM channel WHERE channel_account_id = %d AND channel_id = %d LIMIT 1", intval($record['account_id']), intval($record['account_default_channel']) ); if ($r) { - $this->currentUser = $r[0]['channel_address']; - $this->channel_name = $r[0]['channel_address']; - $this->channel_id = $r[0]['channel_id']; - $this->channel_hash = $this->observer = $r[0]['channel_hash']; - $_SESSION['uid'] = $r[0]['channel_id']; - $_SESSION['account_id'] = $r[0]['channel_account_id']; - $_SESSION['authenticated'] = true; - return true; + return $this->setAuthenticated($r[0]); } } - $r = q("select * from channel where channel_address = '%s' limit 1", + $r = q("SELECT * FROM channel WHERE channel_address = '%s' LIMIT 1", dbesc($username) ); if ($r) { - $x = q("select * from account where account_id = %d limit 1", + $x = q("SELECT account_flags, account_salt, account_password FROM account WHERE account_id = %d LIMIT 1", intval($r[0]['channel_account_id']) ); if ($x) { + // @fixme this foreach should not be needed? foreach ($x as $record) { if (($record['account_flags'] == ACCOUNT_OK) || ($record['account_flags'] == ACCOUNT_UNVERIFIED) && (hash('whirlpool', $record['account_salt'] . $password) === $record['account_password'])) { logger('(DAV) RedBasicAuth: password verified for ' . $username); - $this->currentUser = $r[0]['channel_address']; - $this->channel_name = $r[0]['channel_address']; - $this->channel_id = $r[0]['channel_id']; - $this->channel_hash = $this->observer = $r[0]['channel_hash']; - $_SESSION['uid'] = $r[0]['channel_id']; - $_SESSION['account_id'] = $r[0]['channel_account_id']; - $_SESSION['authenticated'] = true; - return true; + return $this->setAuthenticated($r[0]); } } } @@ -1051,12 +1091,68 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic { return false; } + /** + * @brief Sets variables and session parameters after successfull authentication. + * + * @param array $r + * Array with the values for the authenticated channel. + * @return bool + */ + protected function setAuthenticated($r) { + $this->channel_name = $r['channel_address']; + $this->channel_id = $r['channel_id']; + $this->channel_hash = $this->observer = $r['channel_hash']; + $_SESSION['uid'] = $r['channel_id']; + $_SESSION['account_id'] = $r['channel_account_id']; + $_SESSION['authenticated'] = true; + return true; + } + + /** + * Sets the channel_name from the currently logged-in channel. + * + * @param string $name + * The channel's name + */ public function setCurrentUser($name) { - $this->currentUser = $name; + $this->channel_name = $name; + } + /** + * Returns information about the currently logged-in channel. + * + * If nobody is currently logged in, this method should return null. + * + * @see DAV\Auth\Backend\AbstractBasic::getCurrentUser + * @return string|null + */ + public function getCurrentUser() { + return $this->channel_name; } /** - * @brief Set browser plugin. + * @brief Sets the timezone from the channel in RedBasicAuth. + * + * Set in mod/cloud.php if the channel has a timezone set. + * + * @param string $timezone + * The channel's timezone. + * @return void + */ + public function setTimezone($timezone) { + $this->timezone = $timezone; + } + /** + * @brief Returns the timezone. + * + * @return string + * Return the channel's timezone. + */ + public function getTimezone() { + return $this->timezone; + } + + /** + * @brief Set browser plugin for SabreDAV. * * @see RedBrowser::set_writeable() * @param DAV\Browser\Plugin $browser @@ -1065,8 +1161,12 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic { $this->browser = $browser; } - // internal? logging function - function log() { + /** + * Prints out all RedBasicAuth variables to logger(). + * + * @return void + */ + public function log() { logger('dav: auth: channel_name ' . $this->channel_name, LOGGER_DATA); logger('dav: auth: channel_id ' . $this->channel_id, LOGGER_DATA); logger('dav: auth: channel_hash ' . $this->channel_hash, LOGGER_DATA); @@ -1080,13 +1180,23 @@ class RedBasicAuth extends DAV\Auth\Backend\AbstractBasic { /** - * RedBrowser class. + * @brief RedBrowser class. * + * RedBrowser is a SabreDAV server-plugin to provide a view to the DAV in + * the browser */ class RedBrowser extends DAV\Browser\Plugin { + /** + * @var RedBasicAuth + */ private $auth; + /** + * @brief Constructor for RedBrowser. + * + * @param RedBasicAuth &$auth + */ function __construct(&$auth) { $this->auth = $auth; $this->enableAssets = false; @@ -1096,6 +1206,7 @@ class RedBrowser extends DAV\Browser\Plugin { // directory and who the owner and observer are. So we add a pointer to the browser into the auth module and vice // versa. Then when we've figured out what directory is actually being accessed, we call the following function // to decide whether or not to show web elements which include writeable objects. + // @todo Maybe this can be solved with some $server->subscribeEvent()? function set_writeable() { if (! $this->auth->owner_id) { $this->enablePost = false; @@ -1117,8 +1228,8 @@ class RedBrowser extends DAV\Browser\Plugin { // (owner_id = channel_id) is visitor owner of this directory? $is_owner = ((local_user() && $this->auth->owner_id == local_user()) ? true : false); - if ($this->auth->timezone) - date_default_timezone_set($this->auth->timezone); + if ($this->auth->getTimezone()) + date_default_timezone_set($this->auth->getTimezone()); require_once('include/conversation.php'); @@ -1237,7 +1348,7 @@ class RedBrowser extends DAV\Browser\Plugin { // put the array for this file together $ft['attachId'] = $this->findAttachIdByHash($attachHash); - $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->channel_name; + $ft['fileStorageUrl'] = substr($fullPath, 0, strpos($fullPath, "cloud/")) . "filestorage/" . $this->auth->getCurrentUser(); $ft['icon'] = $icon; $ft['attachIcon'] = (($size) ? $attachIcon : ''); // @todo Should this be an item value, not a global one? diff --git a/install/INSTALL.txt b/install/INSTALL.txt index ee9900cb8..09e840498 100644 --- a/install/INSTALL.txt +++ b/install/INSTALL.txt @@ -66,7 +66,7 @@ local .htaccess file php.ini file - and with no hosting provider restrictions on the use of exec() and proc_open(). - - curl, gd (with at least jpeg support), mysqli, mbstring, mcrypt, and openssl extensions. The imagick extension is not required but desirable. + - curl, gd (with at least jpeg and png support), mysqli, mbstring, mcrypt, and openssl extensions. The imagick extension is not required but desirable. - some form of email server or email gateway such that PHP mail() works diff --git a/mod/cloud.php b/mod/cloud.php index 1765c0b69..c21c4c4b6 100644 --- a/mod/cloud.php +++ b/mod/cloud.php @@ -1,31 +1,34 @@ <?php /** * @file mod/cloud.php - * @brief Initialize Red Matrix's cloud (SabreDAV) + * @brief Initialize RedMatrix's cloud (SabreDAV). * + * Module for accessing the DAV storage area. */ - use Sabre\DAV; - require_once('vendor/autoload.php'); +use Sabre\DAV; - // workaround for HTTP-auth in CGI mode - if(x($_SERVER,'REDIRECT_REMOTE_USER')) { - $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } - } +// composer autoloader for SabreDAV +require_once('vendor/autoload.php'); - if(x($_SERVER,'HTTP_AUTHORIZATION')) { - $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; - if(strlen($userpass)) { - list($name, $password) = explode(':', $userpass); - $_SERVER['PHP_AUTH_USER'] = $name; - $_SERVER['PHP_AUTH_PW'] = $password; - } +// workaround for HTTP-auth in CGI mode +if(x($_SERVER, 'REDIRECT_REMOTE_USER')) { + $userpass = base64_decode(substr($_SERVER["REDIRECT_REMOTE_USER"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; + } +} + +if(x($_SERVER, 'HTTP_AUTHORIZATION')) { + $userpass = base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)) ; + if(strlen($userpass)) { + list($name, $password) = explode(':', $userpass); + $_SERVER['PHP_AUTH_USER'] = $name; + $_SERVER['PHP_AUTH_PW'] = $password; } +} /** * @brief Fires up the SabreDAV server. @@ -33,14 +36,12 @@ * @param App &$a */ function cloud_init(&$a) { - // call ($currenttheme)_init since we're operating outside of index.php - - $theme_info_file = "view/theme/".current_theme()."/php/theme.php"; + $theme_info_file = "view/theme/" . current_theme() . "/php/theme.php"; if (file_exists($theme_info_file)){ require_once($theme_info_file); - if(function_exists(str_replace('-','_',current_theme()) . '_init')) { - $func = str_replace('-','_',current_theme()) . '_init'; + if(function_exists(str_replace('-', '_', current_theme()) . '_init')) { + $func = str_replace('-', '_', current_theme()) . '_init'; $func($a); } } @@ -48,16 +49,15 @@ function cloud_init(&$a) { require_once('include/reddav.php'); if(! is_dir('store')) - os_mkdir('store',STORAGE_DEFAULT_PERMISSIONS,false); + os_mkdir('store', STORAGE_DEFAULT_PERMISSIONS, false); $which = null; if(argc() > 1) $which = argv(1); $profile = 0; - $channel = $a->get_channel(); - $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which . '" />' . "\r\n" ; + $a->page['htmlhead'] .= '<link rel="alternate" type="application/atom+xml" href="' . $a->get_baseurl() . '/feed/' . $which . '" />' . "\r\n"; if($which) profile_load($a, $which, $profile); @@ -70,12 +70,11 @@ function cloud_init(&$a) { if(local_user()) { $channel = $a->get_channel(); $auth->setCurrentUser($channel['channel_address']); - $auth->channel_name = $channel['channel_address']; $auth->channel_id = $channel['channel_id']; $auth->channel_hash = $channel['channel_hash']; $auth->channel_account_id = $channel['channel_account_id']; if($channel['channel_timezone']) - $auth->timezone = $channel['channel_timezone']; + $auth->setTimezone($channel['channel_timezone']); } $auth->observer = $ob_hash; } @@ -83,13 +82,13 @@ function cloud_init(&$a) { if($_GET['davguest']) $_SESSION['davguest'] = true; - $_SERVER['QUERY_STRING'] = str_replace(array('?f=','&f='),array('',''),$_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['QUERY_STRING']); $_SERVER['QUERY_STRING'] = strip_zids($_SERVER['QUERY_STRING']); - $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism','',$_SERVER['QUERY_STRING']); + $_SERVER['QUERY_STRING'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['QUERY_STRING']); - $_SERVER['REQUEST_URI'] = str_replace(array('?f=','&f='),array('',''),$_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = str_replace(array('?f=', '&f='), array('', ''), $_SERVER['REQUEST_URI']); $_SERVER['REQUEST_URI'] = strip_zids($_SERVER['REQUEST_URI']); - $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism','',$_SERVER['REQUEST_URI']); + $_SERVER['REQUEST_URI'] = preg_replace('/[\?&]davguest=(.*?)([\?&]|$)/ism', '', $_SERVER['REQUEST_URI']); $rootDirectory = new RedDirectory('/', $auth); @@ -101,11 +100,15 @@ function cloud_init(&$a) { $server->addPlugin($lockPlugin); - // The next section of code allows us to bypass prompting for http-auth if a FILE is being accessed anonymously and permissions - // allow this. This way one can create hotlinks to public media files in their cloud and anonymous viewers won't get asked to login. - // If a DIRECTORY is accessed or there are permission issues accessing the file and we aren't previously authenticated via zot, - // prompt for HTTP-auth. This will be the default case for mounting a DAV directory. - // In order to avoid prompting for passwords for viewing a DIRECTORY, add the URL query parameter 'davguest=1' + // The next section of code allows us to bypass prompting for http-auth if a + // FILE is being accessed anonymously and permissions allow this. This way + // one can create hotlinks to public media files in their cloud and anonymous + // viewers won't get asked to login. + // If a DIRECTORY is accessed or there are permission issues accessing the + // file and we aren't previously authenticated via zot, prompt for HTTP-auth. + // This will be the default case for mounting a DAV directory. + // In order to avoid prompting for passwords for viewing a DIRECTORY, add + // the URL query parameter 'davguest=1'. $isapublic_file = false; $davguest = ((x($_SESSION, 'davguest')) ? true : false); @@ -116,22 +119,21 @@ function cloud_init(&$a) { if($x instanceof RedFile) $isapublic_file = true; } - catch ( Exception $e ) { + catch (Exception $e) { $isapublic_file = false; } } if((! $auth->observer) && (! $isapublic_file) && (! $davguest)) { try { - $auth->Authenticate($server, t('Red Matrix - Guests: Username: {your email address}, Password: +++')); + $auth->Authenticate($server, t('RedMatrix - Guests: Username: {your email address}, Password: +++')); } - catch ( Exception $e) { + catch (Exception $e) { logger('mod_cloud: auth exception' . $e->getMessage()); http_status_exit($e->getHTTPCode(), $e->getMessage()); } } - // provide a directory view for the cloud in Red Matrix $browser = new RedBrowser($auth); diff --git a/mod/photo.php b/mod/photo.php index 9302278b6..0329fe0a8 100644 --- a/mod/photo.php +++ b/mod/photo.php @@ -71,7 +71,7 @@ function photo_init(&$a) { } if(! isset($data)) { $data = file_get_contents($default); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; } } else { @@ -176,15 +176,15 @@ function photo_init(&$a) { case 4: $data = file_get_contents(get_default_profile_photo()); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; case 5: $data = file_get_contents(get_default_profile_photo(80)); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; case 6: $data = file_get_contents(get_default_profile_photo(48)); - $mimetype = 'image/jpeg'; + $mimetype = 'image/png'; break; default: killme(); |