Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Haakon Meland Eriksen 2016-01-14 18:14:30 +01:00
commit 72353bf044
39 changed files with 10054 additions and 9166 deletions

View file

@ -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)

View file

@ -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 );

View file

@ -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;

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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.

View file

@ -170,8 +170,8 @@ function widget_follow($args) {
}
return replace_macros(get_markup_template('follow.tpl'),array(
'$connect' => t('Add New Connection'),
'$desc' => t('Enter the channel address'),
'$hint' => t('Example: bob@example.com, http://example.com/barbara'),
'$desc' => t('Enter channel address'),
'$hint' => t('Examples: bob@example.com, https://example.com/barbara'),
'$follow' => t('Connect'),
'$abook_usage_message' => $abook_usage_message
));

View file

@ -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'];
}

View file

@ -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'.

View file

@ -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'),
));
}

View file

@ -121,53 +121,60 @@ function connections_content(&$a) {
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
$tabs = array(
/*
array(
'label' => t('Suggestions'),
'url' => z_root() . '/suggest',
'sel' => '',
'title' => t('Suggest new connections'),
),
array(
*/
'pending' => array(
'label' => t('New Connections'),
'url' => z_root() . '/connections/pending',
'sel' => ($pending) ? 'active' : '',
'title' => t('Show pending (new) connections'),
),
array(
'all' => array(
'label' => t('All Connections'),
'url' => z_root() . '/connections/all',
'sel' => ($all) ? 'active' : '',
'title' => t('Show all connections'),
),
/*
array(
'label' => t('Unblocked'),
'url' => z_root() . '/connections',
'sel' => (($unblocked) && (! $search) && (! $nets)) ? 'active' : '',
'title' => t('Only show unblocked connections'),
),
*/
array(
'blocked' => array(
'label' => t('Blocked'),
'url' => z_root() . '/connections/blocked',
'sel' => ($blocked) ? 'active' : '',
'title' => t('Only show blocked connections'),
),
array(
'ignored' => array(
'label' => t('Ignored'),
'url' => z_root() . '/connections/ignored',
'sel' => ($ignored) ? 'active' : '',
'title' => t('Only show ignored connections'),
),
array(
'archived' => array(
'label' => t('Archived'),
'url' => z_root() . '/connections/archived',
'sel' => ($archived) ? 'active' : '',
'title' => t('Only show archived connections'),
),
array(
'hidden' => array(
'label' => t('Hidden'),
'url' => z_root() . '/connections/hidden',
'sel' => ($hidden) ? 'active' : '',
@ -184,8 +191,8 @@ function connections_content(&$a) {
);
$tab_tpl = get_markup_template('common_tabs.tpl');
$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
//$tab_tpl = get_markup_template('common_tabs.tpl');
//$t = replace_macros($tab_tpl, array('$tabs'=>$tabs));
$searching = false;
if($search) {
@ -224,6 +231,7 @@ function connections_content(&$a) {
$contacts[] = array(
'img_hover' => sprintf( t('%1$s [%2$s]'),$rr['xchan_name'],$rr['xchan_url']),
'edit_hover' => t('Edit connection'),
'delete_hover' => t('Delete connection'),
'id' => $rr['abook_id'],
'alt_text' => $alt_text,
'dir_icon' => $dir_icon,
@ -232,7 +240,9 @@ function connections_content(&$a) {
'username' => $rr['xchan_name'],
'classes' => (intval($rr['abook_archived']) ? 'archived' : ''),
'link' => z_root() . '/connedit/' . $rr['abook_id'],
'deletelink' => z_root() . '/connedit/' . $rr['abook_id'] . '/drop',
'edit' => t('Edit'),
'delete' => t('Delete'),
'url' => chanlink_url($rr['xchan_url']),
'network' => network_to_name($rr['network']),
);
@ -257,12 +267,13 @@ function connections_content(&$a) {
else {
$o .= "<script> var page_query = '" . $_GET['q'] . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
$o .= replace_macros(get_markup_template('connections.tpl'),array(
'$header' => t('Connections') . (($head) ? ' - ' . $head : ''),
'$tabs' => $t,
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
'$tabs' => $tabs,
'$total' => $total,
'$search' => $search_hdr,
'$label' => t('Search'),
'$desc' => t('Search your connections'),
'$finding' => (($searching) ? t('Finding: ') . "'" . $search . "'" : ""),
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
'$submit' => t('Find'),
'$edit' => t('Edit'),
'$cmd' => $a->cmd,

391
mod/cover_photo.php Normal file
View file

@ -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;
}

View file

@ -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();
}

View file

@ -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);
if(! strlen($next_page = get_config('system','workflow_register_next')))
$next_page = 'new_channel';
$_SESSION['workflow'] = 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';
$_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'),

View file

@ -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();
}
}

View file

@ -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();
}
}

View file

@ -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) {

132
util/addons Executable file
View file

@ -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();
}

36
util/hz Executable file
View file

@ -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 )

View file

@ -1 +1 @@
2016-01-10.1274H
2016-01-13.1277H

View file

@ -1,151 +1,18 @@
.search-input {
padding: 4px 12px;
margin: 3px;
#contacts-search-form {
display: none;
}
.field_abook_help {
color: #000;
}
.abook-them {
margin-left: 375px;
margin-bottom: 15px;
}
.abook-me {
margin-left: 36px;
margin-bottom: 15px;
}
.acheckbox {
margin-bottom: 5px !important;
.section-subtitle-wrapper .btn-xs {
margin-top: -2px;
}
.abook-pending-contact {
background: orange;
font-weight: bold;
margin: 10px;
padding: 20px 5px 10px;
.contact-search {
height: 22px;
border-top-right-radius: 0px;
border-bottom-right-radius: 0px;
}
#contact-slider {
width: 600px !important;
}
.abook-edit-them, .abook-edit-me {
float: left;
width: 100px !important;
}
.field_abook_help {
float: left;
}
#contacts-main {
margin-top: 20px;
margin-bottom: 20px;
}
#contact-edit-wrapper {
margin-top: 10px;
}
#contact-edit-banner-name {
font-size: 1.4em;
font-weight: bold;
}
#contact-edit-poll-wrapper {
margin-top: 15px;
}
#contact-edit-poll-text {
margin-top: 15px;
margin-bottom: 5px;
}
#contact-edit-update-now {
margin-top: 15px;
}
#contact-edit-links{
clear: both;
}
#contact-edit-links ul {
list-style: none;
list-style-type: none;
margin-left: 0px;
padding-left: 0px;
}
#contact-edit-links li {
margin-top: 5px;
}
#contact-edit-drop-link {
float: right;
margin-right: 20px;
}
#contact-edit-nav-end {
clear: both;
}
#contact-edit-wrapper {
width: 100%;
}
#contact-edit-end {
clear: both;
margin-top: 15px;
}
#contact-profile-selector {
width: 175px;
margin-left: 175px;
}
.contact-edit-submit {
margin-top: 20px;
}
.contact-entry-wrapper {
float: left;
width: auto;
height: auto;
padding: 10px;
margin: 8px 10px 0 0;
border-top: 1px solid #eee;
border-left: 2px solid #eee;
}
#contacts-search {
font-size: 1em;
width: 300px;
}
#contacts-search-end {
margin-bottom: 10px;
}
.contact-entry-photo-end {
clear: both;
}
.contact-entry-name {
float: left;
margin-left: 0px;
margin-right: 10px;
margin-bottom: 10px;
width: 147px;
height: auto;
overflow: hidden;
white-space: nowrap;
}
.contact-entry-name-end {
clear:both;
}
.contact-entry-end {
clear: both;
.directory-photo-img.archived {
opacity: 0.3;
filter:alpha(opacity=30);
}

View file

@ -26,7 +26,7 @@
}
#prvmail-text {
height: 20.0em;
height: 15.0em;
}
.mail-conv-outside-wrapper {

View file

@ -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;
}

