This commit is contained in:
zotlabs 2019-09-26 18:36:06 -07:00
commit 02f5fa32af
80 changed files with 849 additions and 437 deletions

View File

@ -1,10 +1,65 @@
# Hubzilla at Home next to your Router
# How to use
This readme will show you how to install and run Hubzilla (or Zap) at home.
## Disclaimers
The installation is done by a script.
- This script does work with Debian 10 only.
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
What the script will do for you...
## Preconditions
Hardware
+ Internet connection and router at home
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
+ USB drive for backups
Software
+ Fresh installation of Debian 10 (Stretch)
+ Router with open ports 80 and 443 for your web server
## How to run the script
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your fresh Debian
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- git clone https://framagit.org/hubzilla/core.git html
- 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
- Prepare your external disk for backups
- hubzilla-setup.sh as root
- ... wait, wait, wait until the script is finised
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
## Optional - Set path to imagemagick
In Admin settings of hubzilla or via terminal
cd /var/www/html
util/config system.imagick_convert_path /usr/bin/convert
## Optional - Switch verification of email on/off
Do this just befor you register the user.
In Admin settings of hubzilla or via terminal
cd /var/www/html
Check the current setting
util/config system verify_email
Switch the verification on/off (1/0)
util/config system verify_email 0
## What the script will do for you...
+ install everything required by Hubzilla, basically a web server (Apache), PHP, a database (MySQL), certbot,...
+ create a database
@ -38,69 +93,11 @@ The script can install both [Hubzilla](https://zotlabs.org/page/hubzilla/hubzill
- core: git clone https://framagit.org/zot/zap.git html (in this readme)
- addons: util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons (in hubzilla-setup.sh)
## Disclaimers
- This script does work with Debian 10 only.
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
# Step-by-Step Overwiew
# Step-by-Step - some Details
## Preconditions
Hardware
+ Internet connection and router at home
+ Mini-pc connected to your router (a Raspberry 3 will do for very small Hubs)
+ USB drive for backups
Software
+ Fresh installation of Debian 10 (Stretch)
+ Router with open ports 80 and 443 for your web server
## The basic steps (quick overview)
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
+ Log on to your fresh Debian
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- git clone https://framagit.org/hubzilla/core.git html
- 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
- Prepare your external disk for backups
- hubzilla-setup.sh as root
- ... wait, wait, wait until the script is finised
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
## Troubleshooting
If the check of the mail address fails when you try to register the very first user in the browser. Do...
cd /var/www/html
util/config system.do_not_check_dns 1
## Optional - Set path to imagemagick
In Admin settings of hubzilla or via terminal
cd /var/www/html
util/config system.imagick_convert_path /usr/bin/convert
# Step-by-Step in Detail
## Preparations Software
## Install Debian 9
Provided you use a Raspberry Pi 3...
Download the OS Raspbian from https://www.raspberrypi.org/downloads/raspbian/
Follow the installation instruction there.
## Preparations
## Configure your Router
@ -146,12 +143,5 @@ to boot the Rapsi to the client console.
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
On a Raspian Stretch (Debian 10) the validation of the mail address fails for the very first user.
This used to happen on some *bsd distros but there was some work to fix that a year ago (2017).
So if your system isn't registered in DNS or DNS isn't active do
cd /var/www/html
util/config system.do_not_check_dns 1

View File

@ -28,14 +28,13 @@
# * php,
# * mariadb - the database for hubzilla,
# * adminer,
# * git to download and update hubzilla addon
# - download hubzilla core and addons
# * git to download and update addons
# - configure cron
# * "Master.php" for regular background prozesses of hubzilla
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
# * backup hubzillas database and files (rsync)
# - letsencrypt
# - run letsencrypt to create, register and use a certifacte for https
#
#
# Discussion
@ -56,7 +55,7 @@
# - creates a daily cron that runs the hubzilla-daily.sh
#
# hubzilla-daily.sh makes a (daily) backup of all relevant files
# - /var/lib/mysql/ > hubzilla database
# - /var/lib/mysql/ > database
# - /var/www/ > hubzilla/zap from github
# - /etc/letsencrypt/ > certificates
#
@ -223,6 +222,11 @@ function install_curl {
nocheck_install "curl"
}
function install_wget {
print_info "installing wget..."
nocheck_install "wget"
}
function install_sendmail {
print_info "installing sendmail..."
nocheck_install "sendmail sendmail-bin"
@ -269,7 +273,19 @@ function install_adminer {
else
print_info "file /etc/adminer/adminer.conf exists already"
fi
a2enmod rewrite
if [ ! -f /etc/apache2/apache2.conf ]
then
die "could not find file /etc/apache2/apache2.conf"
fi
sed -i \
"s/AllowOverride None/AllowOverride all/" \
/etc/apache2/apache2.conf
a2enconf adminer
systemctl restart mariadb
systemctl reload apache2
}
@ -407,10 +423,9 @@ function install_letsencrypt {
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
fi
# check if user gave mail address
if [ -z "$le_email" ]
then
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
fi
nocheck_install "certbot python-certbot-apache"
print_info "run certbot ..."
@ -431,12 +446,19 @@ function check_https {
}
function install_hubzilla {
print_info "installing hubzilla addons..."
print_info "installing addons..."
cd /var/www/html/
# if you install Hubzilla
# util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
# if you install ZAP
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
if git remote -v | grep -i "origin.*core.git"
then
print_info "hubzilla"
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
elif git remote -v | grep -i "origin.*zap.git"
then
print_info "zap"
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
else
die "neither zap nor hubzilla repository > did not install addons or zap/hubzilla"
fi
mkdir -p "store/[data]/smarty3"
chmod -R 777 store
touch .htconfig.php
@ -446,7 +468,7 @@ function install_hubzilla {
chown root:www-data /var/www/html/
chown root:www-data /var/www/html/.htaccess
chmod 0644 /var/www/html/.htaccess
print_info "installed hubzilla"
print_info "installed addons"
}
function install_rsync {
@ -585,6 +607,7 @@ check_config
stop_hubzilla
update_upgrade
install_curl
install_wget
install_sendmail
install_apache
install_imagemagick
@ -600,23 +623,34 @@ configure_cron_selfhost
if [ "$le_domain" != "localhost" ]
then
install_letsencrypt
check_https
install_letsencrypt
configure_apache_for_https
check_https
else
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
fi
install_hubzilla
if [ "$le_domain" != "localhost" ]
then
rewrite_to_https
install_rsnapshot
else
print_info "is localhost - skipped rewrite to https and installation of rsnapshot"
fi
configure_cron_daily
if [ "$le_domain" != "localhost" ]
then
install_rsync
install_cryptosetup
install_cryptosetup
write_uninstall_script
else
print_info "is localhost - skipped installation of cryptosetup"
print_info "is localhost - skipped installation of cryptosetup"
fi
#set +x # stop debugging from here

View File

@ -215,7 +215,7 @@ class Cron {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
return;
}
reload_plugins();

View File

@ -13,7 +13,7 @@ class CurlAuth {
static public function run($argc,$argv) {
if($argc != 2)
killme();
return;
\App::$session->start();
@ -50,6 +50,6 @@ class CurlAuth {
file_put_contents($c,$x);
killme();
return;
}
}
}

View File

@ -9,7 +9,7 @@ if(array_search( __file__ , get_included_files()) === 0) {
if($argc)
Master::Release($argc,$argv);
killme();
return;
}

View File

@ -285,8 +285,21 @@ class Notifier {
}
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
return;
$hookinfo=[
'targetitem'=>$target_item,
'deliver'=>false
];
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
call_hooks('customitem_deliver',$hookinfo);
}
if (!$hookinfo['deliver']) {
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
return;
}
$target_item = $hookinfo['targetitem'];
}
// Check for non published items, but allow an exclusion for transmitting hidden file activities

View File

@ -47,7 +47,7 @@ class Poller {
$restart = true;
$generation = intval($argv[2]);
if(! $generation)
killme();
return;
}
if(($argc > 1) && intval($argv[1])) {

View File

@ -2,6 +2,7 @@
namespace Zotlabs\Lib;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Daemon\Master;
use Zotlabs\Web\HTTPSig;
@ -41,6 +42,8 @@ class Activity {
if($x['type'] === ACTIVITY_OBJ_PHOTO) {
return self::fetch_image($x);
}
call_hooks('encode_object',$x);
}
return $x;
@ -340,10 +343,21 @@ class Activity {
}
}
if (intval($i['item_wall']) && $i['mid'] === $i['parent_mid']) {
$ret['commentPolicy'] = map_scope(PermissionLimits::Get($i['uid'],'post_comments'));
}
if (intval($i['item_private']) === 2) {
$ret['directMessage'] = true;
}
if (array_key_exists('comments_closed',$i) && $i['comments_closed'] !== EMPTY_STR && $i['comments_closed'] !== NULL_DATE) {
if($ret['commentPolicy']) {
$ret['commentPolicy'] .= ' ';
}
$ret['commentPolicy'] .= 'until=' . datetime_convert('UTC','UTC',$i['comments_closed'],ATOM_TIME);
}
$ret['attributedTo'] = $i['author']['xchan_url'];
if($i['id'] != $i['parent']) {
@ -795,6 +809,7 @@ class Activity {
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
];
call_hooks('activity_mapper',$acts);
if(array_key_exists($verb,$acts) && $acts[$verb]) {
return $acts[$verb];
@ -840,6 +855,7 @@ class Activity {
'http://purl.org/zot/activity/attendmaybe' => 'TentativeAccept'
];
call_hooks('activity_decode_mapper',$acts);
foreach($acts as $k => $v) {
if($verb === $v) {
@ -873,6 +889,8 @@ class Activity {
];
call_hooks('activity_obj_decode_mapper',$objs);
foreach($objs as $k => $v) {
if($obj === $v) {
return $k;
@ -910,6 +928,8 @@ class Activity {
];
call_hooks('activity_obj_mapper',$objs);
if(array_key_exists($obj,$objs)) {
return $objs[$obj];
}
@ -1930,6 +1950,15 @@ class Activity {
set_iconfig($s,'activitypub','rawmsg',$act->raw,1);
}
$hookinfo = [
'act' => $act,
's' => $s
];
call_hooks('decode_note',$hookinfo);
$s = $hookinfo['s'];
return $s;
}
@ -2119,16 +2148,25 @@ class Activity {
break;
}
if(! $item) {
break;
$hookinfo = [
'a' => $a,
'item' => $item
];
call_hooks('fetch_and_store',$hookinfo);
$item = $hookinfo['item'];
if($item) {
array_unshift($p,[ $a, $item, $replies]);
if($item['parent_mid'] === $item['mid'] || count($p) > 20) {
break;
}
}
array_unshift($p,[ $a, $item, $replies]);
if($item['parent_mid'] === $item['mid'] || count($p) > 20) {
break;
}
$current_act = $a;
$current_item = $item;
}
@ -2177,11 +2215,19 @@ class Activity {
default:
break;
}
if(! $item) {
break;
}
array_unshift($p,[ $a, $item ]);
$hookinfo = [
'a' => $a,
'item' => $item
];
call_hooks('fetch_and_store',$hookinfo);
$item = $hookinfo['item'];
if($item) {
array_unshift($p,[ $a, $item ]);
}
}

View File

@ -1223,9 +1223,39 @@ class Libzot {
if($private) {
$arr['item_private'] = true;
}
if ($arr['mid'] === $arr['parent_mid']) {
if (is_array($AS->obj) && array_key_exists('commentPolicy',$AS->obj)) {
$p = strstr($AS->obj['commentPolicy'],'until=');
if($p !== false) {
$arr['comments_closed'] = datetime_convert('UTC','UTC', substr($p,6));
$arr['comment_policy'] = trim(str_replace($p,'',$AS->obj['commentPolicy']));
}
else {
$arr['comment_policy'] = $AS->obj['commentPolicy'];
}
}
}
/// @FIXME - spoofable
if($AS->data['hubloc']) {
$arr['item_verified'] = true;
if (! array_key_exists('comment_policy',$arr)) {
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
// Anything else we'll say is zot - which could have a range of project names
$s = q("select site_project from site where site_url = '%s' limit 1",
dbesc($r[0]['hubloc_url'])
);
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
$arr['comment_policy'] = 'authenticated';
}
else {
$arr['comment_policy'] = 'contacts';
}
}
}
if($AS->data['signed_data']) {
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
@ -1819,6 +1849,10 @@ class Libzot {
$ret = [];
$signer = q("select hubloc_hash, hubloc_url from hubloc where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
dbesc($a['signature']['signer'])
);
foreach($a['data']['orderedItems'] as $activity) {
$AS = new ActivityStreams($activity);
@ -1877,6 +1911,23 @@ class Libzot {
if($AS->data['hubloc']) {
$arr['item_verified'] = true;
}
// set comment policy depending on source hub. Unknown or osada is ActivityPub.
// Anything else we'll say is zot - which could have a range of project names
if ($signer) {
$s = q("select site_project from site where site_url = '%s' limit 1",
dbesc($signer[0]['hubloc_url'])
);
if ((! $s) || (in_array($s[0]['site_project'],[ '', 'osada' ]))) {
$arr['comment_policy'] = 'authenticated';
}
else {
$arr['comment_policy'] = 'contacts';
}
}
if($AS->data['signed_data']) {
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
}

View File

@ -345,7 +345,7 @@ class Directory extends \Zotlabs\Web\Controller {
'pdesc_label' => t('Description:'),
'marital' => $marital,
'homepage' => $homepage,
'homepageurl' => linkify($homepageurl),
'homepageurl' => linkify($homepageurl, true),
'hometown' => $hometown,
'hometown_label' => t('Hometown:'),
'about' => $about,

View File

@ -63,6 +63,18 @@ class Well_known extends \Zotlabs\Web\Controller {
case 'dnt-policy.txt':
echo file_get_contents('doc/dnt-policy.txt');
killme();
case 'caldav':
if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
http_status('301', 'moved permanently');
goaway(z_root() . '/cdav');
};
case 'carddav':
if ($_SERVER['REQUEST_METHOD'] == 'PROPFIND') {
http_status('301', 'moved permanently');
goaway(z_root() . '/cdav');
};
default:
if(file_exists(\App::$cmd)) {

View File

@ -38,10 +38,15 @@ class SessionHandler implements \SessionHandlerInterface {
function write ($id, $data) {
// Pretend everything is hunky-dory, even though it isn't.
// There probably isn't anything we can do about it in any event.
// See: https://stackoverflow.com/a/43636110
if(! $id || ! $data) {
return false;
return true;
}
// Unless we authenticate somehow, only keep a session for 5 minutes
// The viewer can extend this by performing any web action using the
// original cookie, but this allows us to cleanup the hundreds or

58
composer.lock generated
View File

@ -8,16 +8,16 @@
"packages": [
{
"name": "blueimp/jquery-file-upload",
"version": "v9.31.0",
"version": "v9.34.0",
"source": {
"type": "git",
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
"reference": "2485bf016e1085f0cd8308723064458cb0af5729"
"reference": "6d86a591f9a35bb811befb750dcd2c7da9ac05a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/2485bf016e1085f0cd8308723064458cb0af5729",
"reference": "2485bf016e1085f0cd8308723064458cb0af5729",
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/6d86a591f9a35bb811befb750dcd2c7da9ac05a2",
"reference": "6d86a591f9a35bb811befb750dcd2c7da9ac05a2",
"shasum": ""
},
"type": "library",
@ -59,7 +59,7 @@
"upload",
"widget"
],
"time": "2019-05-24T07:59:46+00:00"
"time": "2019-07-22T13:10:51+00:00"
},
{
"name": "bshaffer/oauth2-server-php",
@ -204,23 +204,23 @@
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
"version": "v4.11.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "^1.1"
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
},
"type": "library",
"autoload": {
@ -233,7 +233,7 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
"LGPL-2.1-or-later"
],
"authors": [
{
@ -247,20 +247,20 @@
"keywords": [
"html"
],
"time": "2018-02-23T01:58:20+00:00"
"time": "2019-07-14T18:58:38+00:00"
},
{
"name": "league/html-to-markdown",
"version": "4.8.1",
"version": "4.8.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1"
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e747489191f8e9144a7270eb61f8b9516e99e413",
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413",
"shasum": ""
},
"require": {
@ -292,17 +292,17 @@
"MIT"
],
"authors": [
{
"name": "Nick Cernis",
"email": "nick@cern.is",
"homepage": "http://modernnerd.net",
"role": "Original Author"
},
{
"name": "Colin O'Dell",
"email": "colinodell@gmail.com",
"homepage": "https://www.colinodell.com",
"role": "Lead Developer"
},
{
"name": "Nick Cernis",
"email": "nick@cern.is",
"homepage": "http://modernnerd.net",
"role": "Original Author"
}
],
"description": "An HTML-to-markdown conversion helper for PHP",
@ -311,7 +311,7 @@
"html",
"markdown"
],
"time": "2018-12-24T17:21:44+00:00"
"time": "2019-08-02T11:57:39+00:00"
},
{
"name": "lukasreschke/id3parser",
@ -1020,16 +1020,16 @@
},
{
"name": "simplepie/simplepie",
"version": "1.5.2",
"version": "1.5.3",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263"
"reference": "173663382a9346acd53df60c7ffb20689c9cf1f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/0e8fe72132dad765d25db4cabc69a91139af1263",
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/173663382a9346acd53df60c7ffb20689c9cf1f6",
"reference": "173663382a9346acd53df60c7ffb20689c9cf1f6",
"shasum": ""
},
"require": {
@ -1088,10 +1088,10 @@
"rss"
],
"support": {
"source": "https://github.com/simplepie/simplepie/tree/1.5.2",
"source": "https://github.com/simplepie/simplepie/tree/1.5.3",
"issues": "https://github.com/simplepie/simplepie/issues"
},
"time": "2018-08-02T05:43:58+00:00"
"time": "2019-09-22T23:21:30+00:00"
},
{
"name": "smarty/smarty",

View File

@ -1,3 +1,12 @@
[h2]Database updates[/h2]
In the [observer.baseurl]/admin/dbsync page the administrator can check if any update was not successful and, if so, retry it.
If an update has failed but doesn't register as failed for some reason, the administrator can attempt to re-execute the update. For example for DB update #1999, by visiting the webpage:
https://hubzilla.com.bradmin/dbsync/1999
[h2]Database Tables[/h2][table border=1][tr][th]Table[/th][th]Description[/th][/tr]
[tr][td][zrl=[baseurl]/help/database/db_abconfig]abconfig[/zrl][/td][td]arbitrary storage for connections of local channels[/td][/tr]
[tr][td][zrl=[baseurl]/help/database/db_abook]abook[/zrl][/td][td]connections of local channels[/td][/tr]

View File

@ -1,7 +1,10 @@
[h1]Advanced Configurations for Administrators[/h1]
$Projectname contains many configuration options hidden from the main admin panel.
These are generally options considered too niche, confusing, or advanced for the average member. These settings can be activated from the the top level web directory with the syntax
[i]This document assumes you're an administrator.[/i]
$Projectname contains many configuration options hidden from the main admin panel. These are generally options considered too niche, advanced or prone do confusion.
These settings can be modified through the shell, from the the top level web directory, with the syntax:
[code]util/config cat key value[/code]
for a site configuration, or
@ -9,8 +12,13 @@ for a site configuration, or
[code]util/pconfig channel_id cat key value[/code]
for a member configuration.
This document assumes you're an administrator.
[h2]pconfig[/h2][dl terms="mb"]
For a site configuration, another option is to add a line to .htconfig.php, with the syntax:
[code]App::$config['cat']['key'] = 'value';[/code]
[h2]Member configuration (pconfig)[/h2]
[dl terms="mb"]
[*= system.always_my_theme ] Always use your own theme when viewing channels on the same hub. This will break in some quite imaginative ways when viewing channels with theme dependent Comanche.
[*= system.blocked ] An array of xchans blocked by this channel. Technically, this is a hidden config and does belong here, however, addons (notably superblock) have made this available in the UI.
[*= system.default_cipher ] Set the default cipher used for E2EE items.
@ -31,7 +39,10 @@ Options are:
[*= system.anonymous_comments ] By default or if set to 1, custom permissions can be set to allow anonymous (moderated) comments like WordPress, moderated by the channel owner. If set to 0, no member of your site can select or enable this.
[*= system.user_scalable ] Determine if the app is scalable on touch screens. Defaults to on, to disable, set to zero - real zero, not just false.
[/dl]
[h2]Site config[/h2][dl terms="mb"]
[h2]Site configuration[/h2]
[dl terms="mb"]
[*= randprofile.check ] When requesting a random profile, check that it actually exists first
[*= randprofile.retry ] Number of times to retry getting a random profile
[*= system.admin_email ] Specifies the administrator's email for this site. This is initially set during install.
@ -87,13 +98,19 @@ Options are:
[*= system.workflow_channel_next ] The page to direct new members to immediately after creating a channel.
[*= system.workflow_register_next ] The page to direct members to immediately after creating an account (only when auto_channel_create or UNO is enabled).
[/dl]
[h2]Directory config[/h2]
[h3]Directory search defaults[/h3][dl terms="mb"]
[h3]Directory config[/h3]
[h4]Directory search defaults[/h4]
[dl terms="mb"]
[*= directory.globaldir ] 0 or 1. Default 0. If you visit the directory on a site you'll just see the members of that site by default. You have to go through an extra step to see the people in the rest of the network; and by doing so there's a clear delineation that these people *aren't* members of that site but of a larger network.
[*= directory.pubforums ] 0 or 1. Public forums [i]should[/i] be default 0.
[*= directory.safemode ] 0 or 1.
[/dl]
[h3]Directory server configuration[/h3][i](see [zrl=[baseurl]/help/directories]help/directories[/zrl])[/i]
[h4]Directory server configuration[/h4][i](see [zrl=[baseurl]/help/directories]help/directories[/zrl])[/i]
[dl terms="mb"]
[*= system.directory_mode ]

View File

@ -0,0 +1 @@
[h2]activity_decode_mapper[/h2]

View File

@ -0,0 +1 @@
[h2]activity_mapper[/h2]

View File

@ -0,0 +1 @@
[h2]activity_obj_decode_mapper[/h2]

View File

@ -0,0 +1 @@
[h2]activity_obj_mapper[/h2]

View File

@ -0,0 +1 @@
[h2]encode_object[/h2]

View File

@ -0,0 +1 @@
[h2]fetch_and_store[/h2]

View File

@ -34,6 +34,18 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/activity_filter]activity_filter[/zrl]
Called when generating the list of filters for the network page
[zrl=[baseurl]/help/hook/activity_filter]activity_mapper[/zrl]
Called when determining the activity type for transmission.
[zrl=[baseurl]/help/hook/activity_filter]activity_decode_mapper[/zrl]
Called when determining the activity type for transmission.
[zrl=[baseurl]/help/hook/activity_filter]activity_obj_mapper[/zrl]
Called when determining the object type for transmission.
[zrl=[baseurl]/help/hook/activity_filter]activity_obj_decode_mapper[/zrl]
Called when determining the object type for transmission.
[zrl=[baseurl]/help/hook/activity_order]activity_order[/zrl]
Called when generating the list of order options for the network page
@ -232,6 +244,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/drop_item]drop_item[/zrl]
called when an 'item' is removed
[zrl=[baseurl]/help/hook/encode_object]encode_object[/zrl]
called when encoding an object for transmission.
[zrl=[baseurl]/help/hook/enotify]enotify[/zrl]
called before any notification
@ -262,6 +277,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/feature_settings_post]feature_settings_post[/zrl]
called from settings page when posting from 'addon/feature settings'
[zrl=[baseurl]/help/hook/fetch_and_store]fetch_and_store[/zrl]
called to allow filtering of 'decoded' items before storage.
[zrl=[baseurl]/help/hook/file_thumbnail]file_thumbnail[/zrl]
called when generating thumbnail images for cloud page in 'view tiles' mode

View File

@ -37,7 +37,8 @@
<div class="flex-column">
<a class="nav-link" href="/help/admin/administrator_guide">Guide</a>
<a class="nav-link" href="/help/admin/hub_snapshots">Hub Snapshots</a>
<a class="nav-link" href="/help/database">Database Tables</a>
<a class="nav-link" href="/help/database">Database</a>
<a class="nav-link" href="/help/hidden_configs">Extra configs</a>
</div>
</div>
</div>

View File

@ -1718,9 +1718,9 @@ function advanced_profile() {
if(App::$profile['sexual']) $profile['sexual'] = array( t('Sexual Preference:'), App::$profile['sexual'] );
if(App::$profile['homepage']) $profile['homepage'] = array( t('Homepage:'), linkify(App::$profile['homepage']) );
if(App::$profile['homepage']) $profile['homepage'] = array( t('Homepage:'), linkify(App::$profile['homepage'], true) );
if(App::$profile['hometown']) $profile['hometown'] = array( t('Hometown:'), linkify(App::$profile['hometown']) );
if(App::$profile['hometown']) $profile['hometown'] = array( t('Hometown:'), linkify(App::$profile['hometown'], true) );
if(App::$profile['politic']) $profile['politic'] = array( t('Political Views:'), App::$profile['politic']);

View File

@ -1640,20 +1640,14 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
'allow_exec' => $allow_exec
];
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
/* Custom items are not stored by default
because they require an addon to process. */
$d['item']['cancel']=true;
call_hooks('item_custom',$d);
}
/**
* @hooks item_store
* Called when item_store() stores a record of type item.
* * \e array \b item
* * \e boolean \b allow_exec
*/
call_hooks('item_store', $d);
call_hooks('item_store_before', $d);
$arr = $d['item'];
$allow_exec = $d['allow_exec'];
@ -1961,6 +1955,7 @@ function item_store($arr, $allow_exec = false, $deliver = true) {
*/
call_hooks('item_store', $arr);
/**
* @hooks post_remote
* Called when an activity arrives from another site.
@ -2129,14 +2124,6 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
'allow_exec' => $allow_exec
];
if ($arr['item_type']==ITEM_TYPE_CUSTOM) {
/* Custom items are not stored by default
because they require an addon to process. */
$d['item']['cancel']=true;
call_hooks('item_custom_update',$d);
}
/**
* @hooks item_store_update
* Called when item_store_update() is called to update a stored item. It
@ -2144,7 +2131,7 @@ function item_store_update($arr, $allow_exec = false, $deliver = true) {
* * \e array \b item
* * \e boolean \b allow_exec
*/
call_hooks('item_store_update', $d);
call_hooks('item_store_update_before', $d);
$arr = $d['item'];
$allow_exec = $d['allow_exec'];

View File

@ -266,7 +266,7 @@ function bb_to_markdown($Text, $options = []) {
$Text = preg_replace("/\[zrl\=\].*?\[\/zrl\]/is", "", $Text);
// Remove unprocessed spoiler HTML tags
$Text = strip_tags(preg_replace("/(<\/div>)(>.+)$/im", "$1\n$2", $Text));
$Text = preg_replace("/<div.+>([^<]+)<.+>(>.+)$/im", "$1\n$2", $Text);
$Text = trim($Text);

View File

@ -596,7 +596,7 @@ CREATE TABLE IF NOT EXISTS `item` (
`postopts` text NOT NULL,
`route` text NOT NULL,
`llink` char(191) NOT NULL DEFAULT '',
`plink` char(191) NOT NULL DEFAULT '',
`plink` text NOT NULL,
`resource_id` char(191) NOT NULL DEFAULT '',
`resource_type` char(16) NOT NULL DEFAULT '',
`attach` mediumtext NOT NULL,

View File

@ -17,7 +17,7 @@ if($x) {
$width = $xx['width'];
$height = $xx['height'];
$n = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale > 0",
$n = q("SELECT * FROM photo WHERE resource_id = '%s' AND imgscale > 0 ORDER BY imgscale",
dbesc($xx['resource_id'])
);

View File

@ -96,12 +96,16 @@ The File Upload plugin is regularly tested with the latest browser versions and
### Mobile browsers
The File Upload plugin has been tested with and supports the following mobile browsers:
* Apple Safari on iOS 6.0+
* Google Chrome on iOS 6.0+
* Apple Safari on iOS 6.0+ (see Caveats below)
* Google Chrome on iOS 6.0+ (see Caveats below)
* Google Chrome on Android 4.0+
* Default Browser on Android 2.3+
* Opera Mobile 12.0+
### Caveats
- iOS 9 has a [known bug](https://apple.stackexchange.com/questions/118154) where photos chosen from the Photo Library are all given the name `image.jpeg`, which is problematic when uploading multiple files at a time. Ideally your server should be responsible for deduplicating file uploads ([example](https://github.com/blueimp/jQuery-File-Upload/blob/master/server/php/UploadHandler.php#L490)). If you don't have control, as in the case of direct uploads to S3, you can pass an option `uniqueFilenames: {}` as part of the options object, which tells the uploader to deduplicate filenames. More details [here](https://github.com/blueimp/jQuery-File-Upload/commit/d419f43478aeafe95a794815f80a3016f58eb3b7).
### Supported features
For a detailed overview of the features supported by each browser version, please have a look at the [Extended browser support information](https://github.com/blueimp/jQuery-File-Upload/wiki/Browser-support).

View File

@ -162,14 +162,14 @@ $(function () {
}).on('fileuploadadd', function (e, data) {
data.context = $('<div/>').appendTo('#files');
$.each(data.files, function (index, file) {
var node = $('<p/>')
.append($('<span/>').text(file.name));
if (!index) {
node
.append('<br>')
.append(uploadButton.clone(true).data(data));
$('<p/>')
.append($('<span/>').text(file.name))
.appendTo(data.context);
if (index === data.files.length - 1) {
$('<p/>')
.append(uploadButton.clone(true).data(data))
.appendTo(data.context);
}
node.appendTo(data.context);
});
}).on('fileuploadprocessalways', function (e, data) {
var index = data.index,

View File

@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
"version": "9.31.0",
"version": "9.34.0",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&amp;drop support, progress bar, validation and preview images.",
"keywords": [

View File

@ -165,6 +165,15 @@
bitrateInterval: 500,
// By default, uploads are started automatically when adding files:
autoUpload: true,
// By default, duplicate file names are expected to be handled on
// the server-side. If this is not possible (e.g. when uploading
// files directly to Amazon S3), the following option can be set to
// an empty object or an object mapping existing filenames, e.g.:
// { "image.jpg": true, "image (1).jpg": true }
// If it is set, all files will be uploaded with unique filenames,
// adding increasing number suffixes if necessary, e.g.:
// "image (2).jpg"
uniqueFilenames: undefined,
// Error and info messages:
messages: {
@ -449,6 +458,23 @@
return Object.prototype.toString.call(obj) === '[object ' + type + ']';
},
_getUniqueFilename: function (name, map) {
name = String(name);
if (map[name]) {
name = name.replace(
/(?: \(([\d]+)\))?(\.[^.]+)?$/,
function (_, p1, p2) {
var index = p1 ? Number(p1) + 1 : 1;
var ext = p2 || '';
return ' (' + index + ')' + ext;
}
);
return this._getUniqueFilename(name, map);
}
map[name] = true;
return name;
},
_initXHRData: function (options) {
var that = this,
formData,
@ -510,11 +536,18 @@
// dummy objects:
if (that._isInstanceOf('File', file) ||
that._isInstanceOf('Blob', file)) {
var fileName = file.uploadName || file.name;
if (options.uniqueFilenames) {
fileName = that._getUniqueFilename(
fileName,
options.uniqueFilenames
);
}
formData.append(
($.type(options.paramName) === 'array' &&
options.paramName[index]) || paramName,
file,
file.uploadName || file.name
fileName
);
}
});

View File

@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
"version": "9.31.0",
"version": "9.34.0",
"title": "jQuery File Upload",
"description": "File Upload widget with multiple file selection, drag&drop support, progress bar, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (Google App Engine, PHP, Python, Ruby on Rails, Java, etc.) that supports standard HTML form file uploads.",
"keywords": [

View File

@ -1,20 +1,20 @@
[
{
"name": "blueimp/jquery-file-upload",
"version": "v9.31.0",
"version_normalized": "9.31.0.0",
"version": "v9.34.0",
"version_normalized": "9.34.0.0",
"source": {
"type": "git",
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
"reference": "2485bf016e1085f0cd8308723064458cb0af5729"
"reference": "6d86a591f9a35bb811befb750dcd2c7da9ac05a2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/2485bf016e1085f0cd8308723064458cb0af5729",
"reference": "2485bf016e1085f0cd8308723064458cb0af5729",
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/6d86a591f9a35bb811befb750dcd2c7da9ac05a2",
"reference": "6d86a591f9a35bb811befb750dcd2c7da9ac05a2",
"shasum": ""
},
"time": "2019-05-24T07:59:46+00:00",
"time": "2019-07-22T13:10:51+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -205,26 +205,26 @@
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
"version_normalized": "4.10.0.0",
"version": "v4.11.0",
"version_normalized": "4.11.0.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "d85d39da4576a6934b72480be6978fb10c860021"
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/d85d39da4576a6934b72480be6978fb10c860021",
"reference": "d85d39da4576a6934b72480be6978fb10c860021",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"reference": "83ab08bc1af7d808a9e0fbf024f1c24bfd73c0a7",
"shasum": ""
},
"require": {
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "^1.1"
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
},
"time": "2018-02-23T01:58:20+00:00",
"time": "2019-07-14T18:58:38+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -237,7 +237,7 @@
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL"
"LGPL-2.1-or-later"
],
"authors": [
{
@ -254,17 +254,17 @@
},
{
"name": "league/html-to-markdown",
"version": "4.8.1",
"version_normalized": "4.8.1.0",
"version": "4.8.2",
"version_normalized": "4.8.2.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1"
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"reference": "250d1bf45f80d15594fb6b316df777d6d4c97ad1",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/e747489191f8e9144a7270eb61f8b9516e99e413",
"reference": "e747489191f8e9144a7270eb61f8b9516e99e413",
"shasum": ""
},
"require": {
@ -277,7 +277,7 @@
"phpunit/phpunit": "4.*",
"scrutinizer/ocular": "~1.1"
},
"time": "2018-12-24T17:21:44+00:00",
"time": "2019-08-02T11:57:39+00:00",
"bin": [
"bin/html-to-markdown"
],
@ -298,17 +298,17 @@
"MIT"
],
"authors": [
{
"name": "Nick Cernis",
"email": "nick@cern.is",
"homepage": "http://modernnerd.net",
"role": "Original Author"
},
{
"name": "Colin O'Dell",
"email": "colinodell@gmail.com",
"homepage": "https://www.colinodell.com",
"role": "Lead Developer"
},
{
"name": "Nick Cernis",
"email": "nick@cern.is",
"homepage": "http://modernnerd.net",
"role": "Original Author"
}
],
"description": "An HTML-to-markdown conversion helper for PHP",
@ -1049,17 +1049,17 @@
},
{
"name": "simplepie/simplepie",
"version": "1.5.2",
"version_normalized": "1.5.2.0",
"version": "1.5.3",
"version_normalized": "1.5.3.0",
"source": {
"type": "git",
"url": "https://github.com/simplepie/simplepie.git",
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263"
"reference": "173663382a9346acd53df60c7ffb20689c9cf1f6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/0e8fe72132dad765d25db4cabc69a91139af1263",
"reference": "0e8fe72132dad765d25db4cabc69a91139af1263",
"url": "https://api.github.com/repos/simplepie/simplepie/zipball/173663382a9346acd53df60c7ffb20689c9cf1f6",
"reference": "173663382a9346acd53df60c7ffb20689c9cf1f6",
"shasum": ""
},
"require": {
@ -1078,7 +1078,7 @@
"ext-mbstring": "",
"mf2/mf2": "Microformat module that allows for parsing HTML for microformats"
},
"time": "2018-08-02T05:43:58+00:00",
"time": "2019-09-22T23:21:30+00:00",
"type": "library",
"installation-source": "dist",
"autoload": {
@ -1120,7 +1120,7 @@
"rss"
],
"support": {
"source": "https://github.com/simplepie/simplepie/tree/1.5.2",
"source": "https://github.com/simplepie/simplepie/tree/1.5.3",
"issues": "https://github.com/simplepie/simplepie/issues"
}
},

View File

@ -15,7 +15,7 @@ with these contents.
---------------------------------------------------------------------------
1. Compatibility
HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.0.5
HTML Purifier is PHP 5 and PHP 7, and is actively tested from PHP 5.3
and up. It has no core dependencies with other libraries.
These optional extensions can enhance the capabilities of HTML Purifier:
@ -101,31 +101,6 @@ Autoload compatibility
autoloader, but there are some cases where you will need to change
your own code to accomodate HTML Purifier. These are those cases:
PHP VERSION IS LESS THAN 5.1.2, AND YOU'VE DEFINED __autoload
Because spl_autoload_register() doesn't exist in early versions
of PHP 5, HTML Purifier has no way of adding itself to the autoload
stack. Modify your __autoload function to test
HTMLPurifier_Bootstrap::autoload($class)
For example, suppose your autoload function looks like this:
function __autoload($class) {
require str_replace('_', '/', $class) . '.php';
return true;
}
A modified version with HTML Purifier would look like this:
function __autoload($class) {
if (HTMLPurifier_Bootstrap::autoload($class)) return true;
require str_replace('_', '/', $class) . '.php';
return true;
}
Note that there *is* some custom behavior in our autoloader; the
original autoloader in our example would work for 99% of the time,
but would fail when including language files.
AN __autoload FUNCTION IS DECLARED AFTER OUR AUTOLOADER IS REGISTERED
spl_autoload_register() has the curious behavior of disabling
the existing __autoload() handler. Users need to explicitly
@ -138,11 +113,6 @@ Autoload compatibility
spl_autoload_register('__autoload')
Users should also be on guard if they use a version of PHP previous
to 5.1.2 without an autoloader--HTML Purifier will define __autoload()
for you, which can collide with an autoloader that was added by *you*
later.
For better performance
----------------------
@ -204,9 +174,7 @@ For advanced users
HTMLPurifier.autoload.php
Registers our autoload handler HTMLPurifier_Bootstrap::autoload($class).
You can do these operations by yourself--in fact, you must modify your own
autoload handler if you are using a version of PHP earlier than PHP 5.1.2
(See "Autoload compatibility" above).
You can do these operations by yourself, if you like.
---------------------------------------------------------------------------

View File

@ -11,7 +11,7 @@ pied de page, mais je recommande de lire le document.
1. Compatibilité
HTML Purifier fonctionne avec PHP 5. PHP 5.0.5 est la dernière version testée.
HTML Purifier fonctionne avec PHP 5. PHP 5.3 est la dernière version testée.
Il ne dépend pas d'autres librairies.
Les extensions optionnelles sont iconv (généralement déjà installée) et tidy

View File

@ -9,6 +9,34 @@ NEWS ( CHANGELOG and HISTORY ) HTMLPurifier
. Internal change
==========================
4.11.0, released 2019-07-14
# SafeScripting now matches case-sensitively against its whitelist (previously it was
case-insensitive.) Thanks Dimitri Gritsajuk <gritsajuk.dimitri@gmail.com>
for reporting.
! New directive %Core.AllowParseManyTags which allows parsing of many nested tags.
Thanks M. Suzuki <msuzuki1986@gmail.com> for contributing the patch.
! purifyArray now supports multidimensional arrays. Thanks
Sandro Miguel Marques <sandromiguel@sandromiguel.com> for contributing this patch.
! initial and inherit settings available for width, height, and the min-/max-
versions thereof. Thanks Michael Kliewe <info@phpgansta.de> for contributing
this patch.
! More color names are supported. Thanks Daijobou for contributing.
- Compatibility fixes for PHP 7.3, including new CI for PHP 7.3
(thank you Lukas Neumann <lksnmnn@gmail.com>) and removal of
reserved words in our constants (thanks Darko Hrgovic <darko@darkodev.com>
- Compatibility fixes for HHVM. Thanks Mateusz Turcza for contributing
this fix.
- HTML Purifier now never defines __autoload, fixing #196. Thanks
Michael Kliewe for reporting.
- In some situations, Config.php would report an undefined index: class
error; this has been fixed. Thanks DiLong Fa for contributing
this fix.
- We no longer produce <script /> tags; we always explicitly write
out the open and close tag. Thanks Dimitri Gritsajuk
<gritsajuk.dimitri@gmail.com> for contributing this fix.
- Better compatibility when IDNA constants are not present. Thanks
Mateusz Turcza <xemlock@gmail.com> for contributing this fix.
4.10.0, released 2018-02-22
# PHP 5.3 is no longer officially supported by HTML Purifier
(we did not specifically break support, but we are no longer

View File

@ -26,4 +26,4 @@ Package available on [Composer](https://packagist.org/packages/ezyang/htmlpurifi
If you're using Composer to manage dependencies, you can use
$ composer require "ezyang/htmlpurifier":"dev-master"
$ composer require ezyang/htmlpurifier

View File

@ -1 +1 @@
4.10.0
4.11.0

View File

@ -1,13 +1,7 @@
HTML Purifier 4.9.x is a maintenance release, collecting a year
of accumulated bug fixes plus a few new features. New features
include support for min/max-width/height CSS, and rgba/hsl/hsla
in color specifications. Major bugfixes include improvements
in the Serializer cache to avoid chmod'ing directories, better
entity decoding (we won't accidentally encode entities that occur
in URLs) and rel="noopener" on links with target attributes,
to prevent them from overwriting the original frame.
4.9.3 works around an infinite loop bug in PHP 7.1 with the opcode
cache (and has one other, minor bugfix, avoiding using autoloading
when testing for DOMDocument presence). If these bugs do not
affect you, you do not need to upgrade.
HTML Purifier 4.11.x is a maintenance release, collecting a year
and a half of accumulated bug fixes. Most notable fixes are
compatibility with PHP 7.3, and case-sensitive matching for
the SafeScripting whitelist. There are a number small feature
enhancements, including an expanded supported color list,
initial and inherit support for {min-,max-,}{width,height}
and multidimensional array support for purifyArray.

View File

@ -4,7 +4,7 @@
"type": "library",
"keywords": ["html"],
"homepage": "http://htmlpurifier.org/",
"license": "LGPL",
"license": "LGPL-2.1-or-later",
"authors": [
{
"name": "Edward Z. Yang",
@ -16,7 +16,7 @@
"php": ">=5.2"
},
"require-dev": {
"simpletest/simpletest": "^1.1"
"simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
},
"autoload": {
"psr-0": { "HTMLPurifier": "library/" },

View File

@ -7,7 +7,7 @@
* primary concern and you are using an opcode cache. PLEASE DO NOT EDIT THIS
* FILE, changes will be overwritten the next time the script is run.
*
* @version 4.10.0
* @version 4.11.0
*
* @warning
* You must *not* include any other HTML Purifier files before this file,

View File

@ -19,7 +19,7 @@
*/
/*
HTML Purifier 4.10.0 - Standards Compliant HTML Filtering
HTML Purifier 4.11.0 - Standards Compliant HTML Filtering
Copyright (C) 2006-2008 Edward Z. Yang
This library is free software; you can redistribute it and/or
@ -58,12 +58,12 @@ class HTMLPurifier
* Version of HTML Purifier.
* @type string
*/
public $version = '4.10.0';
public $version = '4.11.0';
/**
* Constant with version of HTML Purifier.
*/
const VERSION = '4.10.0';
const VERSION = '4.11.0';
/**
* Global configuration object.
@ -240,12 +240,16 @@ class HTMLPurifier
public function purifyArray($array_of_html, $config = null)
{
$context_array = array();
foreach ($array_of_html as $key => $html) {
$array_of_html[$key] = $this->purify($html, $config);
foreach($array_of_html as $key=>$value){
if (is_array($value)) {
$array[$key] = $this->purifyArray($value, $config);
} else {
$array[$key] = $this->purify($value, $config);
}
$context_array[$key] = $this->context;
}
$this->context = $context_array;
return $array_of_html;
return $array;
}
/**

View File

@ -97,7 +97,11 @@ class HTMLPurifier_AttrDef_URI_Host extends HTMLPurifier_AttrDef
// PHP 5.3 and later support this functionality natively
if (function_exists('idn_to_ascii')) {
$string = idn_to_ascii($string, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
if (defined('IDNA_NONTRANSITIONAL_TO_ASCII') && defined('INTL_IDNA_VARIANT_UTS46')) {
$string = idn_to_ascii($string, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
} else {
$string = idn_to_ascii($string);
}
// If we have Net_IDNA2 support, we can support IRIs by
// punycoding them. (This is the most portable thing to do,

View File

@ -220,15 +220,25 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('auto'))
new HTMLPurifier_AttrDef_Enum(array('auto', 'initial', 'inherit'))
)
);
$trusted_min_wh = new HTMLPurifier_AttrDef_CSS_Composite(
array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit'))
)
);
$trusted_max_wh = new HTMLPurifier_AttrDef_CSS_Composite(
array(
new HTMLPurifier_AttrDef_CSS_Length('0'),
new HTMLPurifier_AttrDef_CSS_Percentage(true),
new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit'))
)
);
$max = $config->get('CSS.MaxImgLength');
$this->info['min-width'] =
$this->info['max-width'] =
$this->info['min-height'] =
$this->info['max-height'] =
$this->info['width'] =
$this->info['height'] =
$max === null ?
@ -245,6 +255,38 @@ class HTMLPurifier_CSSDefinition extends HTMLPurifier_Definition
// For everyone else:
$trusted_wh
);
$this->info['min-width'] =
$this->info['min-height'] =
$max === null ?
$trusted_min_wh :
new HTMLPurifier_AttrDef_Switch(
'img',
// For img tags:
new HTMLPurifier_AttrDef_CSS_Composite(
array(
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
new HTMLPurifier_AttrDef_Enum(array('initial', 'inherit'))
)
),
// For everyone else:
$trusted_min_wh
);
$this->info['max-width'] =
$this->info['max-height'] =
$max === null ?
$trusted_max_wh :
new HTMLPurifier_AttrDef_Switch(
'img',
// For img tags:
new HTMLPurifier_AttrDef_CSS_Composite(
array(
new HTMLPurifier_AttrDef_CSS_Length('0', $max),
new HTMLPurifier_AttrDef_Enum(array('none', 'initial', 'inherit'))
)
),
// For everyone else:
$trusted_max_wh
);
$this->info['text-decoration'] = new HTMLPurifier_AttrDef_CSS_TextDecoration();

View File

@ -21,7 +21,7 @@ class HTMLPurifier_Config
* HTML Purifier's version
* @type string
*/
public $version = '4.10.0';
public $version = '4.11.0';
/**
* Whether or not to automatically finalize
@ -890,7 +890,7 @@ class HTMLPurifier_Config
// zip(tail(trace), trace) -- but PHP is not Haskell har har
for ($i = 0, $c = count($trace); $i < $c - 1; $i++) {
// XXX this is not correct on some versions of HTML Purifier
if ($trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
if (isset($trace[$i + 1]['class']) && $trace[$i + 1]['class'] === 'HTMLPurifier_Config') {
continue;
}
$frame = $trace[$i];

View File

@ -100,7 +100,7 @@ class HTMLPurifier_ConfigSchema
* @param string $key Name of directive
* @param mixed $default Default value of directive
* @param string $type Allowed type of the directive. See
* HTMLPurifier_DirectiveDef::$type for allowed values
* HTMLPurifier_VarParser::$types for allowed values
* @param bool $allow_null Whether or not to allow null values
*/
public function add($key, $default, $type, $allow_null)

View File

@ -6,7 +6,7 @@ DEFAULT: false
<p>
When enabled, HTML Purifier will treat any elements that contain only
non-breaking spaces as well as regular whitespace as empty, and remove
them when %AutoForamt.RemoveEmpty is enabled.
them when %AutoFormat.RemoveEmpty is enabled.
</p>
<p>
See %AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions for a list of elements

View File

@ -0,0 +1,12 @@
Core.AllowParseManyTags
TYPE: bool
DEFAULT: false
VERSION: 4.10.1
--DESCRIPTION--
<p>
This directive allows parsing of many nested tags.
If you set true, relaxes any hardcoded limit from the parser.
However, in that case it may cause a Dos attack.
Be careful when enabling it.
</p>
--# vim: et sw=4 sts=4

View File

@ -3,23 +3,154 @@ TYPE: hash
VERSION: 2.0.0
--DEFAULT--
array (
'maroon' => '#800000',
'red' => '#FF0000',
'orange' => '#FFA500',
'yellow' => '#FFFF00',
'olive' => '#808000',
'purple' => '#800080',
'fuchsia' => '#FF00FF',
'white' => '#FFFFFF',
'lime' => '#00FF00',
'green' => '#008000',
'navy' => '#000080',
'blue' => '#0000FF',
'aliceblue' => '#F0F8FF',
'antiquewhite' => '#FAEBD7',
'aqua' => '#00FFFF',
'teal' => '#008080',
'aquamarine' => '#7FFFD4',
'azure' => '#F0FFFF',
'beige' => '#F5F5DC',
'bisque' => '#FFE4C4',
'black' => '#000000',
'silver' => '#C0C0C0',
'blanchedalmond' => '#FFEBCD',
'blue' => '#0000FF',
'blueviolet' => '#8A2BE2',
'brown' => '#A52A2A',
'burlywood' => '#DEB887',
'cadetblue' => '#5F9EA0',
'chartreuse' => '#7FFF00',
'chocolate' => '#D2691E',
'coral' => '#FF7F50',
'cornflowerblue' => '#6495ED',
'cornsilk' => '#FFF8DC',
'crimson' => '#DC143C',
'cyan' => '#00FFFF',
'darkblue' => '#00008B',
'darkcyan' => '#008B8B',
'darkgoldenrod' => '#B8860B',
'darkgray' => '#A9A9A9',
'darkgrey' => '#A9A9A9',
'darkgreen' => '#006400',
'darkkhaki' => '#BDB76B',
'darkmagenta' => '#8B008B',
'darkolivegreen' => '#556B2F',
'darkorange' => '#FF8C00',
'darkorchid' => '#9932CC',
'darkred' => '#8B0000',
'darksalmon' => '#E9967A',
'darkseagreen' => '#8FBC8F',
'darkslateblue' => '#483D8B',
'darkslategray' => '#2F4F4F',
'darkslategrey' => '#2F4F4F',
'darkturquoise' => '#00CED1',
'darkviolet' => '#9400D3',
'deeppink' => '#FF1493',
'deepskyblue' => '#00BFFF',
'dimgray' => '#696969',
'dimgrey' => '#696969',
'dodgerblue' => '#1E90FF',
'firebrick' => '#B22222',
'floralwhite' => '#FFFAF0',
'forestgreen' => '#228B22',
'fuchsia' => '#FF00FF',
'gainsboro' => '#DCDCDC',
'ghostwhite' => '#F8F8FF',
'gold' => '#FFD700',
'goldenrod' => '#DAA520',
'gray' => '#808080',
'grey' => '#808080',
'green' => '#008000',
'greenyellow' => '#ADFF2F',
'honeydew' => '#F0FFF0',
'hotpink' => '#FF69B4',
'indianred' => '#CD5C5C',
'indigo' => '#4B0082',
'ivory' => '#FFFFF0',
'khaki' => '#F0E68C',
'lavender' => '#E6E6FA',
'lavenderblush' => '#FFF0F5',
'lawngreen' => '#7CFC00',
'lemonchiffon' => '#FFFACD',
'lightblue' => '#ADD8E6',
'lightcoral' => '#F08080',
'lightcyan' => '#E0FFFF',
'lightgoldenrodyellow' => '#FAFAD2',
'lightgray' => '#D3D3D3',
'lightgrey' => '#D3D3D3',
'lightgreen' => '#90EE90',
'lightpink' => '#FFB6C1',
'lightsalmon' => '#FFA07A',
'lightseagreen' => '#20B2AA',
'lightskyblue' => '#87CEFA',
'lightslategray' => '#778899',
'lightslategrey' => '#778899',
'lightsteelblue' => '#B0C4DE',
'lightyellow' => '#FFFFE0',
'lime' => '#00FF00',
'limegreen' => '#32CD32',
'linen' => '#FAF0E6',
'magenta' => '#FF00FF',
'maroon' => '#800000',
'mediumaquamarine' => '#66CDAA',
'mediumblue' => '#0000CD',
'mediumorchid' => '#BA55D3',
'mediumpurple' => '#9370DB',
'mediumseagreen' => '#3CB371',
'mediumslateblue' => '#7B68EE',
'mediumspringgreen' => '#00FA9A',
'mediumturquoise' => '#48D1CC',
'mediumvioletred' => '#C71585',
'midnightblue' => '#191970',
'mintcream' => '#F5FFFA',
'mistyrose' => '#FFE4E1',
'moccasin' => '#FFE4B5',
'navajowhite' => '#FFDEAD',
'navy' => '#000080',
'oldlace' => '#FDF5E6',
'olive' => '#808000',
'olivedrab' => '#6B8E23',
'orange' => '#FFA500',
'orangered' => '#FF4500',
'orchid' => '#DA70D6',
'palegoldenrod' => '#EEE8AA',
'palegreen' => '#98FB98',
'paleturquoise' => '#AFEEEE',
'palevioletred' => '#DB7093',
'papayawhip' => '#FFEFD5',
'peachpuff' => '#FFDAB9',
'peru' => '#CD853F',
'pink' => '#FFC0CB',
'plum' => '#DDA0DD',
'powderblue' => '#B0E0E6',
'purple' => '#800080',
'rebeccapurple' => '#663399',
'red' => '#FF0000',
'rosybrown' => '#BC8F8F',
'royalblue' => '#4169E1',
'saddlebrown' => '#8B4513',
'salmon' => '#FA8072',
'sandybrown' => '#F4A460',
'seagreen' => '#2E8B57',
'seashell' => '#FFF5EE',
'sienna' => '#A0522D',
'silver' => '#C0C0C0',
'skyblue' => '#87CEEB',
'slateblue' => '#6A5ACD',
'slategray' => '#708090',
'slategrey' => '#708090',
'snow' => '#FFFAFA',
'springgreen' => '#00FF7F',
'steelblue' => '#4682B4',
'tan' => '#D2B48C',
'teal' => '#008080',
'thistle' => '#D8BFD8',
'tomato' => '#FF6347',
'turquoise' => '#40E0D0',
'violet' => '#EE82EE',
'wheat' => '#F5DEB3',
'white' => '#FFFFFF',
'whitesmoke' => '#F5F5F5',
'yellow' => '#FFFF00',
'yellowgreen' => '#9ACD32'
)
--DESCRIPTION--

View File

@ -118,7 +118,7 @@ class HTMLPurifier_EntityParser
$entity = $matches[0];
$hex_part = @$matches[1];
$dec_part = @$matches[2];
$named_part = empty($matches[3]) ? @$matches[4] : $matches[3];
$named_part = empty($matches[3]) ? (empty($matches[4]) ? "" : $matches[4]) : $matches[3];
if ($hex_part !== NULL && $hex_part !== "") {
return HTMLPurifier_Encoder::unichr(hexdec($hex_part));
} elseif ($dec_part !== NULL && $dec_part !== "") {

View File

@ -23,13 +23,13 @@ class HTMLPurifier_HTMLModule_SafeScripting extends HTMLPurifier_HTMLModule
$script = $this->addElement(
'script',
'Inline',
'Empty',
'Optional:', // Not `Empty` to not allow to autoclose the <script /> tag @see https://www.w3.org/TR/html4/interact/scripts.html
null,
array(
// While technically not required by the spec, we're forcing
// it to this value.
'type' => 'Enum#text/javascript',
'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed))
'src*' => new HTMLPurifier_AttrDef_Enum(array_keys($allowed), /*case sensitive*/ true)
)
);
$script->attr_transform_pre[] =

View File

@ -8,4 +8,6 @@ $messages = array(
'HTMLPurifier' => 'HTML Purifier X'
);
$errorNames = array();
// vim: et sw=4 sts=4

View File

@ -9,4 +9,6 @@ $messages = array(
'HTMLPurifier' => 'HTML Purifier XNone'
);
$errorNames = array();
// vim: et sw=4 sts=4

View File

@ -68,8 +68,13 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
$doc = new DOMDocument();
$doc->encoding = 'UTF-8'; // theoretically, the above has this covered
$options = 0;
if ($config->get('Core.AllowParseManyTags') && defined('LIBXML_PARSEHUGE')) {
$options |= LIBXML_PARSEHUGE;
}
set_error_handler(array($this, 'muteErrorHandler'));
$doc->loadHTML($html);
$doc->loadHTML($html, $options);
restore_error_handler();
$body = $doc->getElementsByTagName('html')->item(0)-> // <html>
@ -133,11 +138,11 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
*/
protected function getTagName($node)
{
if (property_exists($node, 'tagName')) {
if (isset($node->tagName)) {
return $node->tagName;
} else if (property_exists($node, 'nodeName')) {
} else if (isset($node->nodeName)) {
return $node->nodeName;
} else if (property_exists($node, 'localName')) {
} else if (isset($node->localName)) {
return $node->localName;
}
return null;
@ -150,11 +155,11 @@ class HTMLPurifier_Lexer_DOMLex extends HTMLPurifier_Lexer
*/
protected function getData($node)
{
if (property_exists($node, 'data')) {
if (isset($node->data)) {
return $node->data;
} else if (property_exists($node, 'nodeValue')) {
} else if (isset($node->nodeValue)) {
return $node->nodeValue;
} else if (property_exists($node, 'textContent')) {
} else if (isset($node->textContent)) {
return $node->textContent;
}
return null;

View File

@ -48,7 +48,7 @@ class HTMLPurifier_Printer_ConfigForm extends HTMLPurifier_Printer
$this->compress = $compress;
// initialize sub-printers
$this->fields[0] = new HTMLPurifier_Printer_ConfigForm_default();
$this->fields[HTMLPurifier_VarParser::BOOL] = new HTMLPurifier_Printer_ConfigForm_bool();
$this->fields[HTMLPurifier_VarParser::C_BOOL] = new HTMLPurifier_Printer_ConfigForm_bool();
}
/**
@ -339,7 +339,7 @@ class HTMLPurifier_Printer_ConfigForm_default extends HTMLPurifier_Printer
$value = '';
}
}
if ($type === HTMLPurifier_VarParser::MIXED) {
if ($type === HTMLPurifier_VarParser::C_MIXED) {
return 'Not supported';
$value = serialize($value);
}

View File

@ -7,34 +7,34 @@
class HTMLPurifier_VarParser
{
const STRING = 1;
const C_STRING = 1;
const ISTRING = 2;
const TEXT = 3;
const ITEXT = 4;
const INT = 5;
const FLOAT = 6;
const BOOL = 7;
const C_INT = 5;
const C_FLOAT = 6;
const C_BOOL = 7;
const LOOKUP = 8;
const ALIST = 9;
const HASH = 10;
const MIXED = 11;
const C_MIXED = 11;
/**
* Lookup table of allowed types. Mainly for backwards compatibility, but
* also convenient for transforming string type names to the integer constants.
*/
public static $types = array(
'string' => self::STRING,
'string' => self::C_STRING,
'istring' => self::ISTRING,
'text' => self::TEXT,
'itext' => self::ITEXT,
'int' => self::INT,
'float' => self::FLOAT,
'bool' => self::BOOL,
'int' => self::C_INT,
'float' => self::C_FLOAT,
'bool' => self::C_BOOL,
'lookup' => self::LOOKUP,
'list' => self::ALIST,
'hash' => self::HASH,
'mixed' => self::MIXED
'mixed' => self::C_MIXED
);
/**
@ -42,7 +42,7 @@ class HTMLPurifier_VarParser
* allowed value lists.
*/
public static $stringTypes = array(
self::STRING => true,
self::C_STRING => true,
self::ISTRING => true,
self::TEXT => true,
self::ITEXT => true,
@ -74,7 +74,7 @@ class HTMLPurifier_VarParser
// These are basic checks, to make sure nothing horribly wrong
// happened in our implementations.
switch ($type) {
case (self::STRING):
case (self::C_STRING):
case (self::ISTRING):
case (self::TEXT):
case (self::ITEXT):
@ -85,17 +85,17 @@ class HTMLPurifier_VarParser
$var = strtolower($var);
}
return $var;
case (self::INT):
case (self::C_INT):
if (!is_int($var)) {
break;
}
return $var;
case (self::FLOAT):
case (self::C_FLOAT):
if (!is_float($var)) {
break;
}
return $var;
case (self::BOOL):
case (self::C_BOOL):
if (!is_bool($var)) {
break;
}
@ -119,7 +119,7 @@ class HTMLPurifier_VarParser
}
}
return $var;
case (self::MIXED):
case (self::C_MIXED):
return $var;
default:
$this->errorInconsistent(get_class($this), $type);

View File

@ -23,23 +23,23 @@ class HTMLPurifier_VarParser_Flexible extends HTMLPurifier_VarParser
// Note: if code "breaks" from the switch, it triggers a generic
// exception to be thrown. Specific errors can be specifically
// done here.
case self::MIXED:
case self::C_MIXED:
case self::ISTRING:
case self::STRING:
case self::C_STRING:
case self::TEXT:
case self::ITEXT:
return $var;
case self::INT:
case self::C_INT:
if (is_string($var) && ctype_digit($var)) {
$var = (int)$var;
}
return $var;
case self::FLOAT:
case self::C_FLOAT:
if ((is_string($var) && is_numeric($var)) || is_int($var)) {
$var = (float)$var;
}
return $var;
case self::BOOL:
case self::C_BOOL:
if (is_int($var) && ($var === 0 || $var === 1)) {
$var = (bool)$var;
} elseif (is_string($var)) {

View File

@ -1 +1,7 @@
Deny from all
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Deny from all
</ifModule>

View File

@ -1,30 +0,0 @@
#!/usr/bin/php
<?php
chdir(dirname(__FILE__));
require_once 'common.php';
assertCli();
/**
* @file
* Runs all generation/flush cache scripts to ensure that somewhat volatile
* generated files are up-to-date.
*/
function e($cmd)
{
echo "\$ $cmd\n";
passthru($cmd, $status);
echo "\n";
if ($status) exit($status);
}
$php = empty($_SERVER['argv'][1]) ? 'php' : $_SERVER['argv'][1];
e($php . ' generate-includes.php');
e($php . ' generate-schema-cache.php');
e($php . ' flush-definition-cache.php');
e($php . ' generate-standalone.php');
e($php . ' config-scanner.php');
// vim: et sw=4 sts=4

View File

@ -0,0 +1,8 @@
#!/bin/bash
set -ex
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
php "$DIR/generate-includes.php"
php "$DIR/generate-schema-cache.php"
php "$DIR/flush-definition-cache.php"
php "$DIR/generate-standalone.php"
php "$DIR/config-scanner.php"

View File

@ -1,34 +0,0 @@
#!/usr/bin/php
<?php
chdir(dirname(__FILE__));
require_once 'common.php';
assertCli();
/**
* @file
* Converts all instances of $config->set and $config->get to the new
* format, as described by docs/dev-config-bcbreaks.txt
*/
$FS = new FSTools();
chdir(dirname(__FILE__) . '/..');
$raw_files = $FS->globr('.', '*.php');
foreach ($raw_files as $file) {
$file = substr($file, 2); // rm leading './'
if (strpos($file, 'library/standalone/') === 0) continue;
if (strpos($file, 'maintenance/update-config.php') === 0) continue;
if (strpos($file, 'test-settings.php') === 0) continue;
if (substr_count($file, '.') > 1) continue; // rm meta files
// process the file
$contents = file_get_contents($file);
$contents = preg_replace(
"#config->(set|get)\('(.+?)', '(.+?)'#",
"config->\\1('\\2.\\3'",
$contents
);
if ($contents === '') continue;
file_put_contents($file, $contents);
}
// vim: et sw=4 sts=4

View File

@ -53,5 +53,6 @@ $config->set('Core.Encoding', $GLOBALS['PHORUM']['DATA']['CHARSET']); // we'll c
if (strtolower($GLOBALS['PHORUM']['DATA']['CHARSET']) !== 'utf-8') {
$config->set('Core.EscapeNonASCIICharacters', true);
}
$config->set('Core.AllowParseManyTags', false);
// vim: et sw=4 sts=4

View File

@ -1,22 +0,0 @@
<?php
// Tags releases
if (php_sapi_name() != 'cli') {
echo 'Release script cannot be called from web-browser.';
exit;
}
require 'svn.php';
$svn_info = my_svn_info('.');
$version = trim(file_get_contents('VERSION'));
$trunk_url = $svn_info['Repository Root'] . '/htmlpurifier/trunk';
$trunk_tag_url = $svn_info['Repository Root'] . '/htmlpurifier/tags/' . $version;
echo "Tagging trunk to tags/$version...";
passthru("svn copy --message \"Tag $version release.\" $trunk_url $trunk_tag_url");
// vim: et sw=4 sts=4

View File

@ -102,7 +102,7 @@ if (!$c) {
}
file_put_contents('library/HTMLPurifier/Config.php', $config_c);
passthru('php maintenance/flush.php');
passthru('maintenance/flush.sh');
if ($is_dev) echo "Review changes, write something in WHATSNEW and FOCUS, and then commit with log 'Release $version.'" . PHP_EOL;
else echo "Numbers updated to dev, no other modifications necessary!";

View File

@ -0,0 +1 @@
patreon: colinodell

View File

@ -0,0 +1,18 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 90
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 30
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- on hold
- security
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View File

@ -4,6 +4,14 @@ Updates should follow the [Keep a CHANGELOG](http://keepachangelog.com/) princip
## [Unreleased][unreleased]
## [4.8.2] - 2019-08-02
### Fixed
- Fixed headers not being placed onto a new line in some cases (#172)
- Fixed handling of links containing spaces (#175)
### Removed
- Removed support for HHVM
## [4.8.1] - 2018-12-24
### Added
- Added support for PHP 7.3
@ -243,7 +251,8 @@ not ideally set, so this releases fixes that. Moving forwards this should reduce
### Added
- Initial release
[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.1...master
[unreleased]: https://github.com/thephpleague/html-to-markdown/compare/4.8.2...master
[4.8.2]: https://github.com/thephpleague/html-to-markdown/compare/4.8.1...4.8.2
[4.8.1]: https://github.com/thephpleague/html-to-markdown/compare/4.8.0...4.8.1
[4.8.0]: https://github.com/thephpleague/html-to-markdown/compare/4.7.0...4.8.0
[4.7.0]: https://github.com/thephpleague/html-to-markdown/compare/4.6.2...4.7.0

View File

@ -35,7 +35,7 @@ class HeaderConverter implements ConverterInterface, ConfigurationAwareInterface
$style = $this->config->getOption('header_style', self::STYLE_SETEXT);
if (strlen($element->getValue()) === 0) {
return '';
return "\n";
}
if (($level === 1 || $level === 2) && !$element->isDescendantOf('blockquote') && $style === self::STYLE_SETEXT) {

View File

@ -24,6 +24,9 @@ class LinkConverter implements ConverterInterface
} elseif ($href === 'mailto:' . $text && $this->isValidEmail($text)) {
$markdown = '<' . $text . '>';
} else {
if (stristr($href, ' ')) {
$href = '<'.$href.'>';
}
$markdown = '[' . $text . '](' . $href . ')';
}

View File

@ -33,7 +33,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*
* @package SimplePie
* @version 1.5.2
* @version 1.5.3
* @copyright 2004-2017 Ryan Parman, Geoffrey Sneddon, Ryan McCue
* @author Ryan Parman
* @author Geoffrey Sneddon
@ -50,7 +50,7 @@ define('SIMPLEPIE_NAME', 'SimplePie');
/**
* SimplePie Version
*/
define('SIMPLEPIE_VERSION', '1.5.2');
define('SIMPLEPIE_VERSION', '1.5.3');
/**
* SimplePie Build

View File

@ -101,7 +101,7 @@ class SimplePie_Cache_File implements SimplePie_Cache_Base
*/
public function save($data)
{
if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
if (file_exists($this->name) && is_writable($this->name) || file_exists($this->location) && is_writable($this->location))
{
if ($data instanceof SimplePie)
{

View File

@ -402,7 +402,7 @@ class SimplePie_Locator
{
break;
}
if (preg_match('/(rss|rdf|atom|xml)/i', $value))
if (preg_match('/(feed|rss|rdf|atom|xml)/i', $value))
{
$this->checked_feeds++;
$headers = array(

View File

@ -145,6 +145,14 @@ class SimplePie_Parse_Date
'Παρ' => 5,
'Σαβ' => 6,
'Κυρ' => 7,
// Russian
'Пн.' => 1,
'Вт.' => 2,
'Ср.' => 3,
'Чт.' => 4,
'Пт.' => 5,
'Сб.' => 6,
'Вс.' => 7,
);
/**
@ -289,7 +297,33 @@ class SimplePie_Parse_Date
'Σεπ' => 9,
'Οκτ' => 10,
'Νοέ' => 11,
'Δεκ' => 12,
'Δεκ' => 12,
// Russian
'Янв' => 1,
'января' => 1,
'Фев' => 2,
'февраля' => 2,
'Мар' => 3,
'марта' => 3,
'Апр' => 4,
'апреля' => 4,
'Май' => 5,
'мая' => 5,
'Июн' => 6,
'июня' => 6,
'Июл' => 7,
'июля' => 7,
'Авг' => 8,
'августа' => 8,
'Сен' => 9,
'сентября' => 9,
'Окт' => 10,
'октября' => 10,
'Ноя' => 11,
'ноября' => 11,
'Дек' => 12,
'декабря' => 12,
);
/**
@ -541,8 +575,8 @@ class SimplePie_Parse_Date
*/
public function __construct()
{
$this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
$this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
$this->day_pcre = '(' . implode('|', array_keys($this->day)) . ')';
$this->month_pcre = '(' . implode('|', array_keys($this->month)) . ')';
static $cache;
if (!isset($cache[get_class($this)]))
@ -690,7 +724,7 @@ class SimplePie_Parse_Date
}
// Convert the number of seconds to an integer, taking decimals into account
$second = round((int)$match[6] + (int)$match[7] / pow(10, strlen($match[7])));
$second = round((int)$match[6] + (int)$match[7] / (10 ** strlen($match[7])));
return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
}

View File

@ -1146,8 +1146,8 @@ function doreply(parent, ident, owner, hint) {
var i = form.find('button[type=submit]');
var btn = i.html().replace(/<[^>]*>/g, '').trim();
i.html('<i class="fa fa-reply" ></i> ' + btn);
i.prop('title', hint);
form.find('textarea').val("@{" + owner + "} ");
var sel = 'wall-item-body-' + ident.toString();
form.find('textarea').val("@{" + owner + "}" + (($(window.getSelection().anchorNode).closest("#" + sel).attr("id") != sel) ? " " : "\n[quote]" + window.getSelection().toString() + "[/quote]\n"));
$('#comment-edit-text-' + parent.toString()).focus();
}

View File

@ -20,7 +20,7 @@
{{/if}}
{{if $item.title && !$item.event}}
<div class="p-2{{if $item.is_new}} bg-primary text-white{{/if}} wall-item-title h3{{if !$item.photo}} rounded-top{{/if}}" id="wall-item-title-{{$item.id}}">
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})" rel="nofollow">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
</div>
{{if ! $item.is_new}}
<hr class="m-0">

View File

@ -20,7 +20,7 @@
{{/if}}
{{if $item.title && !$item.event}}
<div class="p-2{{if $item.is_new}} bg-primary text-white{{/if}} wall-item-title h3{{if !$item.photo}} rounded-top{{/if}}" id="wall-item-title-{{$item.id}}">
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
{{if $item.title_tosource}}{{if $item.plink}}<a href="{{$item.plink.href}}" title="{{$item.title}} ({{$item.plink.title}})" rel="nofollow">{{/if}}{{/if}}{{$item.title}}{{if $item.title_tosource}}{{if $item.plink}}</a>{{/if}}{{/if}}
</div>
{{if ! $item.is_new}}
<hr class="m-0">

View File

@ -8,7 +8,7 @@
<ul class="pmenu-body{{if $wrap || !$class}} nav nav-pills flex-column{{elseif !$wrap || $class}} {{$class}}{{/if}}">
{{foreach $items as $mitem }}
<li id="pmenu-item-{{$mitem.mitem_id}}" class="nav-item pmenu-item{{if $mitem.submenu}} dropdown{{/if}}">
<a href="{{if $mitem.submenu}}#{{else}}{{$mitem.mitem_link}}{{/if}}" class="nav-link {{if $mitem.submenu}} dropdown-toggle{{/if}}"{{if $mitem.submenu}} data-toggle="dropdown"{{/if}}{{if $mitem.newwin}}target="_blank"{{/if}}>{{$mitem.mitem_desc}}{{if $mitem.submenu}}<span class="caret"></span>{{/if}}</a>
<a href="{{if $mitem.submenu}}#{{else}}{{$mitem.mitem_link}}{{/if}}" class="nav-link {{if $mitem.submenu}} dropdown-toggle{{/if}}"{{if $mitem.submenu}} data-toggle="dropdown"{{/if}}{{if $mitem.newwin}}target="_blank"{{/if}} rel="nofollow noopener">{{$mitem.mitem_desc}}{{if $mitem.submenu}}<span class="caret"></span>{{/if}}</a>
{{if $mitem.submenu}}{{$mitem.submenu}}{{/if}}
</li>
{{/foreach }}

View File

@ -1,7 +1,7 @@
<div id="vcard" class="vcard h-card">
<div id="profile-photo-wrapper"><a href="{{$link}}"><img class="vcard-photo photo u-photo" src="{{$photo}}" alt="{{$name}}" /></a></div>
{{if $connect}}
<div class="connect-btn-wrapper"><a href="follow?f=&url={{$follow}}" class="btn btn-block btn-success btn-sm"><i class="fa fa-plus"></i> {{$connect}}</a></div>
<div class="connect-btn-wrapper"><a href="follow?f=&url={{$follow}}" class="btn btn-block btn-success btn-sm" rel="nofollow"><i class="fa fa-plus"></i> {{$connect}}</a></div>
{{/if}}
<div class="fn p-name">{{$name}}</div>
</div>