aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md9
-rwxr-xr-xboot.php2
-rw-r--r--include/account.php22
-rw-r--r--include/config.php19
-rw-r--r--include/identity.php42
-rw-r--r--include/photo/photo_driver.php3
-rw-r--r--include/photo/photo_gd.php17
-rw-r--r--include/photo/photo_imagick.php18
-rwxr-xr-xinclude/plugin.php37
-rwxr-xr-xindex.php8
-rw-r--r--install/INSTALL.txt38
-rw-r--r--mod/admin.php44
-rw-r--r--mod/cover_photo.php391
-rw-r--r--mod/profile_photo.php4
-rw-r--r--mod/register.php64
-rw-r--r--mod/regmod.php4
-rw-r--r--mod/regver.php4
-rw-r--r--mod/share.php2
-rwxr-xr-xutil/addons132
-rwxr-xr-xutil/hz36
-rw-r--r--version.inc2
-rw-r--r--view/css/mod_mail.css2
-rw-r--r--view/css/mod_register.css37
-rw-r--r--view/js/mod_register.js21
-rwxr-xr-xview/tpl/admin_plugins.tpl6
-rwxr-xr-xview/tpl/admin_plugins_details.tpl19
-rwxr-xr-xview/tpl/cover_photo.tpl23
-rwxr-xr-xview/tpl/cropcover.tpl58
-rwxr-xr-xview/tpl/register.tpl34
29 files changed, 1043 insertions, 55 deletions
diff --git a/README.md b/README.md
index b6750480e..645065948 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,9 @@ Hubzilla - Community Server
Help us redefine the web - using integrated and united community websites.
--------------------------------------------------------------------------
-[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla)
+<p align="center" markdown="1">
+<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
+</p>
**What are Hubs?**
@@ -38,3 +40,8 @@ Possible website applications include
* dating websites
* pretty much anything you can do on a traditional blog or community website, but that you could do better if you could easily connect it with other websites or privately share things across website boundaries.
+<p align="center" markdown="1">
+<em><a href="https://github.com/redmatrix/hubzilla/blob/master/install/INSTALL.txt">Installing Hubzilla</a></em>
+</p>
+
+[![Build Status](https://travis-ci.org/redmatrix/hubzilla.svg)](https://travis-ci.org/redmatrix/hubzilla)
diff --git a/boot.php b/boot.php
index f58709384..599514d20 100755
--- a/boot.php
+++ b/boot.php
@@ -48,7 +48,7 @@ require_once('include/AccessList.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'RED_VERSION', trim(file_get_contents('version.inc')));
-define ( 'STD_VERSION', '1.1' );
+define ( 'STD_VERSION', '1.1.1' );
define ( 'ZOT_REVISION', 1 );
define ( 'DB_UPDATE_VERSION', 1161 );
diff --git a/include/account.php b/include/account.php
index e448bdcc6..dae0f4895 100644
--- a/include/account.php
+++ b/include/account.php
@@ -11,6 +11,7 @@ require_once('include/text.php');
require_once('include/language.php');
require_once('include/datetime.php');
require_once('include/crypto.php');
+require_once('include/identity.php');
function check_account_email($email) {
@@ -329,7 +330,7 @@ function send_reg_approval_email($arr) {
return($delivered ? true : false);
}
-function send_verification_email($email,$password) {
+function send_register_success_email($email,$password) {
$email_msg = replace_macros(get_intltext_template('register_open_eml.tpl'), array(
'$sitename' => get_config('system','sitename'),
@@ -353,7 +354,7 @@ function send_verification_email($email,$password) {
* @param string $hash
* @return array|boolean
*/
-function user_allow($hash) {
+function account_allow($hash) {
$ret = array('success' => false);
@@ -406,6 +407,9 @@ function user_allow($hash) {
pop_lang();
+ if(get_config('system','auto_channel_create'))
+ auto_channel_create($register[0]['uid']);
+
if ($res) {
info( t('Account approved.') . EOL );
return true;
@@ -414,7 +418,7 @@ function user_allow($hash) {
/**
- * @brief Denies a user registration.
+ * @brief Denies an account registration.
*
* This does not have to go through user_remove() and save the nickname
* permanently against re-registration, as the person was not yet
@@ -423,7 +427,8 @@ function user_allow($hash) {
* @param string $hash
* @return boolean
*/
-function user_deny($hash) {
+
+function account_deny($hash) {
$register = q("SELECT * FROM register WHERE hash = '%s' LIMIT 1",
dbesc($hash)
@@ -452,11 +457,14 @@ function user_deny($hash) {
}
+// called from regver to activate an account from the email verification link
-function user_approve($hash) {
+function account_approve($hash) {
$ret = array('success' => false);
+ // Note: when the password in the register table is 'verify', the uid actually contains the account_id
+
$register = q("SELECT * FROM `register` WHERE `hash` = '%s' and password = 'verify' LIMIT 1",
dbesc($hash)
);
@@ -491,6 +499,10 @@ function user_approve($hash) {
intval($register[0]['uid'])
);
+
+ if(get_config('system','auto_channel_create'))
+ auto_channel_create($register[0]['uid']);
+
info( t('Account verified. Please login.') . EOL );
return true;
diff --git a/include/config.php b/include/config.php
index c94d25eb8..f65e4a470 100644
--- a/include/config.php
+++ b/include/config.php
@@ -531,3 +531,22 @@ function del_xconfig($xchan, $family, $key) {
);
return $ret;
}
+
+
+// account configuration storage is built on top of the under-utilised xconfig
+
+function load_aconfig($account_id) {
+ load_xconfig('a_' . $account_id);
+}
+
+function get_aconfig($account_id, $family, $key) {
+ return get_xconfig('a_' . $account_id, $family, $key);
+}
+
+function set_aconfig($account_id, $family, $key, $value) {
+ return set_xconfig('a_' . $account_id, $family, $key, $value);
+}
+
+function del_aconfig($account_id, $family, $key) {
+ return del_xconfig('a_' . $account_id, $family, $key);
+} \ No newline at end of file
diff --git a/include/identity.php b/include/identity.php
index cfedd243a..1d908056f 100644
--- a/include/identity.php
+++ b/include/identity.php
@@ -1695,3 +1695,45 @@ function profiles_build_sync($channel_id) {
build_sync_packet($channel_id,array('profile' => $r));
}
}
+
+
+function auto_channel_create($account_id) {
+
+ if(! $account_id)
+ return false;
+
+ $arr = array();
+ $arr['account_id'] = $account_id;
+ $arr['name'] = get_aconfig($account_id,'register','channel_name');
+ $arr['nickname'] = legal_webbie(get_aconfig($account_id,'register','channel_address'));
+ $arr['permissions_role'] = get_aconfig($account_id,'register','permissions_role');
+
+ del_aconfig($account_id,'register','channel_name');
+ del_aconfig($account_id,'register','channel_address');
+ del_aconfig($account_id,'register','permissions_role');
+
+ if((! $arr['name']) || (! $arr['nickname'])) {
+ $x = q("select * from account where account_id = %d limit 1",
+ intval($account_id)
+ );
+ if($x) {
+ if(! $arr['name'])
+ $arr['name'] = substr($x[0]['account_email'],0,strpos($x[0]['account_email'],'@'));
+ if(! $arr['nickname'])
+ $arr['nickname'] = legal_webbie(substr($x[0]['account_email'],0,strpos($x[0]['account_email'],'@')));
+ }
+ }
+ if(! $arr['permissions_role'])
+ $arr['permissions_role'] = 'social';
+
+ if(validate_channelname($arr['name']))
+ return false;
+ if($arr['nickname'] === 'sys')
+ $arr['nickname'] = $arr['nickname'] . mt_rand(1000,9999);
+
+ $arr['nickname'] = check_webbie(array($arr['nickname'], $arr['nickname'] . mt_rand(1000,9999)));
+
+ return create_identity($arr);
+
+}
+
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 0de3b9c97..dce92d8da 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -69,6 +69,8 @@ abstract class photo_driver {
abstract function cropImage($max,$x,$y,$w,$h);
+ abstract function cropImageRect($maxx,$maxy,$x,$y,$w,$h);
+
abstract function imageString();
@@ -229,6 +231,7 @@ abstract class photo_driver {
$this->doScaleImage($dest_width,$dest_height);
}
+
public function scaleImageSquare($dim) {
if(!$this->is_valid())
return FALSE;
diff --git a/include/photo/photo_gd.php b/include/photo/photo_gd.php
index 2ac7287e4..24bdc204f 100644
--- a/include/photo/photo_gd.php
+++ b/include/photo/photo_gd.php
@@ -108,6 +108,23 @@ class photo_gd extends photo_driver {
$this->setDimensions();
}
+ public function cropImageRect($maxx,$maxy,$x,$y,$w,$h) {
+ if(!$this->is_valid())
+ return FALSE;
+
+ $dest = imagecreatetruecolor( $maxx, $maxy );
+ imagealphablending($dest, false);
+ imagesavealpha($dest, true);
+ if ($this->type=='image/png') imagefill($dest, 0, 0, imagecolorallocatealpha($dest, 0, 0, 0, 127)); // fill with alpha
+ imagecopyresampled($dest, $this->image, 0, 0, $x, $y, $maxx, $maxy, $w, $h);
+ if($this->image)
+ imagedestroy($this->image);
+ $this->image = $dest;
+ $this->setDimensions();
+ }
+
+
+
public function imageString() {
if(!$this->is_valid())
return FALSE;
diff --git a/include/photo/photo_imagick.php b/include/photo/photo_imagick.php
index 3f84fd06c..32bb61342 100644
--- a/include/photo/photo_imagick.php
+++ b/include/photo/photo_imagick.php
@@ -163,6 +163,24 @@ class photo_imagick extends photo_driver {
$this->doScaleImage($max,$max);
}
+ public function cropImageRect($maxx,$maxy,$x,$y,$w,$h) {
+ if(!$this->is_valid())
+ return FALSE;
+
+ $this->image->setFirstIterator();
+ do {
+ $this->image->cropImage($w, $h, $x, $y);
+ /**
+ * We need to remove the canvas,
+ * or the image is not resized to the crop:
+ * http://php.net/manual/en/imagick.cropimage.php#97232
+ */
+ $this->image->setImagePage(0, 0, 0, 0);
+ } while ($this->image->nextImage());
+
+ $this->doScaleImage($maxx,$maxy);
+ }
+
public function imageString() {
if(!$this->is_valid())
return FALSE;
diff --git a/include/plugin.php b/include/plugin.php
index 4da73dfd8..2bc363556 100755
--- a/include/plugin.php
+++ b/include/plugin.php
@@ -348,19 +348,46 @@ function get_plugin_info($plugin){
} else {
$info[$k][] = array('name' => $v);
}
- } else {
-// if (array_key_exists($k, $info)){
- $info[$k] = $v;
-// }
+ }
+ else {
+ $info[$k] = $v;
}
}
}
}
-
return $info;
}
+function check_plugin_versions($info) {
+
+ if(! is_array($info))
+ return true;
+
+ if(array_key_exists('minversion',$info)) {
+ if(version_compare(trim($info['minversion']),STD_VERSION, '>=')) {
+ logger('minversion limit: ' . $info['name'],LOGGER_NORMAL,LOG_WARNING);
+ return false;
+ }
+ }
+ if(array_key_exists('maxversion',$info)) {
+ if(version_compare(STD_VERSION,trim($info['maxversion']), '>')) {
+ logger('maxversion limit: ' . $info['name'],LOGGER_NORMAL,LOG_WARNING);
+ return false;
+ }
+ }
+ if(array_key_exists('minphpversion',$info)) {
+ if(version_compare(trim($info['minphpversion']),PHP_VERSION, '>=')) {
+ logger('minphpversion limit: ' . $info['name'],LOGGER_NORMAL,LOG_WARNING);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+
/**
* @brief Parse theme comment in search of theme infos.
diff --git a/index.php b/index.php
index 6ed7eeb11..c864a7b37 100755
--- a/index.php
+++ b/index.php
@@ -336,11 +336,13 @@ if($a->module_loaded) {
}
if((! $a->error) && (function_exists($a->module . '_content'))) {
- $arr = array('content' => $a->page['content']);
+ $arr = array('content' => $a->page['content'], 'replace' => false);
call_hooks($a->module . '_mod_content', $arr);
$a->page['content'] = $arr['content'];
- $func = $a->module . '_content';
- $arr = array('content' => $func($a));
+ if(! $arr['replace']) {
+ $func = $a->module . '_content';
+ $arr = array('content' => $func($a));
+ }
call_hooks($a->module . '_mod_aftercontent', $arr);
$a->page['content'] .= $arr['content'];
}
diff --git a/install/INSTALL.txt b/install/INSTALL.txt
index 8ca74c23b..78cea638d 100644
--- a/install/INSTALL.txt
+++ b/install/INSTALL.txt
@@ -1,6 +1,6 @@
Hubzilla Installation
-We've tried very hard to ensure that the Hubzilla will run on commodity
+We've tried very hard to ensure that Hubzilla will run on commodity
hosting platforms - such as those used to host Wordpress blogs and Drupal
websites. It will run on most any Linux VPS system. Windows LAMP platforms
such as XAMPP and WAMP are not officially supported at this time - however
@@ -29,7 +29,7 @@ issues.
Before you begin: Choose a domain name or subdomain name for your server.
-The Hubzilla can only be installed into the root of a domain or
+Hubzilla can only be installed into the root of a domain or
sub-domain, and can not be installed using alternate TCP ports.
Decide if you will use SSL and obtain an SSL certificate before software
@@ -53,13 +53,14 @@ advice. This is disruptive to the community. That said, we recognise the issues
surrounding the current certificate infrastructure and agree there are many
problems, but that doesn't change the requirement.
-Free "browser-valid" certificates are available from providers such as StartSSL.
+Free "browser-valid" certificates are available from providers such as StartSSL
+and LetsEncrypt.
If you do NOT use SSL, there may be a delay of up to a minute for the initial
install script - while we check the SSL port to see if anything responds there.
When communicating with new sites, Hubzilla always attempts connection on the
SSL port first, before falling back to a less secure connection. If you do not
-use SSL, your webserver must not listen on port 443 at all.
+use SSL, your webserver MUST NOT listen on port 443 at all.
1. Requirements
- Apache with mod-rewrite enabled and "AllowOverride All" so you can use a
@@ -137,7 +138,7 @@ use SSL, your webserver must not listen on port 443 at all.
cd mywebsite
util/update_addon_repo matrix
- - Create searchable represenations of the online documentation. You may do this any time
+ - Create searchable representations of the online documentation. You may do this any time
that the documentation is updated.
cd mywebsite
@@ -177,7 +178,16 @@ Registration errors should all be recoverable automatically.
If you get any *critical* failure at this point, it generally indicates the
database was not installed correctly. You might wish to move/rename
.htconfig.php to another name and empty (called 'dropping') the database
-tables, so that you can start fresh.
+tables, so that you can start fresh.
+
+In order for your account to be given administrator access, it should be the
+first account created, and the email address provided during registration
+must match the "administrator email" address you provided during
+installation. Otherwise to give an account administrator access,
+add 4096 to the account_roles for that account in the database.
+
+For your site security there is no way to provide administrator access
+using web forms.
****************************************************************************
****************************************************************************
@@ -185,7 +195,7 @@ tables, so that you can start fresh.
****************************************************************************
****************************************************************************
-8. Set up a cron job or scheduled task to run the poller once every 5-10
+8. Set up a cron job or scheduled task to run the poller once every 10-15
minutes to pick up the recent "public" postings of your friends. Example:
cd /base/directory; /path/to/php include/poller.php
@@ -201,10 +211,11 @@ You can generally find the location of PHP by executing "which php". If you
have troubles with this section please contact your hosting provider for
assistance. Hubzilla will not work correctly if you cannot perform this step.
-You should also be sure that $a->config['system']['php_path'] is set correctly,
-it should look like (changing it to the correct PHP location)
+You should also be sure that $a->config['system']['php_path'] is set correctly
+in your .htconfig.php file, it should look like (changing it to the correct
+PHP location):
-$a->config['system']['php_path'] = '/usr/local/php53/bin/php';
+$a->config['system']['php_path'] = '/usr/local/php55/bin/php';
#####################################################################
@@ -221,7 +232,7 @@ $a->config['system']['php_path'] = '/usr/local/php53/bin/php';
Check your database settings. It usually means your database could not be
opened or accessed. If the database resides on the same machine, check that
-the database server name is the word "localhost".
+the database server name is "127.0.0.1" or the word "localhost".
#####################################################################
- 500 Internal Error
@@ -296,7 +307,7 @@ Retry the installation. As soon as the database has been created,
#####################################################################
- Some configurations with "suhosin" security are configured without
-an ability to run external processes. The Hubzilla requires this ability.
+an ability to run external processes. Hubzilla requires this ability.
Following are some notes provided by one of our members.
#####################################################################
@@ -386,4 +397,5 @@ MaxRequestWorkers to 70.
Here you can read more about Apache performance tuning:
https://httpd.apache.org/docs/2.4/misc/perf-tuning.html
-There are tons of scripts to help you with fine-tuning your Apache installation. Just search with your favorite search engine 'apache fine-tuning script'.
+There are tons of scripts to help you with fine-tuning your Apache installation.
+Just search with your favorite search engine 'apache fine-tuning script'.
diff --git a/mod/admin.php b/mod/admin.php
index c175a4a61..2d859399b 100644
--- a/mod/admin.php
+++ b/mod/admin.php
@@ -1092,6 +1092,23 @@ function admin_page_plugins(&$a){
return '';
}
+ $enabled = in_array($plugin,$a->plugins);
+ $info = get_plugin_info($plugin);
+ $x = check_plugin_versions($info);
+
+ // disable plugins which are installed but incompatible versions
+
+ if($enabled && ! $x) {
+ $enabled = false;
+ $idz = array_search($plugin, $a->plugins);
+ if ($idz !== false) {
+ unset($a->plugins[$idz]);
+ uninstall_plugin($plugin);
+ set_config("system","addon", implode(", ",$a->plugins));
+ }
+ }
+ $info['disabled'] = 1-intval($x);
+
if (x($_GET,"a") && $_GET['a']=="t"){
check_form_security_token_redirectOnErr('/admin/plugins', 'admin_plugins', 't');
@@ -1142,6 +1159,7 @@ function admin_page_plugins(&$a){
}
}
+
$t = get_markup_template('admin_plugins_details.tpl');
return replace_macros($t, array(
'$title' => t('Administration'),
@@ -1153,9 +1171,14 @@ function admin_page_plugins(&$a){
'$plugin' => $plugin,
'$status' => $status,
'$action' => $action,
- '$info' => get_plugin_info($plugin),
+ '$info' => $info,
'$str_author' => t('Author: '),
'$str_maintainer' => t('Maintainer: '),
+ '$str_minversion' => t('Minimum project version: '),
+ '$str_maxversion' => t('Maximum project version: '),
+ '$str_minphpversion' => t('Minimum PHP version: '),
+
+ '$disabled' => t('Disabled - version incompatibility'),
'$admin_form' => $admin_form,
'$function' => 'plugins',
@@ -1177,7 +1200,23 @@ function admin_page_plugins(&$a){
if (is_dir($file)){
list($tmp, $id) = array_map('trim', explode('/', $file));
$info = get_plugin_info($id);
- $plugins[] = array( $id, (in_array($id, $a->plugins)?"on":"off") , $info);
+ $enabled = in_array($id,$a->plugins);
+ $x = check_plugin_versions($info);
+
+ // disable plugins which are installed but incompatible versions
+
+ if($enabled && ! $x) {
+ $enabled = false;
+ $idz = array_search($id, $a->plugins);
+ if ($idz !== false) {
+ unset($a->plugins[$idz]);
+ uninstall_plugin($id);
+ set_config("system","addon", implode(", ",$a->plugins));
+ }
+ }
+ $info['disabled'] = 1-intval($x);
+
+ $plugins[] = array( $id, (($enabled)?"on":"off") , $info);
}
}
}
@@ -1190,6 +1229,7 @@ function admin_page_plugins(&$a){
'$baseurl' => $a->get_baseurl(true),
'$function' => 'plugins',
'$plugins' => $plugins,
+ '$disabled' => t('Disabled - version incompatibility'),
'$form_security_token' => get_form_security_token('admin_plugins'),
));
}
diff --git a/mod/cover_photo.php b/mod/cover_photo.php
new file mode 100644
index 000000000..fd7d794f5
--- /dev/null
+++ b/mod/cover_photo.php
@@ -0,0 +1,391 @@
+<?php
+
+/* @file cover_photo.php
+ @brief Module-file with functions for handling of profile-photos
+
+*/
+
+require_once('include/photo/photo_driver.php');
+require_once('include/identity.php');
+
+
+
+/* @brief Initalize the cover-photo edit view
+ *
+ * @param $a Current application
+ * @return void
+ *
+ */
+
+function cover_photo_init(&$a) {
+
+ if(! local_channel()) {
+ return;
+ }
+
+ $channel = $a->get_channel();
+ profile_load($a,$channel['channel_address']);
+
+}
+
+/* @brief Evaluate posted values
+ *
+ * @param $a Current application
+ * @return void
+ *
+ */
+
+function cover_photo_post(&$a) {
+
+ if(! local_channel()) {
+ return;
+ }
+
+ check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
+
+ if((x($_POST,'cropfinal')) && ($_POST['cropfinal'] == 1)) {
+
+ // phase 2 - we have finished cropping
+
+ if(argc() != 2) {
+ notice( t('Image uploaded but image cropping failed.') . EOL );
+ return;
+ }
+
+ $image_id = argv(1);
+
+ if(substr($image_id,-2,1) == '-') {
+ $scale = substr($image_id,-1,1);
+ $image_id = substr($image_id,0,-2);
+ }
+
+
+ $srcX = $_POST['xstart'];
+ $srcY = $_POST['ystart'];
+ $srcW = $_POST['xfinal'] - $srcX;
+ $srcH = $_POST['yfinal'] - $srcY;
+
+ $r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND scale = 0 LIMIT 1",
+ dbesc($image_id),
+ intval(local_channel())
+ );
+
+ if($r) {
+
+ $base_image = $r[0];
+ $base_image['data'] = (($r[0]['os_storage']) ? @file_get_contents($base_image['data']) : dbunescbin($base_image['data']));
+
+ $im = photo_factory($base_image['data'], $base_image['type']);
+ if($im->is_valid()) {
+
+ $g = q("select width, height from photo where resource_id = '%s' and uid = %d and scale = 3",
+ dbesc($image_id),
+ intval(local_channel())
+ );
+
+ // scale these numbers to the original photo instead of the scaled photo we operated on
+
+ $scaled_width = $g[0]['width'];
+ $scaled_height = $g[0]['height'];
+
+ if((! $scaled_width) || (! $scaled_height)) {
+ logger('potential divide by zero scaling cover photo');
+ return;
+ }
+
+ $orig_srcx = ( $r[0]['width'] / $scaled_width ) * $srcX;
+ $orig_srcy = ( $r[0]['height'] / $scaled_height ) * $srcY;
+ $orig_srcw = ( $srcW / $scaled_width ) * $r[0]['width'];
+ $orig_srch = ( $srcH / $scaled_height ) * $r[0]['height'];
+
+ $im->cropImageRect(1200,435,$orig_srcx, $orig_srcy, $orig_srcw, $orig_srch);
+
+ $aid = get_account_id();
+
+ $p = array('aid' => $aid, 'uid' => local_channel(), 'resource_id' => $base_image['resource_id'],
+ 'filename' => $base_image['filename'], 'album' => t('Profile Photos'));
+
+ $p['scale'] = 7;
+ $p['photo_usage'] = PHOTO_COVER;
+
+ $r1 = $im->save($p);
+
+ $im->doScaleImage(850,310);
+ $p['scale'] = 8;
+
+ $r2 = $im->save($p);
+
+ if($r1 === false || $r2 === false) {
+ // if one failed, delete them all so we can start over.
+ notice( t('Image resize failed.') . EOL );
+ $x = q("delete from photo where resource_id = '%s' and uid = %d and scale >= 7 ",
+ dbesc($base_image['resource_id']),
+ local_channel()
+ );
+ return;
+ }
+
+ $channel = $a->get_channel();
+
+
+ }
+ else
+ notice( t('Unable to process image') . EOL);
+ }
+
+ goaway($a->get_baseurl() . '/profiles');
+ return; // NOTREACHED
+ }
+
+
+ $hash = photo_new_resource();
+ $smallest = 0;
+
+ require_once('include/attach.php');
+
+ $res = attach_store($a->get_channel(), get_observer_hash(), '', array('album' => t('Profile Photos'), 'hash' => $hash));
+
+ logger('attach_store: ' . print_r($res,true));
+
+ if($res && intval($res['data']['is_photo'])) {
+ $i = q("select * from photo where resource_id = '%s' and uid = %d and scale = 0",
+ dbesc($hash),
+ intval(local_channel())
+ );
+
+ if(! $i) {
+ notice( t('Image upload failed.') . EOL );
+ return;
+ }
+ $os_storage = false;
+
+ foreach($i as $ii) {
+ $smallest = intval($ii['scale']);
+ $os_storage = intval($ii['os_storage']);
+ $imagedata = $ii['data'];
+ $filetype = $ii['type'];
+
+ }
+ }
+
+ $imagedata = (($os_storage) ? @file_get_contents($imagedata) : $imagedata);
+ $ph = photo_factory($imagedata, $filetype);
+
+ if(! $ph->is_valid()) {
+ notice( t('Unable to process image.') . EOL );
+ return;
+ }
+
+ return cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
+
+}
+
+function send_cover_photo_activity($channel,$photo,$profile) {
+
+ // for now only create activities for the default profile
+
+ if(! intval($profile['is_default']))
+ return;
+
+ $arr = array();
+ $arr['item_thread_top'] = 1;
+ $arr['item_origin'] = 1;
+ $arr['item_wall'] = 1;
+ $arr['obj_type'] = ACTIVITY_OBJ_PHOTO;
+ $arr['verb'] = ACTIVITY_UPDATE;
+
+ $arr['object'] = json_encode(array(
+ 'type' => $arr['obj_type'],
+ 'id' => z_root() . '/photo/profile/l/' . $channel['channel_id'],
+ 'link' => array('rel' => 'photo', 'type' => $photo['type'], 'href' => z_root() . '/photo/profile/l/' . $channel['channel_id'])
+ ));
+
+ if(stripos($profile['gender'],t('female')) !== false)
+ $t = t('%1$s updated her %2$s');
+ elseif(stripos($profile['gender'],t('male')) !== false)
+ $t = t('%1$s updated his %2$s');
+ else
+ $t = t('%1$s updated their %2$s');
+
+ $ptext = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $photo['resource_id'] . ']' . t('profile photo') . '[/zrl]';
+
+ $ltext = '[zrl=' . z_root() . '/profile/' . $channel['channel_address'] . ']' . '[zmg=150x150]' . z_root() . '/photo/' . $photo['resource_id'] . '-4[/zmg][/zrl]';
+
+ $arr['body'] = sprintf($t,$channel['channel_name'],$ptext) . "\n\n" . $ltext;
+
+ $acl = new AccessList($channel);
+ $x = $acl->get();
+ $arr['allow_cid'] = $x['allow_cid'];
+
+ $arr['allow_gid'] = $x['allow_gid'];
+ $arr['deny_cid'] = $x['deny_cid'];
+ $arr['deny_gid'] = $x['deny_gid'];
+
+ $arr['uid'] = $channel['channel_id'];
+ $arr['aid'] = $channel['channel_account_id'];
+
+ $arr['owner_xchan'] = $channel['channel_hash'];
+ $arr['author_xchan'] = $channel['channel_hash'];
+
+ post_activity_item($arr);
+
+
+}
+
+
+/* @brief Generate content of profile-photo view
+ *
+ * @param $a Current application
+ * @return void
+ *
+ */
+
+
+function cover_photo_content(&$a) {
+
+ if(! local_channel()) {
+ notice( t('Permission denied.') . EOL );
+ return;
+ }
+
+ $channel = $a->get_channel();
+
+ $newuser = false;
+
+ if(argc() == 2 && argv(1) === 'new')
+ $newuser = true;
+
+ if(argv(1) === 'use') {
+ if (argc() < 3) {
+ notice( t('Permission denied.') . EOL );
+ return;
+ };
+
+// check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
+
+ $resource_id = argv(2);
+
+ $r = q("SELECT id, album, scale FROM photo WHERE uid = %d AND resource_id = '%s' ORDER BY scale ASC",
+ intval(local_channel()),
+ dbesc($resource_id)
+ );
+ if(! $r) {
+ notice( t('Photo not available.') . EOL );
+ return;
+ }
+ $havescale = false;
+ foreach($r as $rr) {
+ if($rr['scale'] == 7)
+ $havescale = true;
+ }
+
+ $r = q("SELECT `data`, `type`, resource_id, os_storage FROM photo WHERE id = %d and uid = %d limit 1",
+ intval($r[0]['id']),
+ intval(local_channel())
+
+ );
+ if(! $r) {
+ notice( t('Photo not available.') . EOL );
+ return;
+ }
+
+ if(intval($r[0]['os_storage']))
+ $data = @file_get_contents($r[0]['data']);
+ else
+ $data = dbunescbin($r[0]['data']);
+
+ $ph = photo_factory($data, $r[0]['type']);
+ $smallest = 0;
+ if($ph->is_valid()) {
+ // go ahead as if we have just uploaded a new photo to crop
+ $i = q("select resource_id, scale from photo where resource_id = '%s' and uid = %d and scale = 0",
+ dbesc($r[0]['resource_id']),
+ intval(local_channel())
+ );
+
+ if($i) {
+ $hash = $i[0]['resource_id'];
+ foreach($i as $ii) {
+ $smallest = intval($ii['scale']);
+ }
+ }
+ }
+
+ cover_photo_crop_ui_head($a, $ph, $hash, $smallest);
+ }
+
+
+ if(! x($a->data,'imagecrop')) {
+
+ $tpl = get_markup_template('cover_photo.tpl');
+
+ $o .= replace_macros($tpl,array(
+ '$user' => $a->channel['channel_address'],
+ '$lbl_upfile' => t('Upload File:'),
+ '$lbl_profiles' => t('Select a profile:'),
+ '$title' => t('Upload Cover Photo'),
+ '$submit' => t('Upload'),
+ '$profiles' => $profiles,
+ '$form_security_token' => get_form_security_token("cover_photo"),
+// FIXME - yuk
+ '$select' => sprintf('%s %s', t('or'), ($newuser) ? '<a href="' . $a->get_baseurl() . '">' . t('skip this step') . '</a>' : '<a href="'. $a->get_baseurl() . '/photos/' . $a->channel['channel_address'] . '">' . t('select a photo from your photo albums') . '</a>')
+ ));
+
+ call_hooks('cover_photo_content_end', $o);
+
+ return $o;
+ }
+ else {
+ $filename = $a->data['imagecrop'] . '-3';
+ $resolution = 3;
+ $tpl = get_markup_template("cropcover.tpl");
+ $o .= replace_macros($tpl,array(
+ '$filename' => $filename,
+ '$profile' => intval($_REQUEST['profile']),
+ '$resource' => $a->data['imagecrop'] . '-3',
+ '$image_url' => $a->get_baseurl() . '/photo/' . $filename,
+ '$title' => t('Crop Image'),
+ '$desc' => t('Please adjust the image cropping for optimum viewing.'),
+ '$form_security_token' => get_form_security_token("cover_photo"),
+ '$done' => t('Done Editing')
+ ));
+ return $o;
+ }
+
+ return; // NOTREACHED
+}
+
+/* @brief Generate the UI for photo-cropping
+ *
+ * @param $a Current application
+ * @param $ph Photo-Factory
+ * @return void
+ *
+ */
+
+
+
+function cover_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
+
+ $max_length = get_config('system','max_image_length');
+ if(! $max_length)
+ $max_length = MAX_IMAGE_LENGTH;
+ if($max_length > 0)
+ $ph->scaleImage($max_length);
+
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+
+ if($width < 300 || $height < 300) {
+ $ph->scaleImageUp(240);
+ $width = $ph->getWidth();
+ $height = $ph->getHeight();
+ }
+
+
+ $a->data['imagecrop'] = $hash;
+ $a->data['imagecrop_resolution'] = $smallest;
+ $a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), array());
+ return;
+}
+
diff --git a/mod/profile_photo.php b/mod/profile_photo.php
index 2884505f0..0091d0585 100644
--- a/mod/profile_photo.php
+++ b/mod/profile_photo.php
@@ -502,8 +502,8 @@ function profile_photo_crop_ui_head(&$a, $ph, $hash, $smallest){
$width = $ph->getWidth();
$height = $ph->getHeight();
- if($width < 300 || $height < 300) {
- $ph->scaleImageUp(200);
+ if($width < 500 || $height < 500) {
+ $ph->scaleImageUp(400);
$width = $ph->getWidth();
$height = $ph->getHeight();
}
diff --git a/mod/register.php b/mod/register.php
index 2e9967c60..853728e10 100644
--- a/mod/register.php
+++ b/mod/register.php
@@ -1,5 +1,6 @@
<?php
+require_once('include/identity.php');
function register_init(&$a) {
@@ -97,15 +98,22 @@ function register_post(&$a) {
require_once('include/security.php');
+ if($_REQUEST['name'])
+ set_aconfig($result['account']['account_id'],'register','channel_name',$_REQUEST['name']);
+ if($_REQUEST['nickname'])
+ set_aconfig($result['account']['account_id'],'register','channel_address',$_REQUEST['nickname']);
+ if($_REQUEST['permissions_role'])
+ set_aconfig($result['account']['account_id'],'register','permissions_role',$_REQUEST['permissions_role']);
+
+
$using_invites = intval(get_config('system','invitation_only'));
$num_invites = intval(get_config('system','number_invites'));
$invite_code = ((x($_POST,'invite_code')) ? notags(trim($_POST['invite_code'])) : '');
if($using_invites && $invite_code) {
q("delete * from register where hash = '%s'", dbesc($invite_code));
-// @FIXME - this total needs to be stored by account, but pconfig operates on channels
-// This also needs to be considered when using 'invites_remaining' in mod/invite.php
-// set_pconfig($result['account']['account_id'],'system','invites_remaining',$num_invites);
+ // @FIXME - this also needs to be considered when using 'invites_remaining' in mod/invite.php
+ set_aconfig($result['account']['account_id'],'system','invites_remaining',$num_invites);
}
if($policy == REGISTER_OPEN ) {
@@ -113,7 +121,7 @@ function register_post(&$a) {
$res = verify_email_address($result);
}
else {
- $res = send_verification_email($result['email'],$result['password']);
+ $res = send_register_success_email($result['email'],$result['password']);
}
if($res) {
info( t('Registration successful. Please check your email for validation instructions.') . EOL ) ;
@@ -135,28 +143,43 @@ function register_post(&$a) {
}
authenticate_success($result['account'],true,false,true);
+
+ $new_channel = false;
+
+ if(get_config('system','auto_channel_create')) {
+ $new_channel = auto_channel_create($result['account']['account_id']);
+ if($new_channel['success']) {
+ $channel_id = $new_channel['channel']['channel_id'];
+ change_channel($channel_id);
+ $next_page = '~';
+ }
+ else
+ $new_channel = false;
+ }
+ if(! $new_channel) {
+ if(! strlen($next_page = get_config('system','workflow_register_next')))
+ $next_page = 'new_channel';
- if(! strlen($next_page = get_config('system','workflow_register_next')))
- $next_page = 'new_channel';
+ $_SESSION['workflow'] = true;
+ }
- $_SESSION['workflow'] = true;
-
goaway(z_root() . '/' . $next_page);
}
-
-
-
-
function register_content(&$a) {
$registration_is = '';
$other_sites = '';
if(get_config('system','register_policy') == REGISTER_CLOSED) {
+ if(get_config('system','directory_mode') == DIRECTORY_MODE_STANDALONE) {
+ notice( t('Registration on this site is disabled.') . EOL);
+ return;
+ }
+
require_once('mod/pubsites.php');
return pubsites_content($a);
}
@@ -200,7 +223,12 @@ function register_content(&$a) {
$password = ((x($_REQUEST,'password')) ? trim($_REQUEST['password']) : "" );
$password2 = ((x($_REQUEST,'password2')) ? trim($_REQUEST['password2']) : "" );
$invite_code = ((x($_REQUEST,'invite_code')) ? strip_tags(trim($_REQUEST['invite_code'])) : "" );
+ $name = ((x($_REQUEST,'name')) ? escape_tags(trim($_REQUEST['name'])) : "" );
+ $nickname = ((x($_REQUEST,'nickname')) ? strip_tags(trim($_REQUEST['nickname'])) : "" );
+ $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" );
+ $auto_create = get_config('system','auto_channel_create');
+ $default_role = get_config('system','default_permissions_role');
require_once('include/bbcode.php');
@@ -214,7 +242,17 @@ function register_content(&$a) {
'$invite_desc' => t('Membership on this site is by invitation only.'),
'$label_invite' => t('Please enter your invitation code'),
'$invite_code' => $invite_code,
-
+ '$auto_create' => $auto_create,
+ '$label_name' => t('Channel Name'),
+ '$help_name' => t('Enter your name'),
+ '$label_nick' => t('Choose a short nickname'),
+ '$nick_desc' => t('Your nickname will be used to create an easily remembered channel address (like an email address) which you can share with others.'),
+ '$name' => $name,
+ '$help_role' => t('Please choose a channel type (such as social networking or community forum) and privacy requirements so we can select the best permissions for you'),
+ '$role' => array('permissions_role' , t('Channel Type'), ($privacy_role) ? $privacy_role : 'social', '<a href="help/roles" target="_blank">'.t('Read more about roles').'</a>',get_roles()),
+ '$default_role' => $default_role,
+ '$nickname' => $nickname,
+ '$submit' => t('Create'),
'$label_email' => t('Your email address'),
'$label_pass1' => t('Choose a password'),
'$label_pass2' => t('Please re-enter your password'),
diff --git a/mod/regmod.php b/mod/regmod.php
index c0a75ef48..a1d300e56 100644
--- a/mod/regmod.php
+++ b/mod/regmod.php
@@ -25,10 +25,10 @@ function regmod_content(&$a) {
$hash = argv(2);
if($cmd === 'deny') {
- if (!user_deny($hash)) killme();
+ if (! account_deny($hash)) killme();
}
if($cmd === 'allow') {
- if (!user_allow($hash)) killme();
+ if (! account_allow($hash)) killme();
}
}
diff --git a/mod/regver.php b/mod/regver.php
index c3ade2ee1..78f146ec5 100644
--- a/mod/regver.php
+++ b/mod/regver.php
@@ -13,10 +13,10 @@ function regver_content(&$a) {
$hash = argv(2);
if($cmd === 'deny') {
- if (!user_deny($hash)) killme();
+ if (! account_deny($hash)) killme();
}
if($cmd === 'allow') {
- if (!user_approve($hash)) killme();
+ if (! account_approve($hash)) killme();
}
}
diff --git a/mod/share.php b/mod/share.php
index 7ed6cf9a6..198a6b210 100644
--- a/mod/share.php
+++ b/mod/share.php
@@ -45,7 +45,7 @@ function share_init(&$a) {
$is_photo = (($r[0]['obj_type'] === ACTIVITY_OBJ_PHOTO) ? true : false);
if($is_photo) {
$object = json_decode($r[0]['object'],true);
- $photo_bb = $object['bbcode'];
+ $photo_bb = $object['body'];
}
if (strpos($r[0]['body'], "[/share]") !== false) {
diff --git a/util/addons b/util/addons
new file mode 100755
index 000000000..2c128c50e
--- /dev/null
+++ b/util/addons
@@ -0,0 +1,132 @@
+#!/usr/bin/env php
+<?php
+
+// Hubzilla plugin management utility
+
+function usage() {
+echo <<< EOT
+ Usage:
+ util/addons list # list installed addons
+ util/addons list all # list all addons (*)= installed, (!)= disabled due to version compatibility
+ util/addons install foo # install addon named 'foo'
+ util/addons uninstall foo # uninstall addon named 'foo'
+
+EOT;
+}
+
+require_once('include/cli_startup.php');
+
+cli_startup();
+$a = get_app();
+
+ $plugs = get_config('system', 'addon');
+ $plugins_arr = array();
+
+ if($plugs)
+ $plugins_arr = explode(',', str_replace(' ', '', $plugs));
+
+ $a->plugins = $plugins_arr;
+
+ $plugins = array();
+ $files = glob('addon/*/');
+ if($files) {
+ foreach($files as $file) {
+ if(is_dir($file)){
+ list($tmp, $id) = array_map('trim', explode('/', $file));
+ $info = get_plugin_info($id);
+ $enabled = in_array($id,$a->plugins);
+ $x = check_plugin_versions($info);
+ if($enabled && ! $x) {
+ $enabled = false;
+ $idz = array_search($id, $a->plugins);
+ if ($idz !== false) {
+ unset($a->plugins[$idz]);
+ uninstall_plugin($id);
+ set_config("system","addon", implode(", ",$a->plugins));
+ }
+ }
+ $info['disabled'] = 1-intval($x);
+
+ $plugins[] = array( $id, (($enabled)? '*' : '') , $info);
+ }
+ }
+ }
+
+if($argc == 1) {
+ usage();
+ killme();
+}
+
+
+if($argc == 2 && $argv[1] === 'list') {
+ if($plugins) {
+ foreach($plugins as $p) {
+ if($p[1]) {
+ echo $p[0] . "\n";
+ }
+ }
+ }
+ killme();
+}
+
+if($argc == 3 && $argv[1] === 'list' && $argv[2] === 'all') {
+
+ if($plugins) {
+ foreach($plugins as $p) {
+ echo $p[0] . (($p[1]) ? $p[1] : (($p[2]['disabled']) ? '!' : '')) . "\n";
+ }
+ }
+
+ killme();
+}
+
+
+if($argc == 3 && $argv[1] === 'install') {
+
+ if($plugins) {
+ foreach($plugins as $p) {
+ if($p[0] === $argv[2]) {
+ if($p[1])
+ echo $p[0] . ' already installed.' . "\n";
+ elseif($p[2]['disabled'])
+ echo $p[0] . ' disabled (version compatibility).' . "\n";
+ else {
+ $a->plugins[] = $p[0];
+ install_plugin($p[0]);
+ set_config("system","addon", implode(", ",$a->plugins));
+ echo $p[0] . ' installed.' . "\n";
+ }
+ }
+ }
+ }
+
+ killme();
+}
+
+
+
+if($argc == 3 && $argv[1] === 'uninstall') {
+
+ if($plugins) {
+ foreach($plugins as $p) {
+ if($p[0] === $argv[2]) {
+ if(! $p[1])
+ echo $p[0] . ' not installed.' . "\n";
+ elseif($p[2]['disabled'])
+ echo $p[0] . ' disabled (version compatibility).' . "\n";
+ else {
+ $idx = array_search($p[0], $a->plugins);
+ if ($idx !== false)
+ unset($a->plugins[$idx]);
+ uninstall_plugin($p[0]);
+ set_config("system","addon", implode(", ",$a->plugins));
+ echo $p[0] . ' uninstalled.' . "\n";
+ }
+ }
+ }
+ }
+
+ killme();
+}
+
+
diff --git a/util/hz b/util/hz
new file mode 100755
index 000000000..baa5bfb55
--- /dev/null
+++ b/util/hz
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Simple, minimalist command line tool to post status to hubzilla via the API. Requires curl.
+# Put it in your path, and sneeze your statuses to the zot network from your shell.
+
+CONF=${HOME}/.hubzilla
+
+usage () {
+echo "usage: hz [conffile]"
+echo "Create a conf file, either in .hubzilla in your home directory, or supplied as an arg"
+echo " USER=youruserame "
+echo " PASS=yourpass"
+echo " HUB=your.hub.domain.org"
+echo
+echo "Type \"hz\" (with or without a conf file as an arg), then enter your message. Hit ENTER to send."
+
+}
+
+CUR=`which curl`
+
+[ "$CUR" ] || { echo "curl is not installed or on your path"; usage; exit 1; }
+
+[ "$1" ] && CONF="$1"
+
+
+. ${CONF}
+
+[ "$USER" ] || { echo "no USER"; usage; exit 1; }
+[ "$PASS" ] || { echo "no PASS"; usage; exit 1; }
+[ "$HUB" ] || { echo "no HUB"; usage; exit 1; }
+
+echo "enter your message to be posted as $USER @ $HUB, then hit ENTER to send:"
+
+(read MSG; curl -ssl -u${USER}:${PASS} --data-urlencode "status=${MSG}" https://${HUB}/api/statuses/update )
+
+
diff --git a/version.inc b/version.inc
index 3641bf5e9..a2d8d6da6 100644
--- a/version.inc
+++ b/version.inc
@@ -1 +1 @@
-2016-01-10.1274H
+2016-01-13.1277H
diff --git a/view/css/mod_mail.css b/view/css/mod_mail.css
index 843d1274c..c1874edac 100644
--- a/view/css/mod_mail.css
+++ b/view/css/mod_mail.css
@@ -26,7 +26,7 @@
}
#prvmail-text {
- height: 20.0em;
+ height: 15.0em;
}
.mail-conv-outside-wrapper {
diff --git a/view/css/mod_register.css b/view/css/mod_register.css
index 618b7ce95..890a3f76b 100644
--- a/view/css/mod_register.css
+++ b/view/css/mod_register.css
@@ -42,3 +42,40 @@ h2 {
margin-bottom: 20px;
}
+#newchannel-form {
+ font-size: 1.4em;
+ margin-left: 15%;
+ margin-top: 20px;
+ width: 50%;
+}
+
+#newchannel-form .descriptive-paragraph {
+ color: #888;
+ margin-left: 20px;
+ margin-bottom: 25px;
+}
+
+.newchannel-label {
+ float: left;
+ width: 275px;
+}
+
+.newchannel-role-morehelp {
+ float: left;
+ width: 32px;
+}
+.newchannel-input {
+ float: left;
+ width: 275px;
+ padding: 5px;
+}
+
+.newchannel-feedback {
+ float: left;
+ margin-left: 5px;
+}
+
+.newchannel-field-end {
+ clear: both;
+ margin-bottom: 20px;
+}
diff --git a/view/js/mod_register.js b/view/js/mod_register.js
index 95bc7bbbb..8430b4655 100644
--- a/view/js/mod_register.js
+++ b/view/js/mod_register.js
@@ -26,4 +26,25 @@ $(document).ready(function() {
zFormError("#register-password2-feedback", false);
}
});
+
+
+ $("#newchannel-name").blur(function() {
+ $("#name-spinner").spin('small');
+ var zreg_name = $("#newchannel-name").val();
+ $.get("new_channel/autofill.json?f=&name=" + encodeURIComponent(zreg_name),function(data) {
+ $("#newchannel-nickname").val(data);
+ zFormError("#newchannel-name-feedback",data.error);
+ $("#name-spinner").spin(false);
+ });
+ });
+ $("#newchannel-nickname").blur(function() {
+ $("#nick-spinner").spin('small');
+ var zreg_nick = $("#newchannel-nickname").val();
+ $.get("new_channel/checkaddr.json?f=&nick=" + encodeURIComponent(zreg_nick),function(data) {
+ $("#newchannel-nickname").val(data);
+ zFormError("#newchannel-nickname-feedback",data.error);
+ $("#nick-spinner").spin(false);
+ });
+ });
+
}); \ No newline at end of file
diff --git a/view/tpl/admin_plugins.tpl b/view/tpl/admin_plugins.tpl
index 0f76cc4fe..0da214c17 100755
--- a/view/tpl/admin_plugins.tpl
+++ b/view/tpl/admin_plugins.tpl
@@ -4,8 +4,12 @@
<ul id='pluginslist'>
{{foreach $plugins as $p}}
<li class='plugin {{$p.1}}'>
+ {{if ! $p.2.disabled}}
<a class='toggleplugin' href='{{$baseurl}}/admin/{{$function}}/{{$p.0}}?a=t&amp;t={{$form_security_token}}' title="{{if $p.1==on}}Disable{{else}}Enable{{/if}}" ><i class='{{if $p.1==on}}icon-check{{else}}icon-check-empty{{/if}} admin-icons'></i></a>
- <a href='{{$baseurl}}/admin/{{$function}}/{{$p.0}}'><span class='name'>{{$p.2.name}}</span></a> - <span class="version">{{$p.2.version}}</span>
+ {{else}}
+ <i class='icon-stop admin-icons'></i>
+ {{/if}}
+ <a href='{{$baseurl}}/admin/{{$function}}/{{$p.0}}'><span class='name'>{{$p.2.name}}</span></a> - <span class="version">{{$p.2.version}}</span>{{if $p.2.disabled}} {{$disabled}}{{/if}}
{{if $p.2.experimental}} {{$experimental}} {{/if}}{{if $p.2.unsupported}} {{$unsupported}} {{/if}}
<div class='desc'>{{$p.2.description}}</div>
diff --git a/view/tpl/admin_plugins_details.tpl b/view/tpl/admin_plugins_details.tpl
index 6225ae7bf..721bd3573 100755
--- a/view/tpl/admin_plugins_details.tpl
+++ b/view/tpl/admin_plugins_details.tpl
@@ -1,7 +1,12 @@
<div class = "generic-content-wrapper-styled" id='adminpage'>
<h1>{{$title}} - {{$page}}</h1>
-
- <p><i class='toggleplugin {{if $status==on}}icon-check{{else}}icon-check-empty{{/if}} admin-icons'></i> {{$info.name}} - {{$info.version}} : <a href="{{$baseurl}}/admin/{{$function}}/{{$plugin}}/?a=t&amp;t={{$form_security_token}}">{{$action}}</a></p>
+
+ <p>{{if ! $info.disabled}}<i class='toggleplugin {{if $status==on}}icon-check{{else}}icon-check-empty{{/if}} admin-icons'></i>{{else}}<i class='icon-stop admin-icons'></i>{{/if}} {{$info.name}} - {{$info.version}}{{if ! $info.disabled}} : <a href="{{$baseurl}}/admin/{{$function}}/{{$plugin}}/?a=t&amp;t={{$form_security_token}}">{{$action}}</a>{{/if}}</p>
+
+ {{if $info.disabled}}
+ <p>{{$disabled}}</p>
+ {{/if}}
+
<p>{{$info.description}}</p>
{{foreach $info.author as $a}}
@@ -10,6 +15,16 @@
</p>
{{/foreach}}
+ {{if $info.minversion}}
+ <p class="versionlimit">{{$str_minversion}}{{$info.minversion}}</p>
+ {{/if}}
+ {{if $info.maxversion}}
+ <p class="versionlimit">{{$str_maxversion}}{{$info.maxversion}}</p>
+ {{/if}}
+ {{if $info.minphpversion}}
+ <p class="versionlimit">{{$str_minphpversion}}{{$info.minphpversion}}</p>
+ {{/if}}
+
{{foreach $info.maintainer as $a}}
<p class="maintainer">{{$str_maintainer}}
diff --git a/view/tpl/cover_photo.tpl b/view/tpl/cover_photo.tpl
new file mode 100755
index 000000000..1db139e7b
--- /dev/null
+++ b/view/tpl/cover_photo.tpl
@@ -0,0 +1,23 @@
+<div class="generic-content-wrapper-styled">
+<h1>{{$title}}</h1>
+
+<form enctype="multipart/form-data" action="cover_photo" method="post">
+<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
+
+<div id="profile-photo-upload-wrapper">
+
+<label id="profile-photo-upload-label" class="form-label" for="profile-photo-upload">{{$lbl_upfile}}</label>
+<input name="userfile" class="form-input" type="file" id="profile-photo-upload" size="48" />
+<div class="clear"></div>
+
+<div id="profile-photo-submit-wrapper">
+<input type="submit" name="submit" id="profile-photo-submit" value="{{$submit}}">
+</div>
+</div>
+
+</form>
+
+<div id="profile-photo-link-select-wrapper">
+{{$select}}
+</div>
+</div>
diff --git a/view/tpl/cropcover.tpl b/view/tpl/cropcover.tpl
new file mode 100755
index 000000000..68c948889
--- /dev/null
+++ b/view/tpl/cropcover.tpl
@@ -0,0 +1,58 @@
+<h1>{{$title}}</h1>
+<p id="cropimage-desc">
+{{$desc}}
+</p>
+<div id="cropimage-wrapper">
+<img src="{{$image_url}}" id="croppa" class="imgCrop" alt="{{$title}}" />
+</div>
+<div id="cropimage-preview-wrapper" >
+<div id="previewWrap" ></div>
+</div>
+
+<script type="text/javascript" language="javascript">
+
+ function onEndCrop( coords, dimensions ) {
+ $( 'x1' ).value = coords.x1;
+ $( 'y1' ).value = coords.y1;
+ $( 'x2' ).value = coords.x2;
+ $( 'y2' ).value = coords.y2;
+ $( 'width' ).value = dimensions.width;
+ $( 'height' ).value = dimensions.height;
+ }
+
+ Event.observe( window, 'load', function() {
+ new Cropper.ImgWithPreview(
+ 'croppa',
+ {
+ previewWrap: 'previewWrap',
+ minWidth: 240,
+ minHeight: 87,
+ maxWidth: 320,
+ maxHeight: 320,
+ ratioDim: { x: 100, y:36 },
+ displayOnInit: true,
+ onEndCrop: onEndCrop
+ }
+ );
+ }
+ );
+
+</script>
+
+<form action="cover_photo/{{$resource}}" id="crop-image-form" method="post" />
+<input type='hidden' name='form_security_token' value='{{$form_security_token}}'>
+
+<input type='hidden' name='profile' value='{{$profile}}'>
+<input type="hidden" name="cropfinal" value="1" />
+<input type="hidden" name="xstart" id="x1" />
+<input type="hidden" name="ystart" id="y1" />
+<input type="hidden" name="xfinal" id="x2" />
+<input type="hidden" name="yfinal" id="y2" />
+<input type="hidden" name="height" id="height" />
+<input type="hidden" name="width" id="width" />
+
+<div id="crop-image-submit-wrapper" >
+<input type="submit" name="submit" value="{{$done}}" />
+</div>
+
+</form>
diff --git a/view/tpl/register.tpl b/view/tpl/register.tpl
index 005b122cf..b72e069c3 100755
--- a/view/tpl/register.tpl
+++ b/view/tpl/register.tpl
@@ -22,6 +22,30 @@
<div id="register-invite-end" class="register-field-end"></div>
{{/if}}
+ {{if $auto_create}}
+
+ {{if $default_role}}
+ <input type="hidden" name="permissions_role" value="{{$default_role}}" />
+ {{else}}
+ <div id="newchannel-role-help" class="descriptive-paragraph">{{$help_role}}</div>
+ {{include file="field_select_grouped.tpl" field=$role}}
+ <div id="newchannel-role-end" class="newchannel-field-end"></div>
+ {{/if}}
+
+ <div id="newchannel-name-help" class="descriptive-paragraph">{{$help_name}}</div>
+
+ <label for="newchannel-name" id="label-newchannel-name" class="register-label" >{{$label_name}}</label>
+ <input type="text" name="name" id="newchannel-name" class="register-input" value="{{$name}}" />
+ <div id="name-spinner"></div>
+ <div id="newchannel-name-feedback" class="register-feedback"></div>
+ <div id="newchannel-name-end" class="register-field-end"></div>
+
+
+ {{/if}}
+
+
+
+
<label for="register-email" id="label-register-email" class="register-label" >{{$label_email}}</label>
<input type="text" maxlength="72" size="32" name="email" id="register-email" class="register-input" value="{{$email}}" />
<div id="register-email-feedback" class="register-feedback"></div>
@@ -37,6 +61,16 @@
<div id="register-password2-feedback" class="register-feedback"></div>
<div id="register-password2-end" class="register-field-end"></div>
+ {{if $auto_create}}
+ <div id="newchannel-nick-desc" class="descriptive-paragraph">{{$nick_desc}}</div>
+ <label for="newchannel-nickname" id="label-newchannel-nickname" class="register-label" >{{$label_nick}}</label>
+ <input type="text" name="nickname" id="newchannel-nickname" class="register-input" value="{{$nickname}}" />
+ <div id="nick-spinner"></div>
+ <div id="newchannel-nickname-feedback" class="register-feedback"></div>
+ <div id="newchannel-nickname-end" class="register-field-end"></div>
+
+ {{/if}}
+
{{if $enable_tos}}
<input type="checkbox" name="tos" id="register-tos" value="1" />
<label for="register-tos" id="label-register-tos">{{$label_tos}}</label>