View file

@ -23,17 +23,6 @@
margin-top: 10px;
}
/* follow */
#side-follow-url {
margin-top: 5px;
width: 100%;
}
#side-follow-submit {
margin-top: 15px;
}
/* notes */
#note-text {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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);
});
});
});

View file

@ -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>

View file

@ -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}}

View file

@ -1,10 +1,15 @@
<div class="contact-entry-wrapper" id="contact-entry-wrapper-{{$contact.id}}" >
<div class="contact-entry-photo-wrapper" >
<a href="{{$contact.url}}" title="{{$contact.img_hover}}" ><img class="contact-block-img {{if $contact.classes}}{{$contact.classes}}{{/if}}" src="{{$contact.thumb}}" alt="{{$contact.name}}" /></a>
<div id="contact-entry-wrapper-{{$contact.id}}">
<div class="section-subtitle-wrapper">
<div class="pull-right">
<a href="#" class="btn btn-danger btn-xs" title="{{$contact.delete_hover}}" onclick="dropItem('{{$contact.deletelink}}', '#contact-entry-wrapper-{{$contact.id}}'); return false;"><i class="icon-trash"></i> {{$contact.delete}}</a>
<a href="{{$contact.link}}" class="btn btn-success btn-xs" title="{{$contact.edit_hover}}"><i class="icon-pencil"></i> {{$contact.edit}}</a>
</div>
<h3><a href="{{$contact.url}}" title="{{$contact.img_hover}}" >{{$contact.name}}</a></h3>
</div>
<div class="section-content-tools-wrapper">
<div class="contact-entry-photo-wrapper" >
<a href="{{$contact.url}}" title="{{$contact.img_hover}}" ><img class="directory-photo-img {{if $contact.classes}}{{$contact.classes}}{{/if}}" src="{{$contact.thumb}}" alt="{{$contact.name}}" /></a>
</div>
</div>
<div class="contact-entry-photo-end" ></div>
<a href="{{$contact.url}}" title="{{$contact.img_hover}}" ><div class="contact-entry-name" id="contact-entry-name-{{$contact.id}}" >{{$contact.name}}</div></a>
<div class="contact-entry-name-end" ></div>
<div class="contact-entry-edit btn btn-default"><a href="{{$contact.link}}"><i class="icon-pencil connection-edit-icons"></i> {{$contact.edit}}</a></div>
<div class="contact-entry-end" ></div>
</div>

