diff options
author | zotlabs <mike@macgirvin.com> | 2018-01-08 14:50:58 -0800 |
---|---|---|
committer | zotlabs <mike@macgirvin.com> | 2018-01-08 14:50:58 -0800 |
commit | 75804d7ce57a476c85a486c807ea1f5a75235a0e (patch) | |
tree | 13794288d5ffca739248d9ec017ef1a4cef9b93d | |
parent | d4af870bb6500747790e6f196afeb4d75011185d (diff) | |
parent | 0600817ef75d19d1ec91ba822f8a6938d442824e (diff) | |
download | volse-hubzilla-75804d7ce57a476c85a486c807ea1f5a75235a0e.tar.gz volse-hubzilla-75804d7ce57a476c85a486c807ea1f5a75235a0e.tar.bz2 volse-hubzilla-75804d7ce57a476c85a486c807ea1f5a75235a0e.zip |
Merge branch 'dev' of https://github.com/redmatrix/hubzilla into dev_merge
34 files changed, 338 insertions, 192 deletions
diff --git a/.homeinstall/README.md b/.homeinstall/README.md index e78f78fc6..8b23b9c44 100644 --- a/.homeinstall/README.md +++ b/.homeinstall/README.md @@ -28,23 +28,23 @@ Hardware Software -+ Fresh installation of Debian 9 (Stretch) on your mini-pc -+ Router with open ports 80 and 443 for your Debian ++ Fresh installation of Debian 9 (Stretch) ++ Router with open ports 80 and 443 for your Hub ## The basic steps (quick overview) + Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS) -+ Install Debian 9 -+ On your router: Open the ports 80 and 443 + Log on to your fresh Debian - apt-get install git - mkdir -p /var/www - cd /var/www - git clone https://github.com/redmatrix/hubzilla.git html - - cp .homeinstall/hubzilla-config.txt.template .homeinstall/hubzilla-config.txt - - nano .homeinstall/hubzilla-config.txt + - cd /html/.homeinstall + - cp hubzilla-config.txt.template hubzilla-config.txt + - nano hubzilla-config.txt - Read the comments carefully - Enter your values: db pass, domain, values for dyn DNS + - Make sure your external drive (for backups) is mounted - hubzilla-setup.sh as root - ... wait, wait, wait until the script is finised - reboot @@ -58,24 +58,27 @@ Software ### Recommended: USB Drive for Backups -The installation will create a daily backup. - -If the backup process does not find an external device than the backup goes to -the internal disk. +The installation will create a daily backup written to an external drive. The USB drive must be compatible with the filesystems - ext4 (if you do not want to encrypt the USB) - LUKS + ext4 (if you want to encrypt the USB) +The backup includes + +- Hubzilla DB +- Hubzilla installation /var/www/html +- Certificates for letsencrypt + ## Preparations Software ### Install Debian Linux on the Mini-PC -Download the stable Debian 9 at https://www.debian.org/ +Download the stable Debian at https://www.debian.org/ (Debian 8 is no longer supported.) -Create bootable USB drive with Debian on it. You could use +Create bootable USB drive with Debian on it.You could use - unetbootin, https://en.wikipedia.org/wiki/UNetbootin - or simply the linux command "dd" @@ -109,12 +112,9 @@ You can use subdomains as well my.cooldomain.org -There are two ways to get a domain - -- buy a domain, or -- register a free subdomain +There are two ways to get a domain... -### Method 1: Buy an own Domain +### Method 1: Buy a Domain ...for example buy at selfHOST.de @@ -122,14 +122,14 @@ The cost are around 10,- € once and 1,50 € per month (2017). ### Method 2 Register a (free) Subdomain -...for example register at freeDNS +...for example register at freedns.afraid.org Follow the instructions in .homeinstall/hubzilla-config.txt. ## Install Hubzilla on your Debian -Login to your Debian +Login to your debian (Provided your username is "you" and the name of the mini pc is "debian". You could take the IP address instead of "debian") @@ -164,6 +164,8 @@ Modify the file "hubzilla-config.txt". Read the instructions there carefully and nano hubzilla-config.txt +Make sure your external drive (for backups) is plugged in and can be mounted as configured in "hubzilla-config.txt". Otherwise the daily backups will not work. + Run the script ./hubzilla-setup.sh @@ -187,11 +189,16 @@ Leave db type "MySQL" untouched. Follow the instructions in the next pages. -## Note for the Rasperry +After the daily script was executed at 05:30 (am) -The script was tested with a Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img). +- look at var/www/html/hubzilla-daily.log +- check your backup on the external drive +- optionally view the daily log under yourdomain.org/admin/logs/ + - set the logfile to var/www/html/hubzilla-daily.log + +## Note for the Rasperry -Be patient when a page is loaded by your Raspi-Hub for the very first time. Especially the config pages after the install will load very slowly. +The script was tested with an Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img). It is recommended to deinstall these programms to avoid endless updates. Use... @@ -202,8 +209,8 @@ It is recommended to run the Raspi without graphical frontend (X-Server). Use... sudo raspi-config -There choose "3 Boot Options" > "31 Desktop / CLI" > "B1 Console". Reboot. +to boot the Rapsi to the client console. -**DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!** +DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI! diff --git a/.homeinstall/hubzilla-config.txt.template b/.homeinstall/hubzilla-config.txt.template index 089917c68..2776ccd27 100644 --- a/.homeinstall/hubzilla-config.txt.template +++ b/.homeinstall/hubzilla-config.txt.template @@ -13,10 +13,10 @@ db_pass= # This script automates installation of an SSL certificate from # Let's Encrypt (https://letsencrypt.org) # -# Please give the domain name of your hub. Examples: +# Please give the domain name of your hub # -# le_domain=my.cooldomain.org -# le_domain=cooldomain.org +# Example: my.cooldomain.org +# Example: cooldomain.org # # Email is optional # @@ -25,7 +25,7 @@ le_domain= le_email= ############################################### -### OPTIONAL - dynamic IP address - selfHOST ## +### OPTIONAL - selfHOST - dynamic IP address ## # # 1. Register a domain at selfhost.de # - choose offer "DOMAIN dynamisch" 1,50€/mon at 08.01.2016 @@ -42,7 +42,7 @@ selfhost_user= selfhost_pass= ############################################### -### OPTIONAL - dynamic IP address - FreeDNS ### +### OPTIONAL - FreeDNS - dynamic IP address ### # # Please give the alpha-numeric-key of freedns # diff --git a/.homeinstall/hubzilla-setup.sh b/.homeinstall/hubzilla-setup.sh index 023b9eed1..635bb3518 100755 --- a/.homeinstall/hubzilla-setup.sh +++ b/.homeinstall/hubzilla-setup.sh @@ -459,11 +459,6 @@ function configure_cron_selfhost { fi } -function install_git { - print_info "installing git..." - nocheck_install "git" -} - function install_letsencrypt { print_info "installing let's encrypt ..." # check if user gave domain @@ -570,20 +565,13 @@ function check_https { } function install_hubzilla { - print_info "installing hubzilla..." - # rm -R /var/www/html/ # for "stand alone" usage - cd /var/www/ - # git clone https://github.com/redmatrix/hubzilla html # for "stand alone" usage - cd html/ - git clone https://github.com/redmatrix/hubzilla-addons addon + print_info "installing hubzilla addons..." + cd /var/www/html/ + util/add_addon_repo https://github.com/redmatrix/hubzilla-addons.git hzaddons mkdir -p "store/[data]/smarty3" chmod -R 777 store touch .htconfig.php chmod ou+w .htconfig.php - # uncomment the last function call "install_hubzilla_plugins" - # - if you want to install addons and themes that are not officially supported - # - and read the comments in function "install_hubzilla_plugins" how do do it - # install_hubzilla_plugins cd /var/www/ chown -R www-data:www-data html chown root:www-data /var/www/html/ @@ -598,72 +586,6 @@ function install_hubzilla { print_info "installed hubzilla" } -function install_hubzilla_plugins { - print_info "installing hubzilla plugins..." - cd /var/www/html - plugin_install=.homeinstall/plugin_install.txt - theme_install=.homeinstall/theme_install.txt - # overwrite script to update the plugin and themes - rm -f $plugins_update - echo "cd /var/www/html" >> $plugins_update - ################### - # write plugin file - if [ ! -f "$plugin_install" ] - then - echo "# To install a plugin" >> $plugin_install - echo "# 1. add the plugin in a new line and run" >> $plugin_install - echo "# 2. run" >> $plugin_install - echo "# cd /var/www/html/.homeinstall" >> $plugin_install - echo "# ./hubzilla-setup.sh" >> $plugin_install - echo "https://gitlab.com/zot/ownmapp.git ownMapp" >> $plugin_install - fi - # install plugins - while read -r line; do - [[ "$line" =~ ^#.*$ ]] && continue - p_url=$(echo $line | awk -F' ' '{print $1}') - p_name=$(echo $line | awk -F' ' '{print $2}') - # basic check of format - if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ] - then - # install addon - util/add_addon_repo $line - util/update_addon_repo $p_name # not sure if this line is neccessary - echo "util/update_addon_repo $p_name" >> $plugins_update - else - print_info "skipping installation of a plugin from file $plugin_install - something wrong with format in line: $line" - fi - done < "$plugin_install" - ################### - # write theme file - if [ ! -f "$theme_install" ] - then - echo "# To install a theme" >> $theme_install - echo "# 1. add the theme in a new line and run" >> $theme_install - echo "# 2. run" >> $theme_install - echo "# cd /var/www/html/.homeinstall" >> $theme_install - echo "# ./hubzilla-setup.sh" >> $theme_install - echo "https://github.com/DeadSuperHero/hubzilla-themes.git DeadSuperHeroThemes" >> $theme_install - - fi - # install plugins - while read -r line; do - [[ "$line" =~ ^#.*$ ]] && continue - p_url=$(echo $line | awk -F' ' '{print $1}') - p_name=$(echo $line | awk -F' ' '{print $2}') - # basic check of format - if [ ${#p_url} -ge 1 ] && [ ${#p_name} -ge 1 ] - then - # install addon - util/add_theme_repo $line - util/update_theme_repo $p_name # not sure if this line is neccessary - echo "util/update_theme_repo $p_name" >> $plugins_update - else - print_info "skipping installation of a theme from file $theme_install - something wrong with format in line: $line" - fi - done < "$theme_install" - print_info "installed hubzilla plugins and themes" -} - function rewrite_to_https { print_info "configuring apache to redirect http to httpS ..." htaccessfile=/var/www/html/.htaccess @@ -788,12 +710,11 @@ echo " fi" >> /var/www/$hubzilladaily echo "fi" >> /var/www/$hubzilladaily echo "if [ \$device_mounted == 0 ]" >> /var/www/$hubzilladaily echo "then" >> /var/www/$hubzilladaily -echo " echo \"device could not be mounted $backup_device_name. Using internal disk for backup...\"" >> /var/www/$hubzilladaily -echo " rsnapshot -c $snapshotconfig alpha" >> /var/www/$hubzilladaily +echo " echo \"device could not be mounted $backup_device_name. No backup written.\"" >> /var/www/$hubzilladaily echo "fi" >> /var/www/$hubzilladaily echo "#" >> /var/www/$hubzilladaily echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily -echo "du -h /var/cache/rsnapshot/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily +echo "du -h /var/lib/mysql/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily echo "#" >> /var/www/$hubzilladaily echo "# update" >> /var/www/$hubzilladaily echo "echo \"\$(date) - updating dehydrated...\"" >> /var/www/$hubzilladaily @@ -1,4 +1,8 @@ Hubzilla 3.0 (????-??-??) + - Updated homeinstall script + - Sort cloud directory by 1. is_dir and 2. name + - Document that imagick calls/execs ffmpeg for mp4 video thumbnails + - Use pipe_stream() instead of file_{get, put}_contents() in attach_store() - Make homeinstall script ready for Debian 9 - Add url and headings to bbco_autocomplete() - Remove additional linebreaks after headings @@ -82,6 +86,12 @@ Hubzilla 3.0 (????-??-??) - Table structure for pseudo or proxy channels (pchan) Bugfixes + - Fix sync non-default profile photo changes to clones - github issue #113 + - Fix prev/next buttons on connedit can show deleted connections - github issue #673 + - Fix affinity widget settings + - Fix dupe bug in content hooks - github issue #943 + - Fix directory keywords returned from dir_tagadelic() in standalone mode + - Fix argument warning when arguments are correct in util/dcp - Fix issue with long filenames in mod cloud - Fix misc. issues with new 'insert photo from photo album' github issue #475 - Fix regression in channel sources delivery @@ -116,6 +126,10 @@ Hubzilla 3.0 (????-??-??) - Fix unstar Plugins/Addon + Diaspora: fix 'view full size' photo link - core github issue #947 + Diaspora: implement recent changes in diaspora account_migration spec + GNU-Social: fix uploading a photo to a post results in double post - github issue 75 + GNU-Social: fix gnusoc plugin not respecting delayed delivery - github issue 74 Pubcrawl: fix PHP warning Diaspora: remove garbage from magic envelope Diaspora: fix permalinks for zot reshares diff --git a/Zotlabs/Lib/Img_filesize.php b/Zotlabs/Lib/Img_filesize.php new file mode 100644 index 000000000..e7bef37e1 --- /dev/null +++ b/Zotlabs/Lib/Img_filesize.php @@ -0,0 +1,121 @@ +<?php + +namespace Zotlabs\Lib; + +class Img_filesize { + + private $url; + + function __construct($url) { + $this->url = $url; + } + + function getSize() { + $size = null; + + if(stripos($this->url,z_root() . '/photo') !== false) { + $size = self::getLocalFileSize($this->url); + } + if(! $size) { + $size = getRemoteFileSize($this->url); + } + + return $size; + } + + + static function getLocalFileSize($url) { + + $fname = basename($url); + $resolution = 0; + + if(strpos($fname,'.') !== false) + $fname = substr($fname,0,strpos($fname,'.')); + + if(substr($fname,-2,1) == '-') { + $resolution = intval(substr($fname,-1,1)); + $fname = substr($fname,0,-2); + } + + $r = q("SELECT filesize FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", + dbesc($fname), + intval($resolution) + ); + if($r) { + return $r[0]['filesize']; + } + return null; + } + +} + +/** + * Try to determine the size of a remote file by making an HTTP request for + * a byte range, or look for the content-length header in the response. + * The function aborts the transfer as soon as the size is found, or if no + * length headers are returned, it aborts the transfer. + * + * @return int|null null if size could not be determined, or length of content + */ +function getRemoteFileSize($url) +{ + $ch = curl_init($url); + + $headers = array( + 'Range: bytes=0-1', + 'Connection: close', + ); + + $in_headers = true; + $size = null; + + curl_setopt($ch, CURLOPT_HEADER, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2450.0 Iron/46.0.2450.0'); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); + curl_setopt($ch, CURLOPT_VERBOSE, 0); // set to 1 to debug + curl_setopt($ch, CURLOPT_STDERR, fopen('php://output', 'r')); + + curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $line) use (&$in_headers, &$size) { + $length = strlen($line); + + if (trim($line) == '') { + $in_headers = false; + } + + list($header, $content) = explode(':', $line, 2); + $header = strtolower(trim($header)); + + if ($header == 'content-range') { + // found a content-range header + list($rng, $s) = explode('/', $content, 2); + $size = (int)$s; + return 0; // aborts transfer + } else if ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) { + // found content-length header and this is not a 206 Partial Content response (range response) + $size = (int)$content; + return 0; + } else { + // continue + return $length; + } + }); + + curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use ($in_headers) { + if (!$in_headers) { + // shouldn't be here unless we couldn't determine file size + // abort transfer + return 0; + } + + // write function is also called when reading headers + return strlen($data); + }); + + $result = curl_exec($ch); + $info = curl_getinfo($ch); + + return $size; +}
\ No newline at end of file diff --git a/Zotlabs/Module/Apps.php b/Zotlabs/Module/Apps.php index 2f61f2932..c672ea467 100644 --- a/Zotlabs/Module/Apps.php +++ b/Zotlabs/Module/Apps.php @@ -22,7 +22,8 @@ class Apps extends \Zotlabs\Web\Controller { if(local_channel()) { Zlib\Apps::import_system_apps(); $syslist = array(); - $list = Zlib\Apps::app_list(local_channel(), (($mode == 'edit') ? true : false), $_GET['cat']); + $cat = ((array_key_exists('cat',$_GET) && $_GET['cat']) ? [ escape_tags($_GET['cat']) ] : ''); + $list = Zlib\Apps::app_list(local_channel(), (($mode == 'edit') ? true : false), $cat); if($list) { foreach($list as $x) { $syslist[] = Zlib\Apps::app_encode($x); @@ -43,7 +44,7 @@ class Apps extends \Zotlabs\Web\Controller { return replace_macros(get_markup_template('myapps.tpl'), array( '$sitename' => get_config('system','sitename'), - '$cat' => ((array_key_exists('cat',$_GET) && $_GET['cat']) ? escape_tags($_GET['cat']) : ''), + '$cat' => $cat, '$title' => t('Apps'), '$apps' => $apps, '$authed' => ((local_channel()) ? true : false), diff --git a/Zotlabs/Module/Connedit.php b/Zotlabs/Module/Connedit.php index 23c5282e3..e0511b0d3 100644 --- a/Zotlabs/Module/Connedit.php +++ b/Zotlabs/Module/Connedit.php @@ -567,7 +567,7 @@ class Connedit extends \Zotlabs\Web\Controller { $contact_id = \App::$poi['abook_id']; $contact = \App::$poi; - $cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 order by xchan_name", + $cn = q("SELECT abook_id, xchan_name from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d and abook_self = 0 and xchan_deleted = 0 order by xchan_name", intval(local_channel()) ); diff --git a/Zotlabs/Module/Feed.php b/Zotlabs/Module/Feed.php index 06637b6d2..36869abbe 100644 --- a/Zotlabs/Module/Feed.php +++ b/Zotlabs/Module/Feed.php @@ -16,12 +16,15 @@ class Feed extends \Zotlabs\Web\Controller { $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); - $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); - $params['records'] = ((x($params,'records')) ? intval($params['records']) : 40); - $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); + $params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0); + $params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 40); + $params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); $params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 0); + if(! in_array($params['direction'],['asc','desc'])) { + $params['direction'] = 'desc'; + } if(argc() > 1) { diff --git a/Zotlabs/Module/Network.php b/Zotlabs/Module/Network.php index 4deb7c9e8..551303984 100644 --- a/Zotlabs/Module/Network.php +++ b/Zotlabs/Module/Network.php @@ -35,9 +35,12 @@ class Network extends \Zotlabs\Web\Controller { return login(false); } - if($load) + $o = ''; + + if($load) { $_SESSION['loadtime'] = datetime_convert(); - + } + $arr = array('query' => \App::$query_string); call_hooks('network_content_init', $arr); @@ -104,8 +107,10 @@ class Network extends \Zotlabs\Web\Controller { $def_acl = array('allow_gid' => '<' . $r[0]['hash'] . '>'); } - $o = ''; + $default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0); + $default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99); + // if no tabs are selected, defaults to comments @@ -115,8 +120,8 @@ class Network extends \Zotlabs\Web\Controller { $liked = ((x($_GET,'liked')) ? intval($_GET['liked']) : 0); $conv = ((x($_GET,'conv')) ? intval($_GET['conv']) : 0); $spam = ((x($_GET,'spam')) ? intval($_GET['spam']) : 0); - $cmin = ((x($_GET,'cmin')) ? intval($_GET['cmin']) : 0); - $cmax = ((x($_GET,'cmax')) ? intval($_GET['cmax']) : 99); + $cmin = ((array_key_exists('cmin',$_GET)) ? intval($_GET['cmin']) : $default_cmin); + $cmax = ((array_key_exists('cmax',$_GET)) ? intval($_GET['cmax']) : $default_cmax); $file = ((x($_GET,'file')) ? $_GET['file'] : ''); $xchan = ((x($_GET,'xchan')) ? $_GET['xchan'] : ''); $net = ((x($_GET,'net')) ? $_GET['net'] : ''); @@ -404,7 +409,6 @@ class Network extends \Zotlabs\Web\Controller { if($cmax == 99) $sql_nets .= " OR abook.abook_closeness IS NULL ) "; - } $net_query = (($net) ? " left join xchan on xchan_hash = author_xchan " : ''); @@ -473,7 +477,6 @@ class Network extends \Zotlabs\Web\Controller { if($load) { // Fetch a page full of parent items for this page - $r = q("SELECT distinct item.id AS item_id, $ordering FROM item left join abook on ( item.owner_xchan = abook.abook_xchan $abook_uids ) $net_query @@ -484,7 +487,6 @@ class Network extends \Zotlabs\Web\Controller { $net_query2 ORDER BY $ordering DESC $pager_sql " ); - } else { diff --git a/Zotlabs/Module/Ofeed.php b/Zotlabs/Module/Ofeed.php index 58488d4af..d18a43ae5 100644 --- a/Zotlabs/Module/Ofeed.php +++ b/Zotlabs/Module/Ofeed.php @@ -17,12 +17,15 @@ class Ofeed extends \Zotlabs\Web\Controller { $params['type'] = ((stristr(argv(0),'json')) ? 'json' : 'xml'); $params['pages'] = ((x($_REQUEST,'pages')) ? intval($_REQUEST['pages']) : 0); $params['top'] = ((x($_REQUEST,'top')) ? intval($_REQUEST['top']) : 0); - $params['start'] = ((x($params,'start')) ? intval($params['start']) : 0); - $params['records'] = ((x($params,'records')) ? intval($params['records']) : 10); - $params['direction'] = ((x($params,'direction')) ? dbesc($params['direction']) : 'desc'); + $params['start'] = ((x($_REQUEST,'start')) ? intval($_REQUEST['start']) : 0); + $params['records'] = ((x($_REQUEST,'records')) ? intval($_REQUEST['records']) : 10); + $params['direction'] = ((x($_REQUEST,'direction')) ? dbesc($_REQUEST['direction']) : 'desc'); $params['cat'] = ((x($_REQUEST,'cat')) ? escape_tags($_REQUEST['cat']) : ''); $params['compat'] = ((x($_REQUEST,'compat')) ? intval($_REQUEST['compat']) : 1); + if(! in_array($params['direction'],['asc','desc'])) { + $params['direction'] = 'desc'; + } if(argc() > 1) { diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 411518c61..45a606d5f 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -179,7 +179,10 @@ class Profile_photo extends \Zotlabs\Web\Controller { ); } - profiles_build_sync(local_channel()); + // set $send to false in profiles_build_sync() to return the data + // so that we only send one sync packet. + + $sync_profiles = profiles_build_sync(local_channel(),false); // We'll set the updated profile-photo timestamp even if it isn't the default profile, // so that browsers will do a cache update unconditionally @@ -201,7 +204,7 @@ class Profile_photo extends \Zotlabs\Web\Controller { $sync = attach_export_data($channel,$base_image['resource_id']); if($sync) - build_sync_packet($channel['channel_id'],array('file' => array($sync))); + build_sync_packet($channel['channel_id'],array('file' => array($sync), 'profile' => $sync_profiles)); // Similarly, tell the nav bar to bypass the cache and update the avatar image. diff --git a/Zotlabs/Module/Settings/Featured.php b/Zotlabs/Module/Settings/Featured.php index ebe2996d3..9c5a7b16c 100644 --- a/Zotlabs/Module/Settings/Featured.php +++ b/Zotlabs/Module/Settings/Featured.php @@ -11,15 +11,17 @@ class Featured { call_hooks('feature_settings_post', $_POST); if($_POST['affinity_slider-submit']) { - if(intval($_POST['affinity_cmax'])) { - set_pconfig(local_channel(),'affinity','cmax',intval($_POST['affinity_cmax'])); - } - if(intval($_POST['affinity_cmin'])) { - set_pconfig(local_channel(),'affinity','cmin',intval($_POST['affinity_cmin'])); - } - if(intval($_POST['affinity_cmax']) || intval($_POST['affinity_cmin'])) { - info( t('Affinity Slider settings updated.') . EOL); - } + $cmax = intval($_POST['affinity_cmax']); + if($cmax < 0 || $cmax > 99) + $cmax = 99; + $cmin = intval($_POST['affinity_cmin']); + if($cmin < 0 || $cmin > 99) + $cmin = 0; + set_pconfig(local_channel(),'affinity','cmin',$cmin); + set_pconfig(local_channel(),'affinity','cmax',$cmax); + + info( t('Affinity Slider settings updated.') . EOL); + } build_sync_packet(); @@ -40,12 +42,12 @@ class Featured { $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); $cmax = (($cmax) ? $cmax : 99); $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( - '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, '') + '$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99')) )); $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); $cmin = (($cmin) ? $cmin : 0); $setting_fields .= replace_macros(get_markup_template('field_input.tpl'), array( - '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, '') + '$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0')) )); $settings_addons .= replace_macros(get_markup_template('generic_addon_settings.tpl'), array( diff --git a/Zotlabs/Storage/Directory.php b/Zotlabs/Storage/Directory.php index 63ff4341c..510d463c1 100644 --- a/Zotlabs/Storage/Directory.php +++ b/Zotlabs/Storage/Directory.php @@ -691,7 +691,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota, DAV\IMo } $prefix = ''; - $suffix = ''; + $suffix = ' order by is_dir desc, filename asc '; $r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix", dbesc($folder), diff --git a/Zotlabs/Thumbs/Video.php b/Zotlabs/Thumbs/Video.php index 5e09ef9a3..05127355e 100644 --- a/Zotlabs/Thumbs/Video.php +++ b/Zotlabs/Thumbs/Video.php @@ -32,12 +32,24 @@ class Video { fclose($ostream); } + /* + * Note: imagick convert may try to call 'ffmpeg' (or other conversion utilities) under + * the covers for this particular operation. If this is not installed or not in the path + * for the web server user, errors may be reported in the web server logs. + */ + + + $ffmpeg = trim(shell_exec('which ffmpeg')); + if($ffmpeg) { + logger('ffmpeg not found in path. Video thumbnails may fail.'); + } + $imagick_path = get_config('system','imagick_convert_path'); if($imagick_path && @file_exists($imagick_path)) { $cmd = $imagick_path . ' ' . escapeshellarg(PROJECT_BASE . '/' . $tmpfile . '[0]') . ' -thumbnail ' . $width . 'x' . $height . ' ' . escapeshellarg(PROJECT_BASE . '/' . $outfile); // logger('imagick thumbnail command: ' . $cmd); - exec($cmd); + @exec($cmd); if(! file_exists($outfile)) { logger('imagick scale failed.'); @@ -46,7 +58,7 @@ class Video { @rename($outfile,$file . '.thumb'); } } - + @unlink($tmpfile); } } diff --git a/Zotlabs/Web/Router.php b/Zotlabs/Web/Router.php index 12ef315d4..a6b780cdc 100644 --- a/Zotlabs/Web/Router.php +++ b/Zotlabs/Web/Router.php @@ -265,7 +265,7 @@ class Router { if(! \App::$error) { $arr = array('content' => \App::$page['content'], 'replace' => false); call_hooks(\App::$module . '_mod_content', $arr); - \App::$page['content'] = $arr['content']; + if(! $arr['replace']) { if($this->controller && method_exists($this->controller,'get')) { $arr = array('content' => $this->controller->get()); @@ -276,8 +276,8 @@ class Router { } } call_hooks(\App::$module . '_mod_aftercontent', $arr); - \App::$page['content'] .= $arr['content']; + \App::$page['content'] = (($arr['replace']) ? $arr['content'] : \App::$page['content'] . $arr['content']); } } } -}
\ No newline at end of file +} diff --git a/Zotlabs/Widget/Affinity.php b/Zotlabs/Widget/Affinity.php index 439ba1f33..4fb2874ae 100644 --- a/Zotlabs/Widget/Affinity.php +++ b/Zotlabs/Widget/Affinity.php @@ -9,15 +9,11 @@ class Affinity { if(! local_channel()) return ''; - // Get default cmin value from pconfig, but allow GET parameter to override - $cmin = intval(get_pconfig(local_channel(),'affinity','cmin')); - $cmin = (($cmin) ? $cmin : 0); - $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $cmin); - - // Get default cmax value from pconfig, but allow GET parameter to override - $cmax = intval(get_pconfig(local_channel(),'affinity','cmax')); - $cmax = (($cmax) ? $cmax : 99); - $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $cmax); + $default_cmin = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmin',0) : 0); + $default_cmax = ((feature_enabled(local_channel(),'affinity')) ? get_pconfig(local_channel(),'affinity','cmax',99) : 99); + + $cmin = ((x($_REQUEST,'cmin')) ? intval($_REQUEST['cmin']) : $default_cmin); + $cmax = ((x($_REQUEST,'cmax')) ? intval($_REQUEST['cmax']) : $default_cmax); if(feature_enabled(local_channel(),'affinity')) { diff --git a/Zotlabs/Widget/Notifications.php b/Zotlabs/Widget/Notifications.php index a677d84c9..5a0c1f3d5 100644 --- a/Zotlabs/Widget/Notifications.php +++ b/Zotlabs/Widget/Notifications.php @@ -144,6 +144,7 @@ class Notifications { $o = replace_macros(get_markup_template('notifications_widget.tpl'), array( '$module' => \App::$module, '$notifications' => $notifications, + '$no_notifications' => t('Sorry, you have got no notifications at the moment'), '$loading' => t('Loading') )); @@ -50,7 +50,7 @@ require_once('include/hubloc.php'); require_once('include/attach.php'); define ( 'PLATFORM_NAME', 'hubzilla' ); -define ( 'STD_VERSION', '3.1' ); +define ( 'STD_VERSION', '3.1.1' ); define ( 'ZOT_REVISION', '1.3' ); define ( 'DB_UPDATE_VERSION', 1198 ); diff --git a/include/attach.php b/include/attach.php index e94454905..39269eb03 100644 --- a/include/attach.php +++ b/include/attach.php @@ -550,6 +550,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $type = $f['type']; } else { if(! x($_FILES,'userfile')) { + logger('No source file'); $ret['message'] = t('No source file.'); return $ret; } @@ -590,6 +591,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($channel_id) ); if(! $x) { + logger('update file source not found'); $ret['message'] = t('Cannot locate file to revise/update'); return $ret; } @@ -731,6 +733,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $maxfilesize = get_config('system','maxfilesize'); if(($maxfilesize) && ($filesize > $maxfilesize)) { + logger('quota_exceeded'); $ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize); if($remove_when_processed) @unlink($src); @@ -751,6 +754,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { intval($channel['channel_account_id']) ); if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) { + logger('service_class limit exceeded'); $ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."), $limit / 1024000); if($remove_when_processed) @unlink($src); @@ -783,8 +787,15 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) { $os_path = $os_relpath; $display_path = ltrim($pathname . '/' . $filename,'/'); - if($src) - @file_put_contents($os_basepath . $os_relpath,@file_get_contents($src)); + if($src) { + $istream = @fopen($src,'rb'); + $ostream = @fopen($os_basepath . $os_relpath,'wb'); + if($istream && $ostream) { + pipe_streams($istream,$ostream,65535); + fclose($istream); + fclose($ostream); + } + } if(array_key_exists('created', $arr)) $created = $arr['created']; diff --git a/include/channel.php b/include/channel.php index 2d40b7db6..b9adc588b 100644 --- a/include/channel.php +++ b/include/channel.php @@ -1982,12 +1982,17 @@ function get_channel_default_perms($uid) { } -function profiles_build_sync($channel_id) { +function profiles_build_sync($channel_id,$send = true) { $r = q("select * from profile where uid = %d", intval($channel_id) ); if($r) { - build_sync_packet($channel_id,array('profile' => $r)); + if($send) { + build_sync_packet($channel_id,array('profile' => $r)); + } + else { + return $r; + } } } diff --git a/include/feedutils.php b/include/feedutils.php index 4638ef66a..5e48cb1ee 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -1801,12 +1801,17 @@ function compat_photos_list($s) { if($found) { foreach($matches as $match) { - $ret[] = [ + $entry = [ 'href' => $match[2], - 'length' => 0, 'type' => guess_image_type($match[2]) ]; + $sizer = new \Zotlabs\Lib\Img_filesize($match[2]); + $size = $sizer->getSize(); + if(intval($size)) { + $entry['length'] = intval($size); + } + $ret[] = $entry; } } diff --git a/include/import.php b/include/import.php index a5e8adeb5..5a655ce4c 100644 --- a/include/import.php +++ b/include/import.php @@ -162,13 +162,17 @@ function import_profiles($channel, $profiles) { convert_oldfields($profile,'work','employment'); /** - * @TODO we are going to reset all profile photos to the original - * somebody will have to fix this later and put all the applicable - * photos into the export. + * @TODO put all the applicable photos into the export. */ - $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; - $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) { + $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; + $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + } + else { + $profile['photo'] = z_root() . '/photo/' . basename($profile['photo']); + $profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']); + } create_table_from_array('profile', $profile); } @@ -1328,6 +1332,9 @@ function sync_files($channel, $files) { } } } + + \Zotlabs\Daemon\Master::Summon([ 'Thumbnail' , $att['hash'] ]); + if($f['item']) { sync_items($channel,$f['item'], ['channel_address' => $original_channel,'url' => $oldbase] diff --git a/include/items.php b/include/items.php index 722757f87..d0b9cffc9 100755 --- a/include/items.php +++ b/include/items.php @@ -4063,8 +4063,9 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $item_uids = ' true '; $item_normal = item_normal(); - - if ($arr['uid']) $uid= $arr['uid']; + if($arr['uid']) { + $uid = $arr['uid']; + } if($channel) { $uid = $channel['channel_id']; @@ -4226,7 +4227,7 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C $items = q("SELECT item.*, item.id AS item_id FROM item WHERE $item_uids $item_restrict $simple_update - $sql_extra $sql_nets + $sql_extra $sql_nets $sql_extra3 ORDER BY item.received DESC $pager_sql" ); diff --git a/include/network.php b/include/network.php index 3569874be..79a8c6578 100644 --- a/include/network.php +++ b/include/network.php @@ -752,13 +752,14 @@ function scale_external_images($s, $include_link = true, $scale_replace = false) if($orig_width > 1024 || $orig_height > 1024) { $tag = (($match[1] == 'z') ? 'zmg' : 'img'); + $linktag = (($match[1] == 'z') ? 'zrl' : 'url'); $ph->scaleImage(1024); $new_width = $ph->getWidth(); $new_height = $ph->getHeight(); logger('data: ' . $orig_width . '->' . $new_width . 'w ' . $orig_height . '->' . $new_height . 'h' . ' match: ' . $mtch[0], LOGGER_DEBUG); $s = str_replace($mtch[0],'[' . $tag . '=' . $new_width . 'x' . $new_height. ']' . $scaled . '[/' . $tag . ']' . "\n" . (($include_link) - ? '[zrl=' . $mtch[2] . ']' . t('view full size') . '[/zrl]' . "\n" + ? '[' . $linktag . '=' . $mtch[3] . ']' . t('view full size') . '[/' . $linktag . ']' . "\n" : ''),$s); logger('new string: ' . $s, LOGGER_DEBUG); } diff --git a/include/taxonomy.php b/include/taxonomy.php index a13a9cf77..a646df28c 100644 --- a/include/taxonomy.php +++ b/include/taxonomy.php @@ -313,12 +313,25 @@ function dir_tagadelic($count = 0) { $count = intval($count); - // Fetch tags - $r = q("select xtag_term as term, count(xtag_term) as total from xtag where xtag_flags = 0 - group by xtag_term order by total desc %s", - ((intval($count)) ? "limit $count" : '') - ); - + $dirmode = get_config('system','directory_mode'); + + if($dirmode == DIRECTORY_MODE_STANDALONE) { + // Fetch tags + $r = q("select xtag_term as term, count(xtag_term) as total from xtag + left join hubloc on xtag_hash = hubloc_hash + where xtag_flags = 0 and hubloc_url = '%s' + group by xtag_term order by total desc %s", + dbesc(z_root()), + ((intval($count)) ? "limit $count" : '') + ); + } + else { + // Fetch tags + $r = q("select xtag_term as term, count(xtag_term) as total from xtag where xtag_flags = 0 + group by xtag_term order by total desc %s", + ((intval($count)) ? "limit $count" : '') + ); + } if(! $r) return array(); diff --git a/include/zid.php b/include/zid.php index d1a0fa88a..6ebc9a6ab 100644 --- a/include/zid.php +++ b/include/zid.php @@ -105,8 +105,8 @@ function strip_zats($s) { -function clean_query_string() { - $x = strip_zids(\App::$query_string); +function clean_query_string($s = '') { + $x = strip_zids(($s) ? $s : \App::$query_string); $x = strip_owt($x); $x = strip_zats($x); diff --git a/include/zot.php b/include/zot.php index 6c0d92a42..8e3d03ad8 100644 --- a/include/zot.php +++ b/include/zot.php @@ -3745,6 +3745,15 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) { * @TODO * We also need to import local photos if a custom photo is selected */ + + if((strpos($profile['thumb'],'/photo/profile/l/') !== false) || intval($profile['is_default'])) { + $profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id']; + $profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id']; + } + else { + $profile['photo'] = z_root() . '/photo/' . basename($profile['photo']); + $profile['thumb'] = z_root() . '/photo/' . basename($profile['thumb']); + } } if(count($clean)) { @@ -14,7 +14,7 @@ require_once('include/attach.php'); cli_startup(); -if($argc <= 3) { +if($argc < 3) { echo "Usage: " . $argv[0] . ' src dstdir' . "\n"; echo 'Always run from the toplevel web directory.' . "\n"; echo 'destination should begin with store/$nickname/desired/path or $nickname/desired/path' . "\n"; diff --git a/view/css/widgets.css b/view/css/widgets.css index 5b1273e25..76e829b04 100644 --- a/view/css/widgets.css +++ b/view/css/widgets.css @@ -170,6 +170,9 @@ a.wikilist { } /* notifications */ +.notifications-btn { + opacity: .5; +} .notification-content { max-height: 70vh; diff --git a/view/js/main.js b/view/js/main.js index 11a09b647..a228e6fbc 100644 --- a/view/js/main.js +++ b/view/js/main.js @@ -373,10 +373,12 @@ function notificationsUpdate() { if(data.network || data.home || data.intros || data.register || data.mail || data.all_events || data.notify || data.files || data.pubs) { $('.notifications-btn').css('opacity', 1); + $('#no_notifications').hide(); } else { $('.notifications-btn').css('opacity', 0.5); $('#navbar-collapse-1').removeClass('show'); + $('#no_notifications').show(); } if(data.home || data.intros || data.register || data.mail || data.notify || data.files) { diff --git a/view/tpl/admin_site.tpl b/view/tpl/admin_site.tpl index 399ee42cf..a2a9f3f27 100755 --- a/view/tpl/admin_site.tpl +++ b/view/tpl/admin_site.tpl @@ -23,7 +23,7 @@ $.post(url, data, function(data) { if(timer) clearTimeout(timer); - NavUpdate(); + updateInit(); $.colorbox.close(); }) diff --git a/view/tpl/jot-header.tpl b/view/tpl/jot-header.tpl index 2f9dd9f15..ffaa4e208 100755 --- a/view/tpl/jot-header.tpl +++ b/view/tpl/jot-header.tpl @@ -340,7 +340,7 @@ var activeCommentText = ''; $.get('{{$baseurl}}/tagger/' + id + '?term=' + reply); if(timer) clearTimeout(timer); - timer = setTimeout(NavUpdate,3000); + timer = setTimeout(updateInit,3000); liking = 1; } } @@ -359,7 +359,7 @@ var activeCommentText = ''; if(reply && reply.length) { commentBusy = true; $('body').css('cursor', 'wait'); - $.get('{{$baseurl}}/filer/' + id + '?term=' + reply, NavUpdate); + $.get('{{$baseurl}}/filer/' + id + '?term=' + reply, updateInit); liking = 1; $('#item-filer-dialog').modal('hide'); } @@ -372,13 +372,13 @@ var activeCommentText = ''; function itemBookmark(id) { $.get('{{$baseurl}}/bookmarks?f=&item=' + id); if(timer) clearTimeout(timer); - timer = setTimeout(NavUpdate,1000); + timer = setTimeout(updateInit,1000); } function itemAddToCal(id) { $.get('{{$baseurl}}/events/add/' + id); if(timer) clearTimeout(timer); - timer = setTimeout(NavUpdate,1000); + timer = setTimeout(updateInit,1000); } function toggleVoting() { @@ -409,7 +409,7 @@ var activeCommentText = ''; if(id && icon) { $.get('{{$baseurl}}/react?f=&postid=' + id + '&emoji=' + icon); if(timer) clearTimeout(timer); - timer = setTimeout(NavUpdate,1000); + timer = setTimeout(updateInit,1000); } } diff --git a/view/tpl/myapps.tpl b/view/tpl/myapps.tpl index dd2a67a63..0ac836b38 100755 --- a/view/tpl/myapps.tpl +++ b/view/tpl/myapps.tpl @@ -4,10 +4,10 @@ {{if $create}} <a href="appman" class="pull-right btn btn-success btn-sm"><i class="fa fa-pencil-square-o"></i> {{$create}}</a> {{else}} - <a href="apps/edit{{if $cat}}/?f=&cat={{$cat}}{{/if}}" class="pull-right btn btn-primary btn-sm">{{$manage}}</a> + <a href="apps/edit{{if $cat.0}}/?f=&cat={{$cat.0}}{{/if}}" class="pull-right btn btn-primary btn-sm">{{$manage}}</a> {{/if}} {{/if}} - <h2>{{$title}}{{if $cat}} - {{$cat}}{{/if}}</h2> + <h2>{{$title}}{{if $cat.0}} - {{$cat.0}}{{/if}}</h2> </div> <div class="clearfix section-content-wrapper"> {{foreach $apps as $ap}} diff --git a/view/tpl/notifications_widget.tpl b/view/tpl/notifications_widget.tpl index 299c07592..9d2e08c41 100644 --- a/view/tpl/notifications_widget.tpl +++ b/view/tpl/notifications_widget.tpl @@ -63,7 +63,7 @@ $(document).on('click', '#tt-{{$notification.type}}-only', function(e) { e.preventDefault(); $('#nav-{{$notification.type}}-menu [data-thread_top=false]').toggle(); - $(this).toggleClass('active'); + $(this).toggleClass('active sticky-top'); }); {{/if}} {{/foreach}} @@ -85,6 +85,9 @@ {{if $notifications}} <div id="notifications_wrapper"> + <div id="no_notifications" class="d-xl-none"> + {{$no_notifications}}<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span> + </div> <div id="notifications" class="navbar-nav" data-children=".nav-item"> <div id="nav-notifications-template" rel="template"> <a class="list-group-item clearfix notification {5}" href="{0}" title="{2} {3}" data-b64mid="{6}" data-notify_id="{7}" data-thread_top="{8}"> |