View file

@ -1,27 +1,38 @@
<div class="generic-content-wrapper-styled">
<h1>{{$header}}{{if $total}} ({{$total}}){{/if}}</h1>
{{if $finding}}<h4>{{$finding}}</h4>{{/if}}
<div id="contacts-search-wrapper">
<form id="contacts-search-form" action="{{$cmd}}" method="get" >
<span class="contacts-search-desc">{{$desc}}</span>
<input type="text" name="search" id="contacts-search" class="search-input" onfocus="this.select();" value="{{$search}}" />
<input type="submit" name="submit" id="contacts-search-submit" class="btn btn-default" value="{{$submit}}" />
</form>
</div>
<div id="contacts-search-end"></div>
{{$tabs}}
<div id="connections-wrapper">
{{foreach $contacts as $contact}}
{{include file="connection_template.tpl"}}
{{/foreach}}
<div id="page-end"></div>
</div>
<div id="contact-edit-end"></div>
<div class="generic-content-wrapper">
<div class="section-title-wrapper">
<div class="dropdown pull-right">
<button type="button" class="btn btn-primary btn-xs" onclick="openClose('contacts-search-form');">
<i class="icon-search"></i>&nbsp;{{$label}}
</button>
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="{{$sort}}">
<i class="icon-sort"></i>
</button>
<ul class="dropdown-menu">
{{foreach $tabs as $menu}}
<li><a href="{{$menu.url}}">{{$menu.label}}</a></li>
{{/foreach}}
</ul>
</div>
{{if $finding}}<h2>{{$finding}}</h2>{{else}}<h2>{{$header}}{{if $total}} ({{$total}}){{/if}}</h2>{{/if}}
</div>
<div id="contacts-search-form" class="section-content-tools-wrapper">
<form action="{{$cmd}}" method="get" >
<div class="form-group">
<div class="input-group">
<input type="text" name="search" id="contacts-search" class="widget-input" onfocus="this.select();" value="{{$search}}" placeholder="{{$desc}}" />
<div class="input-group-btn">
<button id="contacts-search-submit" class="btn btn-default btn-sm" type="submit" name="submit" value="{{$submit}}"><i class="icon-search"></i></button>
</div>
</div>
</div>
</form>
</div>
<div id="connections-wrapper">
{{foreach $contacts as $contact}}
{{include file="connection_template.tpl"}}
{{/foreach}}
<div id="page-end"></div>
</div>
</div>
<script>$(document).ready(function() { loadingPage = false;});</script>
<div id="page-spinner"></div>

23
view/tpl/cover_photo.tpl Executable file
View file

@ -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>

58
view/tpl/cropcover.tpl Executable file
View file

@ -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>

View file

@ -1,9 +1,14 @@
<div id="follow-sidebar" class="widget">
<h3>{{$connect}}</h3>
<div id="connect-desc">{{$desc}}</div>
<form action="follow" method="post" />
<input id="side-follow-url" type="text" name="url" title="{{$hint}}" />
<input id="side-follow-submit" type="submit" name="submit" class="btn btn-default" value="{{$follow}}" />
<div class="form-group">
<div class="input-group">
<input class="widget-input" type="text" name="url" title="{{$hint}}" placeholder="{{$desc}}" />
<div class="input-group-btn">
<button class="btn btn-default btn-sm" type="submit" name="submit" value="{{$follow}}"><i class="icon-plus"></i></button>
</div>
</div>
</div>
</form>
{{if $abook_usage_message}}
<div class="usage-message" id="abook-usage-message">{{$abook_usage_message}}</div>

View file

@ -5,7 +5,7 @@
<div class="form-group">
<div class="input-group">
<input class="widget-input" type="text" name="search" title="{{$hint}}{{if $advanced_search}}{{$advanced_hint}}{{/if}}" placeholder="{{$desc}}" />
<div class="input-group-btn">
<div class="input-group-btn">
<button class="btn btn-default btn-sm" type="submit" name="submit"><i class="icon-search"></i></button>
</div>
</div>

View file

@ -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>