diff --git a/.homeinstall/README.md b/.homeinstall/README.md
index aeecb9184..d63931a84 100644
--- a/.homeinstall/README.md
+++ b/.homeinstall/README.md
@@ -5,8 +5,8 @@ Run hubzilla-setup.sh for an unattended installation of hubzilla.
The script is known to work without adjustments with
+ Hardware
- - Mini-PC with Debian-9.2-amd64, or
- - Rapberry 3 with Raspbian, Debian-9.3
+ - Mini-PC with Debian-9.5-amd64, or
+ - Rapberry 3 with Raspbian, Debian-9.5
+ DynDNS
- selfHOST.de
- freedns.afraid.org
@@ -38,7 +38,7 @@ Software
- apt-get install git
- mkdir -p /var/www
- cd /var/www
- - git clone https://github.com/redmatrix/hubzilla.git html
+ - git clone https://framagit.org/hubzilla/core.git html
- cd html/.homeinstall
- cp hubzilla-config.txt.template hubzilla-config.txt
- nano hubzilla-config.txt
@@ -100,7 +100,7 @@ Create bootable USB drive with Debian on it.You could use
Example for command dd...
su -
- dd if=2017-11-29-raspbian-stretch.img of=/dev/mmcblk0
+ dd if=2018-10-09-raspbian-stretch.img of=/dev/mmcblk0
Do not forget to unmount the SD card before and check if unmounted like in this example...
@@ -164,7 +164,7 @@ Make the directory for apache and change diretory to it
Clone hubzilla from git ("git pull" will update it later)
- git clone https://framagit.org/hubzilla/core html
+ git clone https://framagit.org/hubzilla/core.git html
Change to the install script
@@ -217,14 +217,20 @@ After the daily script was executed at 05:30 (am)
- optionally view the daily log under yourdomain.org/admin/logs/
- set the logfile to var/www/html/hubzilla-daily.log
+
+## Install Hubzilla in a Virtual Machine for Test Purposes
+
+Modify the file "hubzilla-config.txt".
+
+ nano hubzilla-config.txt
+
+There use
+
+ le_domain=localhost
+
## Note for the Rasperry
-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...
-
- sudo apt-get purge wolfram-engine sonic-pi
- sudo apt-get autoremove
+The script was tested with an Raspberry 3 under Raspian (Debian 9.5, 2018-10-09-raspbian-stretch.img).
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
@@ -234,7 +240,7 @@ to boot the Rapsi to the client console.
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
-On a Raspian Stretch (Debian 9) the validation of the mail address fails for the very first user.
+If the validation of the mail address fails for the very first registered 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
diff --git a/.homeinstall/hubzilla-config.txt.template b/.homeinstall/hubzilla-config.txt.template
index 2776ccd27..e42da0e4e 100644
--- a/.homeinstall/hubzilla-config.txt.template
+++ b/.homeinstall/hubzilla-config.txt.template
@@ -18,6 +18,8 @@ db_pass=
# Example: my.cooldomain.org
# Example: cooldomain.org
#
+# Example: localhost (test installation without certificates for httpS)
+#
# Email is optional
#
#
diff --git a/.homeinstall/hubzilla-setup.sh b/.homeinstall/hubzilla-setup.sh
index ff101086c..1f3ad5db5 100755
--- a/.homeinstall/hubzilla-setup.sh
+++ b/.homeinstall/hubzilla-setup.sh
@@ -816,15 +816,35 @@ install_run_selfhost
ping_domain
configure_cron_freedns
configure_cron_selfhost
-install_letsencrypt
-configure_apache_for_https
-check_https
+
+if [ "$le_domain" != "localhost" ]
+then
+ install_letsencrypt
+ configure_apache_for_https
+ check_https
+else
+ print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
+fi
+
install_hubzilla
-rewrite_to_https
-install_rsnapshot
+
+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
-install_cryptosetup
-write_uninstall_script
+
+if [ "$le_domain" != "localhost" ]
+then
+ install_cryptosetup
+ write_uninstall_script
+else
+ print_info "is localhost - skipped installation of cryptosetup"
+fi
#set +x # stop debugging from here
diff --git a/CHANGELOG b/CHANGELOG
index 59e8bdfc9..444c7b2e4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,30 @@
+Hubzilla 3.8.6 (2018-12-03)
+ - Prevent incompatible export files (osada/zap) from being imported
+ - Catch exception if readImageBlob() receives bogus data
+ - Streamline PDF previews
+ - Allow notification filtering by name or address
+ - Fix too restrictive attached photo permissions
+ - Update ES translation
+ - Use flex for the default template
+ - Do not store serialized pconfig value received via to Module/Pconfig.php
+ - Update jquery-file-upload lib and move to composer
+ - Update imagesloaded lib and move to composer
+ - Fix activitypub tag notifications
+ - Fix call to undefined function in PConfig
+ - Fix typo which prevented propagation of comments to zot6 (dev)
+ - Activitypub: add support for pterotype (wordpress plugin)
+ - Openstreetmap: check validity of lat+lon before rendering a map
+
+
+Hubzilla 3.8.5 (2018-11-19)
+ - Fix pconfig for new installs
+ - Fix delayed publication of posts in combination with channel clones
+ - Fix issue where photo filesize was not updated in the DB when a photo was edited
+ - Fix issue where the original photo size was not set correct in the DB
+ - Fix delivery issue in zot_fetch()
+ - Fix typo in channel reputation addon
+
+
Hubzilla 3.8.4 (2018-11-14)
- Fix xss issue (thanks to Eduardo)
- Implement hook in enotify to be used by superblock
diff --git a/Zotlabs/Daemon/Cron.php b/Zotlabs/Daemon/Cron.php
index 25e49b817..8b6b42c8a 100644
--- a/Zotlabs/Daemon/Cron.php
+++ b/Zotlabs/Daemon/Cron.php
@@ -94,6 +94,29 @@ class Cron {
@time_sleep_until(microtime(true) + (float) $interval);
}
}
+
+ // Clean expired photos from cache
+
+ $age = get_config('system','active_expire_days', '30');
+ $r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
+ intval(PHOTO_CACHE),
+ db_utcnow(),
+ db_quoteinterval($age . ' DAY')
+ );
+ if($r) {
+ foreach($r as $rr) {
+ $file = dbunescbin($rr['content']);
+ if(is_file($file)) {
+ @unlink($file);
+ logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG);
+ }
+ }
+ }
+ q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
+ intval(PHOTO_CACHE),
+ db_utcnow(),
+ db_quoteinterval($age . ' DAY')
+ );
// publish any applicable items that were set to be published in the future
// (time travel posts). Restrict to items that have come of age in the last
diff --git a/Zotlabs/Lib/Enotify.php b/Zotlabs/Lib/Enotify.php
index 523ccf93a..5e5798cac 100644
--- a/Zotlabs/Lib/Enotify.php
+++ b/Zotlabs/Lib/Enotify.php
@@ -828,7 +828,7 @@ class Enotify {
$x = array(
'notify_link' => $item['llink'],
'name' => $item['author']['xchan_name'],
- 'addr' => $item['author']['xchan_addr'],
+ 'addr' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
'url' => $item['author']['xchan_url'],
'photo' => $item['author']['xchan_photo_s'],
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
diff --git a/Zotlabs/Module/Pconfig.php b/Zotlabs/Module/Pconfig.php
index 44fe5d9a9..f31d5fdf6 100644
--- a/Zotlabs/Module/Pconfig.php
+++ b/Zotlabs/Module/Pconfig.php
@@ -22,6 +22,11 @@ class Pconfig extends \Zotlabs\Web\Controller {
$k = trim(escape_tags($_POST['k']));
$v = trim($_POST['v']);
$aj = intval($_POST['aj']);
+
+ // Do not store "serialized" data received in the $_POST
+ if (preg_match('|^a:[0-9]+:{.*}$|s',$v) || preg_match('O:8:"stdClass":[0-9]+:{.*}$|s',$v)) {
+ return;
+ }
if(in_array(argv(2),$this->disallowed_pconfig())) {
notice( t('This setting requires special processing and editing has been blocked.') . EOL);
diff --git a/Zotlabs/Module/Photo.php b/Zotlabs/Module/Photo.php
index 30e8340e2..d85db7307 100644
--- a/Zotlabs/Module/Photo.php
+++ b/Zotlabs/Module/Photo.php
@@ -1,19 +1,20 @@
get_config('system','photo_cache_enable', 0),
+ 'age' => 86400,
+ 'exp' => true,
+ 'leak' => false
+ );
+ call_hooks('cache_mode_hook', $cache_mode);
+
$observer_xchan = get_observer_hash();
$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
@@ -106,13 +115,14 @@ class Photo extends \Zotlabs\Web\Controller {
License link: http://creativecommons.org/licenses/by/3.0/
*/
+ // @FIXME It seems this part doesn't work because we are not setting such cookie
$cookie_value = false;
if (isset($_COOKIE['devicePixelRatio'])) {
$cookie_value = intval($_COOKIE['devicePixelRatio']);
}
else {
// Force revalidation of cache on next request
- $cache_directive = 'no-cache';
+ // $prvcachecontrol = 'no-cache';
$status = 'no cookie';
}
@@ -129,27 +139,43 @@ class Photo extends \Zotlabs\Web\Controller {
$resolution = 1;
}
- $r = q("SELECT uid, photo_usage FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
+ $r = q("SELECT uid, photo_usage, expires, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
dbesc($photo),
intval($resolution)
);
if($r) {
-
$allowed = (-1);
- if(intval($r[0]['photo_usage'])) {
+ $u = intval($r[0]['photo_usage']);
+ if($u) {
$allowed = 1;
- if(intval($r[0]['photo_usage']) === PHOTO_COVER)
+ if($u === PHOTO_COVER)
if($resolution < PHOTO_RES_COVER_1200)
$allowed = (-1);
- if(intval($r[0]['photo_usage']) === PHOTO_PROFILE)
+ if($u === PHOTO_PROFILE)
if(! in_array($resolution,[4,5,6]))
$allowed = (-1);
+ if($u === PHOTO_CACHE) {
+ // Cached image leak protection
+ if(! (local_channel() || $cache_mode['leak'])) {
+ header("Location: " . $r[0]['display_path']);
+ killme();
+ }
+ // Revalidate cache
+ if($cache_mode['on'] && strtotime($r[0]['expires']) - 60 < time()) {
+ $cache = array(
+ 'url' => $r[0]['display_path'],
+ 'uid' => $r[0]['uid']
+ );
+ call_hooks('cache_url_hook', $cache);
+ if(! $cache['status'])
+ http_status_exit(404,'not found');
+ }
+ }
}
- if($allowed === (-1)) {
+ if($allowed === (-1))
$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo);
- }
$channel = channelx_by_n($r[0]['uid']);
@@ -160,16 +186,19 @@ class Photo extends \Zotlabs\Web\Controller {
);
$exists = (($e) ? true : false);
-
+
if($exists && $allowed) {
+ $expires = strtotime($e[0]['expires'] . 'Z');
$data = dbunescbin($e[0]['content']);
$filesize = $e[0]['filesize'];
$mimetype = $e[0]['mimetype'];
$modified = strtotime($e[0]['edited'] . 'Z');
- if(intval($e[0]['os_storage']))
+
+ if(intval($e[0]['os_storage'])) {
$streaming = $data;
+ }
if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '')
- $prvcachecontrol = true;
+ $prvcachecontrol = 'no-store, no-cache, must-revalidate';
}
else {
if(! $allowed) {
@@ -180,9 +209,9 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
- } else {
+ }
+ else
http_status_exit(404,'not found');
- }
}
header_remove('Pragma');
@@ -225,24 +254,14 @@ class Photo extends \Zotlabs\Web\Controller {
$mimetype = $ph->getType();
}
}
-
- // @FIXME Seems never invoked
- // Writing in cachefile
- if (isset($cachefile) && $cachefile != '') {
- file_put_contents($cachefile, $data);
- $modified = filemtime($cachefile);
- }
-
- header("Content-type: " . $mimetype);
-
- if($prvcachecontrol) {
+ if(isset($prvcachecontrol)) {
// it is a private photo that they have no permission to view.
// tell the browser not to cache it, in case they authenticate
// and subsequently have permission to see it
- header("Cache-Control: no-store, no-cache, must-revalidate");
+ header("Cache-Control: " . $prvcachecontrol);
}
else {
@@ -255,18 +274,23 @@ class Photo extends \Zotlabs\Web\Controller {
// This has performance considerations but we highly recommend you
// leave it alone.
- $cache = get_config('system','photo_cache_time', 86400); // 1 day by default
+ $maxage = $cache_mode['age'];
- header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
- header("Cache-Control: max-age=" . $cache);
+ if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time()))
+ $expires = time() + $maxage;
+ else
+ $maxage = $expires - time();
+
+ header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT");
+ header("Cache-Control: max-age=" . $maxage);
}
+ header("Content-type: " . $mimetype);
header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT");
header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data)));
// If it's a file resource, stream it.
-
if($streaming && $channel) {
if(strpos($streaming,'store') !== false)
$istream = fopen($streaming,'rb');
diff --git a/Zotlabs/Module/Photos.php b/Zotlabs/Module/Photos.php
index 03fd8a53d..21f6293ef 100644
--- a/Zotlabs/Module/Photos.php
+++ b/Zotlabs/Module/Photos.php
@@ -264,7 +264,7 @@ class Photos extends \Zotlabs\Web\Controller {
}
$x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
- dbesc(datetime_convert()),
+ dbesc(datetime_convert()),
dbescbin($data),
intval($fsize),
intval($height),
@@ -278,10 +278,13 @@ class Photos extends \Zotlabs\Web\Controller {
$width = $ph->getWidth();
$height = $ph->getHeight();
+ $data = $ph->imageString();
+ $fsize = strlen($data);
- $x = q("update photo set edited = '%s', content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
- dbesc(datetime_convert()),
- dbescbin($ph->imageString()),
+ $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
+ dbesc(datetime_convert()),
+ dbescbin($data),
+ intval($fsize),
intval($height),
intval($width),
dbesc($resource_id),
@@ -294,10 +297,13 @@ class Photos extends \Zotlabs\Web\Controller {
$width = $ph->getWidth();
$height = $ph->getHeight();
+ $data = $ph->imageString();
+ $fsize = strlen($data);
- $x = q("update photo set edited = '%s', content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
- dbesc(datetime_convert()),
- dbescbin($ph->imageString()),
+ $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
+ dbesc(datetime_convert()),
+ dbescbin($data),
+ intval($fsize),
intval($height),
intval($width),
dbesc($resource_id),
@@ -310,10 +316,13 @@ class Photos extends \Zotlabs\Web\Controller {
$width = $ph->getWidth();
$height = $ph->getHeight();
+ $data = $ph->imageString();
+ $fsize = strlen($data);
- $x = q("update photo set edited = '%s', content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
- dbesc(datetime_convert()),
- dbescbin($ph->imageString()),
+ $x = q("update photo set edited = '%s', content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
+ dbesc(datetime_convert()),
+ dbescbin($data),
+ intval($fsize),
intval($height),
intval($width),
dbesc($resource_id),
diff --git a/Zotlabs/Update/_1228.php b/Zotlabs/Update/_1228.php
index b9ba1d86f..9e6bf8047 100644
--- a/Zotlabs/Update/_1228.php
+++ b/Zotlabs/Update/_1228.php
@@ -11,8 +11,8 @@ class _1228 {
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE item ADD uuid text NOT NULL DEFAULT '' ");
- $r2 = q("create index \"uuid_idx\" on channel (\"uuid\")");
- $r3 = q("ALTER TABLE item add summary TEXT NOT NULL");
+ $r2 = q("create index \"uuid_idx\" on item (\"uuid\")");
+ $r3 = q("ALTER TABLE item add summary TEXT NOT NULL DEFAULT ''");
$r = ($r1 && $r2 && $r3);
}
@@ -25,7 +25,6 @@ class _1228 {
if($r) {
q("COMMIT");
- self::upgrade();
return UPDATE_SUCCESS;
}
diff --git a/Zotlabs/Update/_1229.php b/Zotlabs/Update/_1229.php
new file mode 100644
index 000000000..8e8711644
--- /dev/null
+++ b/Zotlabs/Update/_1229.php
@@ -0,0 +1,32 @@
+ [
'posts_label' => t('Show new posts only'),
- 'name_label' => t('Filter by name')
+ 'name_label' => t('Filter by name or address')
]
];
@@ -43,7 +43,7 @@ class Notifications {
],
'filter' => [
'posts_label' => t('Show new posts only'),
- 'name_label' => t('Filter by name')
+ 'name_label' => t('Filter by name or address')
]
];
@@ -119,7 +119,7 @@ class Notifications {
'label' => t('Forums'),
'title' => t('Forums'),
'filter' => [
- 'name_label' => t('Filter by name')
+ 'name_label' => t('Filter by name or address')
]
];
}
@@ -150,7 +150,7 @@ class Notifications {
],
'filter' => [
'posts_label' => t('Show new posts only'),
- 'name_label' => t('Filter by name')
+ 'name_label' => t('Filter by name or address')
]
];
}
diff --git a/boot.php b/boot.php
index c74309be0..e49134a55 100755
--- a/boot.php
+++ b/boot.php
@@ -53,7 +53,7 @@ define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '3.9.5' );
define ( 'ZOT_REVISION', '6.0a' );
-define ( 'DB_UPDATE_VERSION', 1228 );
+define ( 'DB_UPDATE_VERSION', 1229 );
define ( 'PROJECT_BASE', __DIR__ );
@@ -217,6 +217,7 @@ define ( 'PHOTO_PROFILE', 0x0001 );
define ( 'PHOTO_XCHAN', 0x0002 );
define ( 'PHOTO_THING', 0x0004 );
define ( 'PHOTO_COVER', 0x0010 );
+define ( 'PHOTO_CACHE', 0x0020 );
define ( 'PHOTO_ADULT', 0x0008 );
define ( 'PHOTO_FLAG_OS', 0x4000 );
diff --git a/composer.json b/composer.json
index f117cc3b1..e6cefa241 100644
--- a/composer.json
+++ b/composer.json
@@ -40,7 +40,8 @@
"smarty/smarty": "~3.1",
"ramsey/uuid": "^3.8",
"twbs/bootstrap": "4.1.3",
- "blueimp/jquery-file-upload": "^9.25"
+ "blueimp/jquery-file-upload": "^9.25",
+ "desandro/imagesloaded": "^4.1"
},
"require-dev" : {
"phpunit/phpunit" : "@stable",
diff --git a/composer.lock b/composer.lock
index d7e8d11f6..bd95e8c78 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "63d0e52cc07f8113059ec30d3637b850",
+ "content-hash": "fe5e71d7076eeddf1c174be4a5c052dd",
"packages": [
{
"name": "blueimp/jquery-file-upload",
- "version": "v9.25.1",
+ "version": "v9.28.0",
"source": {
"type": "git",
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
- "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b"
+ "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/28891f9b2bc339bcc1ca8d548e5401e8563bf04b",
- "reference": "28891f9b2bc339bcc1ca8d548e5401e8563bf04b",
+ "url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/ff5accfe2e5c4a522777faa980a90cf86a636d1d",
+ "reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d",
"shasum": ""
},
"type": "library",
@@ -59,7 +59,7 @@
"upload",
"widget"
],
- "time": "2018-10-26T07:21:48+00:00"
+ "time": "2018-11-13T05:41:39+00:00"
},
{
"name": "bshaffer/oauth2-server-php",
@@ -163,6 +163,45 @@
"description": "Internationalization library powered by CLDR data.",
"time": "2017-12-29T00:13:05+00:00"
},
+ {
+ "name": "desandro/imagesloaded",
+ "version": "v4.1.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/desandro/imagesloaded.git",
+ "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/desandro/imagesloaded/zipball/67c4e57453120935180c45c6820e7d3fbd2ea1f9",
+ "reference": "67c4e57453120935180c45c6820e7d3fbd2ea1f9",
+ "shasum": ""
+ },
+ "type": "component",
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "David DeSandro",
+ "homepage": "http://desandro.com/",
+ "role": "developer"
+ }
+ ],
+ "description": "JavaScript is all like _You images done yet or what?_",
+ "homepage": "http://imagesloaded.desandro.com",
+ "keywords": [
+ "dom",
+ "images",
+ "javascript",
+ "jquery-plugin",
+ "library",
+ "loaded",
+ "ui"
+ ],
+ "time": "2018-01-02T16:53:35+00:00"
+ },
{
"name": "ezyang/htmlpurifier",
"version": "v4.10.0",
@@ -446,16 +485,16 @@
},
{
"name": "psr/log",
- "version": "1.0.2",
+ "version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d"
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
- "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
+ "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd",
"shasum": ""
},
"require": {
@@ -489,7 +528,7 @@
"psr",
"psr-3"
],
- "time": "2016-10-10T12:19:37+00:00"
+ "time": "2018-11-20T15:27:04+00:00"
},
{
"name": "ramsey/uuid",
@@ -1110,7 +1149,7 @@
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.9.0",
+ "version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -2536,16 +2575,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "6.1.3",
+ "version": "6.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "4d3ae9b21a7d7e440bd0cf65565533117976859f"
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/4d3ae9b21a7d7e440bd0cf65565533117976859f",
- "reference": "4d3ae9b21a7d7e440bd0cf65565533117976859f",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
+ "reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
"shasum": ""
},
"require": {
@@ -2595,7 +2634,7 @@
"testing",
"xunit"
],
- "time": "2018-10-23T05:59:32+00:00"
+ "time": "2018-10-31T16:06:48+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -2788,16 +2827,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "7.4.3",
+ "version": "7.4.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "c151651fb6ed264038d486ea262e243af72e5e64"
+ "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c151651fb6ed264038d486ea262e243af72e5e64",
- "reference": "c151651fb6ed264038d486ea262e243af72e5e64",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
+ "reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
"shasum": ""
},
"require": {
@@ -2868,7 +2907,7 @@
"testing",
"xunit"
],
- "time": "2018-10-23T05:57:41+00:00"
+ "time": "2018-11-14T16:52:02+00:00"
},
{
"name": "psr/container",
@@ -3534,7 +3573,7 @@
},
{
"name": "symfony/browser-kit",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
@@ -3591,16 +3630,16 @@
},
{
"name": "symfony/class-loader",
- "version": "v3.4.17",
+ "version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/class-loader.git",
- "reference": "f31333bdff54c7595f834d510a6d2325573ddb36"
+ "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/class-loader/zipball/f31333bdff54c7595f834d510a6d2325573ddb36",
- "reference": "f31333bdff54c7595f834d510a6d2325573ddb36",
+ "url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1",
+ "reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1",
"shasum": ""
},
"require": {
@@ -3643,20 +3682,20 @@
],
"description": "Symfony ClassLoader Component",
"homepage": "https://symfony.com",
- "time": "2018-10-02T12:28:39+00:00"
+ "time": "2018-10-31T09:06:03+00:00"
},
{
"name": "symfony/config",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96"
+ "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/b3d4d7b567d7a49e6dfafb6d4760abc921177c96",
- "reference": "b3d4d7b567d7a49e6dfafb6d4760abc921177c96",
+ "url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
+ "reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"shasum": ""
},
"require": {
@@ -3706,20 +3745,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
- "time": "2018-09-08T13:24:10+00:00"
+ "time": "2018-10-31T09:09:42+00:00"
},
{
"name": "symfony/console",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b"
+ "reference": "432122af37d8cd52fba1b294b11976e0d20df595"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/dc7122fe5f6113cfaba3b3de575d31112c9aa60b",
- "reference": "dc7122fe5f6113cfaba3b3de575d31112c9aa60b",
+ "url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595",
+ "reference": "432122af37d8cd52fba1b294b11976e0d20df595",
"shasum": ""
},
"require": {
@@ -3774,11 +3813,11 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
- "time": "2018-10-03T08:15:46+00:00"
+ "time": "2018-10-31T09:30:44+00:00"
},
{
"name": "symfony/css-selector",
- "version": "v3.4.17",
+ "version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
@@ -3831,16 +3870,16 @@
},
{
"name": "symfony/dependency-injection",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "f6b9d893ad28aefd8942dc0469c8397e2216fe30"
+ "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f6b9d893ad28aefd8942dc0469c8397e2216fe30",
- "reference": "f6b9d893ad28aefd8942dc0469c8397e2216fe30",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483",
+ "reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483",
"shasum": ""
},
"require": {
@@ -3898,11 +3937,11 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
- "time": "2018-10-02T12:40:59+00:00"
+ "time": "2018-10-31T10:54:16+00:00"
},
{
"name": "symfony/dom-crawler",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
@@ -3959,16 +3998,16 @@
},
{
"name": "symfony/event-dispatcher",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
- "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e"
+ "reference": "552541dad078c85d9414b09c041ede488b456cd5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/bfb30c2ad377615a463ebbc875eba64a99f6aa3e",
- "reference": "bfb30c2ad377615a463ebbc875eba64a99f6aa3e",
+ "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/552541dad078c85d9414b09c041ede488b456cd5",
+ "reference": "552541dad078c85d9414b09c041ede488b456cd5",
"shasum": ""
},
"require": {
@@ -4018,20 +4057,20 @@
],
"description": "Symfony EventDispatcher Component",
"homepage": "https://symfony.com",
- "time": "2018-07-26T09:10:45+00:00"
+ "time": "2018-10-10T13:52:42+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "596d12b40624055c300c8b619755b748ca5cf0b5"
+ "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/596d12b40624055c300c8b619755b748ca5cf0b5",
- "reference": "596d12b40624055c300c8b619755b748ca5cf0b5",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981",
+ "reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"shasum": ""
},
"require": {
@@ -4068,20 +4107,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
- "time": "2018-10-02T12:40:59+00:00"
+ "time": "2018-10-30T13:18:25+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.9.0",
+ "version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8"
+ "reference": "c79c051f5b3a46be09205c73b80b346e4153e494"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/d0cd638f4634c16d8df4508e847f14e9e43168b8",
- "reference": "d0cd638f4634c16d8df4508e847f14e9e43168b8",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/c79c051f5b3a46be09205c73b80b346e4153e494",
+ "reference": "c79c051f5b3a46be09205c73b80b346e4153e494",
"shasum": ""
},
"require": {
@@ -4127,20 +4166,20 @@
"portable",
"shim"
],
- "time": "2018-08-06T14:22:27+00:00"
+ "time": "2018-09-21T13:07:52+00:00"
},
{
"name": "symfony/translation",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
- "reference": "9f0b61e339160a466ebcde167a6c5521c810e304"
+ "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/translation/zipball/9f0b61e339160a466ebcde167a6c5521c810e304",
- "reference": "9f0b61e339160a466ebcde167a6c5521c810e304",
+ "url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
+ "reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
"shasum": ""
},
"require": {
@@ -4196,11 +4235,11 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
- "time": "2018-10-02T16:36:10+00:00"
+ "time": "2018-10-28T18:38:52+00:00"
},
{
"name": "symfony/yaml",
- "version": "v4.1.6",
+ "version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
diff --git a/doc/es-es/about/about.bb b/doc/es-es/about/about.bb
index 1d5f3a4a2..50d23c778 100644
--- a/doc/es-es/about/about.bb
+++ b/doc/es-es/about/about.bb
@@ -29,7 +29,7 @@ $Projectname es, básicamente, una aplicación de servidor web relativamente est
[*= Identidad nómada] La capacidad de autenticar y migrar fácilmente una identidad a través de hubs y dominios web independientes. La identidad nómada proporciona una verdadera propiedad de una identidad en línea, porque las identidades de los canales controlados por una cuenta en un hub no están vinculadas al propio hub. Un hub es más como un "host" para canales. Con Hubzilla, no tienes una "cuenta" en un servidor como lo haces en sitios web típicos; tienes una identidad que puedes llevarte a través de la rejilla usando clones.
-[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo para el control de acceso distribuido a escala de Internet que es discreto.
+[*= Zot] El novedoso protocolo basado en JSON para la implementación de comunicaciones y servicios descentralizados seguros. Se diferencia de muchos otros protocolos de comunicación en que construye las comunicaciones sobre un marco de identidad y autenticación descentralizado. El componente de autenticación es similar a OpenID conceptualmente pero está aislado de las identidades basadas en DNS. Cuando es posible, la autenticación remota es silenciosa e invisible. Esto proporciona un mecanismo discreto para el control de acceso distribuido a escala de Internet.
[/dl]
@@ -41,7 +41,7 @@ Esta página enumera algunas de las características principales de $Projectname
[h4]Control deslizante de afinidad[/h4]
Cuando se añaden conexiones en $Projectname, los miembros tienen la opción de asignar niveles de "afinidad" (cuán cerca está su amigo).
-Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad de "Amigos".
+Por otro lado, al añadir el canal de un amigo, se puede situar bajo el nivel de afinidad, justamente, de "Amigos".
En este punto, la herramienta $Projectname [i]Control deslizante de afinidad[/i], que normalmente aparece en la parte superior de la página, ajusta su contenido para incluir aquellos contactos que están dentro del rango de afinidad deseado. Los canales fuera de ese rango no se mostrarán, a menos que ajuste el control deslizante para incluirlos.
@@ -62,7 +62,7 @@ Las listas de control de acceso se pueden aplicar a contenido y mensajes, fotos,
[h4]Inicio de sesión único[/h4]
-Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en el hub de su casa. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica".
+Las listas de control de acceso funcionan para todos los canales de la red gracias a nuestra exclusiva tecnología de inicio de sesión único. La mayoría de los enlaces internos proporcionan un token de identidad que puede ser verificado en otros sitios de $Projectname y utilizado para controlar el acceso a recursos privados. Inicie sesión una vez en la página principal del hub. Después de eso, la autenticación de todos los recursos de $Projectname es "mágica".
[h4]Almacenamiento de Archivos habilitado para WebDAV[/h4]
@@ -93,7 +93,7 @@ Las aplicaciones pueden ser construidas y distribuidas por los miembros. Éstas
[h4]Diseño[/h4]
-El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en diseños comanches que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario".
+El diseño de la página se basa en un lenguaje de descripción llamado comanche. La propia $Projectname está escrito en plantillas en comanche que se pueden cambiar. Esto permite un nivel de personalización que no se encuentra normalmente en los llamados "entornos multiusuario".
[h4]Marcadores[/h4]
@@ -111,14 +111,14 @@ Además, los mensajes pueden crearse utilizando "encriptación de extremo a extr
Por lo general, los mensajes públicos no se cifran durante el transporte ni durante el almacenamiento.
-Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído todavía.
+Los mensajes privados pueden ser revocados (no enviados) aunque no hay garantía de que el destinatario no lo haya leído antes.
Los mensajes se pueden crear con una fecha de caducidad, en la que se borrarán/quitarán en el sitio del destinatario.
[h4]Federación de Servicios[/h4]
-Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde/hacia la diáspora, Friendica, GNU-Social, Mastodon y otros proveedores que utilizan estos protocolos.
+Además de añadir "conectores de publicación cruzada" a una variedad de redes alternativas, hay soporte nativo para la importación de contenido desde RSS/Atom feeds y puede utilizarlo para crear canales especiales. Los plugins también están disponibles para comunicarse con otros usando los protocolos Diáspora, GNU-Social (OStatus) o Mastodon (ActivityPub). Estas redes no soportan la identidad nómada ni el control de acceso entre dominios; sin embargo, las comunicaciones básicas son soportadas desde o hacia Diaspora, Friendica, GNU-Social, Mastodon, Pleroma y otros proveedores que utilizan estos protocolos.
También existe soporte experimental para la autenticación OpenID que puede utilizarse en las listas de control de acceso. Este es un trabajo en progreso. Su hub $Projectname puede ser utilizado como un proveedor de OpenID para autenticarle en servicios externos que utilizan esta tecnología.
@@ -126,7 +126,7 @@ Los canales pueden tener permisos para convertirse en "canales derivados" cuando
[h4]Grupos de Privacidad[/h4]
-Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de la Diáspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo).
+Nuestra implementación de grupos de privacidad es similar a la de Google "Círculos" y "Aspectos" de Diaspora. Esto le permite filtrar su flujo entrante por grupos seleccionados y establecer automáticamente la Lista de control de acceso saliente sólo para aquellos que se encuentren en ese grupo de privacidad cuando publique. Usted puede anular esto en cualquier momento (antes de enviar el correo).
[h4]Servicios de directorio[/h4]
@@ -158,19 +158,25 @@ Las opciones son:
[h4]Foros Públicos y Privados[/h4]
-Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros: 1) mensajes de "muro a muro" y 2) a través de las etiquetas @mención del foro. Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros.
+Los foros son típicamente canales que pueden estar abiertos a la participación de múltiples autores. Actualmente existen dos mecanismos para enviar mensajes a los foros:
+
+1) mensajes de "muro a muro" y
+
+2) a través de las etiquetas @mención del foro.
+
+Los foros pueden ser creados por cualquier persona y utilizados para cualquier propósito. El directorio contiene una opción para buscar foros públicos. Los foros privados sólo pueden ser publicados y, a menudo, sólo pueden ser vistos por los miembros.
[h4]Clonación de cuentas[/h4]
-Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando creas una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com.
+Las cuentas en $Projectname se denominan [i]identidades nómadas[/i], porque la identidad de un miembro no está vinculada al hub donde se creó la identidad originalmente. Por ejemplo, cuando cree una cuenta de Facebook o Gmail, está vinculada a esos servicios. No pueden funcionar sin Facebook.com o Gmail.com.
-Por el contrario, digamos que ha creado una identidad $Projectname llamada[b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b]
+Por el contrario, digamos que ha creado una identidad $Projectname llamada [b]tina@$Projectnamehub.com[/b]. Puede clonarlo a otro hub $Projectname eligiendo el mismo o un nombre diferente:[b]vivoParasiempre@algún$ProjectnameHub.info[/b]
-Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envías un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas.
+Ahora ambos canales están sincronizados, lo que significa que todos sus contactos y preferencias se duplicarán en su clon. No importa si envía un mensaje desde su hub original o desde el nuevo hub. Los mensajes se reflejarán en ambas cuentas.
Esta es una característica bastante revolucionaria, si consideramos algunos escenarios:
- ¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tienesque iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre.
+ ¿Qué ocurre si el hub en el que se basa una identidad se desconecta de repente? Sin clonación, un miembro no podrá comunicarse hasta que el hub vuelva a estar en línea (sin duda muchos de ustedes han visto y maldecido el Twitter "Fail Whale"). Con la clonación, sólo tiene que iniciar sesión en su cuenta clonada y la vida continúa feliz para siempre.
El administrador de su hub ya no puede permitirse el lujo de pagar por su hub gratuito y público $Projectname. Anuncia que el centro cerrará en dos semanas. Esto le da tiempo suficiente para clonar su(s) identidad(es) y preservar las relaciones, amigos y contenido de su $Projectname.
@@ -193,9 +199,10 @@ $Projectname ofrece una sencilla copia de seguridad de la cuenta con un solo cli
[h4]Borrado de cuenta[/h4]
-Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la rejilla (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible.
+Las cuentas se pueden eliminar inmediatamente haciendo clic en un enlace. Eso es todo. Todo el contenido asociado se elimina de la red (esto incluye los mensajes y cualquier otro contenido producido por el perfil eliminado). Dependiendo del número de conexiones que tenga, el proceso de eliminación de contenido remoto podría llevar algún tiempo, pero está previsto que ocurra tan rápido como sea posible.
[h4]Supresión de contenido[/h4]
+
Cualquier contenido creado en $Projectname permanece bajo el control del miembro (o canal) que lo creó originalmente. En cualquier momento, un miembro puede borrar un mensaje o un rango de mensajes. El proceso de eliminación garantiza que el contenido se elimine, independientemente de si se publicó en el hub principal de un canal o en otro hub, donde el canal se autenticó de forma remota a través de Zot (protocolo de autenticación y comunicación de $Projectname).
@@ -221,4 +228,4 @@ $Projectname se puede ampliar de varias maneras, a través de la personalizació
[h4]API[/h4]
-Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth es proporcionado.
\ No newline at end of file
+Una API está disponible para su uso por parte de servicios de terceros. Un plugin también proporciona una implementación básica de Twitter (para los que existen cientos de herramientas de terceros). El acceso puede ser proporcionado por login/contraseña o OAuth, y el registro del cliente de las aplicaciones de OAuth está disponible.
\ No newline at end of file
diff --git a/include/items.php b/include/items.php
index 8eaeb61b7..b2c288b75 100755
--- a/include/items.php
+++ b/include/items.php
@@ -618,8 +618,6 @@ function get_item_elements($x,$allow_code = false) {
$arr['created'] = datetime_convert('UTC','UTC',$x['created']);
$arr['edited'] = datetime_convert('UTC','UTC',$x['edited']);
- if($arr['created'] > datetime_convert())
- $arr['created'] = datetime_convert();
if($arr['edited'] > datetime_convert())
$arr['edited'] = datetime_convert();
diff --git a/include/oembed.php b/include/oembed.php
index e5557dc11..426197c5f 100755
--- a/include/oembed.php
+++ b/include/oembed.php
@@ -221,7 +221,11 @@ function oembed_fetch_url($embedurl){
if(strpos(strtolower($embedurl),'.pdf') !== false) {
$action = 'allow';
- $j = [ 'html' => '', 'width' => 500, 'height' => 720, 'type' => 'pdf' ];
+ $j = [
+ 'html' => '',
+ 'title' => t('View PDF'),
+ 'type' => 'pdf'
+ ];
}
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 4173d727e..9aeb2ef17 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -112,7 +112,7 @@ abstract class photo_driver {
public function saveImage($path) {
if(!$this->is_valid())
return FALSE;
- file_put_contents($path, $this->imageString());
+ return (file_put_contents($path, $this->imageString()) ? true : false);
}
@@ -330,9 +330,9 @@ abstract class photo_driver {
}
- public function save($arr) {
+ public function save($arr, $skipcheck = false) {
- if(! $this->is_valid()) {
+ if(! ($skipcheck || $this->is_valid())) {
logger('attempt to store invalid photo.');
return false;
}
@@ -344,6 +344,7 @@ abstract class photo_driver {
$p['xchan'] = (($arr['xchan']) ? $arr['xchan'] : '');
$p['resource_id'] = (($arr['resource_id']) ? $arr['resource_id'] : '');
$p['filename'] = (($arr['filename']) ? $arr['filename'] : '');
+ $p['mimetype'] = (($arr['mimetype']) ? $arr['mimetype'] : $this->getType());
$p['album'] = (($arr['album']) ? $arr['album'] : '');
$p['imgscale'] = ((intval($arr['imgscale'])) ? intval($arr['imgscale']) : 0);
$p['allow_cid'] = (($arr['allow_cid']) ? $arr['allow_cid'] : '');
@@ -360,6 +361,7 @@ abstract class photo_driver {
$p['display_path'] = (($arr['display_path']) ? $arr['display_path'] : '');
$p['width'] = (($arr['width']) ? $arr['width'] : $this->getWidth());
$p['height'] = (($arr['height']) ? $arr['height'] : $this->getHeight());
+ $p['expires'] = (($arr['expires']) ? $arr['expires'] : gmdate('Y-m-d H:i:s', time() + get_config('system','photo_cache_time', 86400)));
if(! intval($p['imgscale']))
logger('save: ' . print_r($arr,true), LOGGER_DATA);
@@ -397,23 +399,24 @@ abstract class photo_driver {
allow_cid = '%s',
allow_gid = '%s',
deny_cid = '%s',
- deny_gid = '%s'
+ deny_gid = '%s',
+ expires = '%s'
where id = %d",
intval($p['aid']),
intval($p['uid']),
dbesc($p['xchan']),
dbesc($p['resource_id']),
- dbesc($p['created']),
- dbesc($p['edited']),
+ dbescdate($p['created']),
+ dbescdate($p['edited']),
dbesc(basename($p['filename'])),
- dbesc($this->getType()),
+ dbesc($p['mimetype']),
dbesc($p['album']),
intval($p['height']),
intval($p['width']),
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
intval($p['os_storage']),
- intval(strlen($this->imageString())),
+ (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
intval($p['imgscale']),
intval($p['photo_usage']),
dbesc($p['title']),
@@ -424,28 +427,29 @@ abstract class photo_driver {
dbesc($p['allow_gid']),
dbesc($p['deny_cid']),
dbesc($p['deny_gid']),
+ dbescdate($p['expires']),
intval($x[0]['id'])
);
}
else {
$p['created'] = (($arr['created']) ? $arr['created'] : $p['edited']);
$r = q("INSERT INTO photo
- ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid )
- VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
+ ( aid, uid, xchan, resource_id, created, edited, filename, mimetype, album, height, width, content, os_storage, filesize, imgscale, photo_usage, title, description, os_path, display_path, allow_cid, allow_gid, deny_cid, deny_gid, expires )
+ VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
intval($p['aid']),
intval($p['uid']),
dbesc($p['xchan']),
dbesc($p['resource_id']),
- dbesc($p['created']),
- dbesc($p['edited']),
+ dbescdate($p['created']),
+ dbescdate($p['edited']),
dbesc(basename($p['filename'])),
- dbesc($this->getType()),
+ dbesc($p['mimetype']),
dbesc($p['album']),
intval($p['height']),
intval($p['width']),
(intval($p['os_storage']) ? dbescbin($p['os_syspath']) : dbescbin($this->imageString())),
intval($p['os_storage']),
- intval(strlen($this->imageString())),
+ (intval($p['os_storage']) ? @filesize($p['os_syspath']) : strlen($this->imageString())),
intval($p['imgscale']),
intval($p['photo_usage']),
dbesc($p['title']),
@@ -455,7 +459,8 @@ abstract class photo_driver {
dbesc($p['allow_cid']),
dbesc($p['allow_gid']),
dbesc($p['deny_cid']),
- dbesc($p['deny_gid'])
+ dbesc($p['deny_gid']),
+ dbescdate($p['expires'])
);
}
logger('photo save ' . $p['imgscale'] . ' returned ' . intval($r));
diff --git a/include/photo/photo_imagick.php b/include/photo/photo_imagick.php
index 89577e71e..f04c00245 100644
--- a/include/photo/photo_imagick.php
+++ b/include/photo/photo_imagick.php
@@ -31,8 +31,12 @@ class photo_imagick extends photo_driver {
if(! $data)
return;
- $this->image->readImageBlob($data);
-
+ try {
+ $this->image->readImageBlob($data);
+ }
+ catch (Exception $e) {
+ logger('imagick readImageBlob() exception:' . print_r($e,true));
+ }
/**
* Setup the image to the format it will be saved to
@@ -205,4 +209,4 @@ class photo_imagick extends photo_driver {
-}
\ No newline at end of file
+}
diff --git a/include/text.php b/include/text.php
index edd0f7a5a..bd0d8048d 100644
--- a/include/text.php
+++ b/include/text.php
@@ -1105,23 +1105,33 @@ function linkify($s, $me = false) {
* to a local redirector which uses https and which redirects to the selected content
*
* @param string $s
+ * @param int $uid
* @returns string
*/
function sslify($s) {
+
+ // Local photo cache
+ $str = array(
+ 'body' => $s,
+ 'uid' => local_channel()
+ );
+ call_hooks('cache_body_hook', $str);
+
+ $s = $str['body'];
+
if (strpos(z_root(),'https:') === false)
return $s;
-
+
// By default we'll only sslify img tags because media files will probably choke.
// You can set sslify_everything if you want - but it will likely white-screen if it hits your php memory limit.
// The downside is that http: media files will likely be blocked by your browser
// Complain to your browser maker
$allow = get_config('system','sslify_everything');
-
- $pattern = (($allow) ? "/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/" : "/\/" );
+ $pattern = (($allow) ? "/\<(.*?)src=[\"|'](http\:.*?)[\"|'](.*?)\>/" : "/\/" );
$matches = null;
- $cnt = preg_match_all($pattern,$s,$matches,PREG_SET_ORDER);
+ $cnt = preg_match_all($pattern, $s, $matches, PREG_SET_ORDER);
if ($cnt) {
foreach ($matches as $match) {
$filename = basename( parse_url($match[2], PHP_URL_PATH) );
@@ -3295,7 +3305,7 @@ function cleanup_bbcode($body) {
$body = preg_replace('/\[\/code\]\s*\[code\]/ism',"\n",$body);
- $body = scale_external_images($body,false);
+ $body = scale_external_images($body, false);
return $body;
}
@@ -3411,7 +3421,7 @@ function get_forum_channels($uid) {
$sql_extra = (($xf) ? " and ( xchan_hash in (" . $xf . ") or xchan_pubforum = 1 ) " : " and xchan_pubforum = 1 ");
- $r = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
+ $r = q("select abook_id, xchan_hash, xchan_name, xchan_url, xchan_addr, xchan_photo_s from abook left join xchan on abook_xchan = xchan_hash where xchan_deleted = 0 and abook_channel = %d and abook_pending = 0 and abook_ignored = 0 and abook_blocked = 0 and abook_archived = 0 $sql_extra order by xchan_name",
intval($uid)
);
diff --git a/install/schema_mysql.sql b/install/schema_mysql.sql
index c820fca25..49a2c476a 100644
--- a/install/schema_mysql.sql
+++ b/install/schema_mysql.sql
@@ -916,7 +916,6 @@ CREATE TABLE IF NOT EXISTS `outq` (
KEY `outq_priority` (`outq_priority`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
CREATE TABLE IF NOT EXISTS pchan (
`pchan_id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`pchan_guid` char(191) NOT NULL DEFAULT '',
@@ -928,15 +927,16 @@ CREATE TABLE IF NOT EXISTS pchan (
KEY `pchan_hash` (`pchan_hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
CREATE TABLE IF NOT EXISTS `pconfig` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` int(11) NOT NULL DEFAULT 0 ,
`cat` char(191) NOT NULL DEFAULT '',
`k` char(191) NOT NULL DEFAULT '',
`v` mediumtext NOT NULL,
+ `updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY (`id`),
- UNIQUE KEY `access` (`uid`,`cat`,`k`)
+ UNIQUE KEY `access` (`uid`,`cat`,`k`),
+ KEY `pconfig_updated` (`updated`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE IF NOT EXISTS `photo` (
@@ -947,6 +947,7 @@ CREATE TABLE IF NOT EXISTS `photo` (
`resource_id` char(191) NOT NULL DEFAULT '',
`created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
+ `expires` datetime NOT NULL DEFAULT '0001-01-01 00:00:00',
`title` char(191) NOT NULL DEFAULT '',
`description` text NOT NULL,
`album` char(191) NOT NULL DEFAULT '',
@@ -979,6 +980,7 @@ CREATE TABLE IF NOT EXISTS `photo` (
KEY `xchan` (`xchan`),
KEY `filesize` (`filesize`),
KEY `resource_id` (`resource_id`),
+ KEY `expires` (`expires`),
KEY `is_nsfw` (`is_nsfw`),
KEY `os_storage` (`os_storage`),
KEY `photo_usage` (`photo_usage`)
diff --git a/install/schema_postgres.sql b/install/schema_postgres.sql
index 3bc256377..1b6cab51b 100644
--- a/install/schema_postgres.sql
+++ b/install/schema_postgres.sql
@@ -897,7 +897,6 @@ create index "outq_async" on outq ("outq_async");
create index "outq_delivered" on outq ("outq_delivered");
create index "outq_priority" on outq ("outq_priority");
-
CREATE TABLE "pchan" (
"pchan_id" serial NOT NULL,
"pchan_guid" text NOT NULL,
@@ -906,7 +905,6 @@ CREATE TABLE "pchan" (
"pchan_prvkey" text NOT NULL,
PRIMARY KEY ("pchan_id")
);
-
create index "pchan_guid" on pchan ("pchan_guid");
create index "pchan_hash" on pchan ("pchan_hash");
@@ -916,9 +914,11 @@ CREATE TABLE "pconfig" (
"cat" text NOT NULL,
"k" text NOT NULL,
"v" text NOT NULL,
+ "updated" timestamp NOT NULL DEFAULT '0001-01-01 00:00:00',
PRIMARY KEY ("id"),
UNIQUE ("uid","cat","k")
);
+create index "pconfig_updated_idx" on pconfig ("updated");
CREATE TABLE "photo" (
"id" serial NOT NULL,
@@ -928,6 +928,7 @@ CREATE TABLE "photo" (
"resource_id" text NOT NULL,
"created" timestamp NOT NULL,
"edited" timestamp NOT NULL,
+ "expires" timestamp NOT NULL,
"title" text NOT NULL,
"description" text NOT NULL,
"album" text NOT NULL,
@@ -961,6 +962,7 @@ create index "photo_aid" on photo ("aid");
create index "photo_xchan" on photo ("xchan");
create index "photo_filesize" on photo ("filesize");
create index "photo_resource_id" on photo ("resource_id");
+create index "photo_expires_idx" on photo ("expires");
create index "photo_usage" on photo ("photo_usage");
create index "photo_is_nsfw" on photo ("is_nsfw");
create index "photo_os_storage" on photo ("os_storage");
diff --git a/library/imagesloaded/imagesloaded.pkgd.min.js b/library/imagesloaded/imagesloaded.pkgd.min.js
deleted file mode 100644
index c3e71fadc..000000000
--- a/library/imagesloaded/imagesloaded.pkgd.min.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/*!
- * imagesLoaded PACKAGED v4.1.0
- * JavaScript is all like "You images are done yet or what?"
- * MIT License
- */
-
-!function(t,e){"function"==typeof define&&define.amd?define("ev-emitter/ev-emitter",e):"object"==typeof module&&module.exports?module.exports=e():t.EvEmitter=e()}(this,function(){function t(){}var e=t.prototype;return e.on=function(t,e){if(t&&e){var i=this._events=this._events||{},n=i[t]=i[t]||[];return-1==n.indexOf(e)&&n.push(e),this}},e.once=function(t,e){if(t&&e){this.on(t,e);var i=this._onceEvents=this._onceEvents||{},n=i[t]=i[t]||[];return n[e]=!0,this}},e.off=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=i.indexOf(e);return-1!=n&&i.splice(n,1),this}},e.emitEvent=function(t,e){var i=this._events&&this._events[t];if(i&&i.length){var n=0,o=i[n];e=e||[];for(var r=this._onceEvents&&this._onceEvents[t];o;){var s=r&&r[o];s&&(this.off(t,o),delete r[o]),o.apply(this,e),n+=s?0:1,o=i[n]}return this}},t}),function(t,e){"use strict";"function"==typeof define&&define.amd?define(["ev-emitter/ev-emitter"],function(i){return e(t,i)}):"object"==typeof module&&module.exports?module.exports=e(t,require("ev-emitter")):t.imagesLoaded=e(t,t.EvEmitter)}(window,function(t,e){function i(t,e){for(var i in e)t[i]=e[i];return t}function n(t){var e=[];if(Array.isArray(t))e=t;else if("number"==typeof t.length)for(var i=0;i
-
+
@@ -177,8 +177,8 @@
-
-
+
+
@@ -186,7 +186,7 @@
-
+
diff --git a/vendor/blueimp/jquery-file-upload/basic-plus.html b/vendor/blueimp/jquery-file-upload/basic-plus.html
index acee24843..6d53acdc1 100644
--- a/vendor/blueimp/jquery-file-upload/basic-plus.html
+++ b/vendor/blueimp/jquery-file-upload/basic-plus.html
@@ -20,7 +20,7 @@
-
+
@@ -96,15 +96,15 @@
-
+
-
+
-
+
diff --git a/vendor/blueimp/jquery-file-upload/basic.html b/vendor/blueimp/jquery-file-upload/basic.html
index 232a24624..a9ef6273e 100644
--- a/vendor/blueimp/jquery-file-upload/basic.html
+++ b/vendor/blueimp/jquery-file-upload/basic.html
@@ -20,7 +20,7 @@
-
+
@@ -96,7 +96,7 @@
-
+
@@ -104,7 +104,7 @@
-
+
+
-
+
@@ -226,7 +226,7 @@
-
+
diff --git a/vendor/blueimp/jquery-file-upload/jquery-ui.html b/vendor/blueimp/jquery-file-upload/jquery-ui.html
index 842dd4ca7..e44d41e89 100644
--- a/vendor/blueimp/jquery-file-upload/jquery-ui.html
+++ b/vendor/blueimp/jquery-file-upload/jquery-ui.html
@@ -22,7 +22,7 @@
-
+
@@ -201,8 +201,8 @@
{% } %}
-
-
+
+
diff --git a/vendor/blueimp/jquery-file-upload/package.json b/vendor/blueimp/jquery-file-upload/package.json
index 4b33a0362..0a635397c 100644
--- a/vendor/blueimp/jquery-file-upload/package.json
+++ b/vendor/blueimp/jquery-file-upload/package.json
@@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
- "version": "9.25.1",
+ "version": "9.28.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": [
diff --git a/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php b/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php
old mode 100755
new mode 100644
index e44004395..5215e4c0f
--- a/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php
+++ b/vendor/blueimp/jquery-file-upload/server/php/UploadHandler.php
@@ -38,9 +38,9 @@ class UploadHandler
'image_resize' => 'Failed to resize image'
);
- protected const IMAGETYPE_GIF = 1;
- protected const IMAGETYPE_JPEG = 2;
- protected const IMAGETYPE_PNG = 3;
+ const IMAGETYPE_GIF = 1;
+ const IMAGETYPE_JPEG = 2;
+ const IMAGETYPE_PNG = 3;
protected $image_objects = array();
@@ -1047,13 +1047,18 @@ class UploadHandler
}
protected function create_scaled_image($file_name, $version, $options) {
- if ($this->options['image_library'] === 2) {
- return $this->imagemagick_create_scaled_image($file_name, $version, $options);
+ try {
+ if ($this->options['image_library'] === 2) {
+ return $this->imagemagick_create_scaled_image($file_name, $version, $options);
+ }
+ if ($this->options['image_library'] && extension_loaded('imagick')) {
+ return $this->imagick_create_scaled_image($file_name, $version, $options);
+ }
+ return $this->gd_create_scaled_image($file_name, $version, $options);
+ } catch (\Exception $e) {
+ error_log($e->getMessage());
+ return false;
}
- if ($this->options['image_library'] && extension_loaded('imagick')) {
- return $this->imagick_create_scaled_image($file_name, $version, $options);
- }
- return $this->gd_create_scaled_image($file_name, $version, $options);
}
protected function destroy_image_object($file_path) {
@@ -1066,12 +1071,12 @@ class UploadHandler
$fp = fopen($file_path, 'r');
$data = fread($fp, 4);
fclose($fp);
- // GIF: 47 49 46
- if (substr($data, 0, 3) === 'GIF') {
+ // GIF: 47 49 46 38
+ if ($data === 'GIF8') {
return self::IMAGETYPE_GIF;
}
- // JPG: FF D8
- if (bin2hex(substr($data, 0, 2)) === 'ffd8') {
+ // JPG: FF D8 FF
+ if (bin2hex(substr($data, 0, 3)) === 'ffd8ff') {
return self::IMAGETYPE_JPEG;
}
// PNG: 89 50 4E 47
@@ -1082,6 +1087,9 @@ class UploadHandler
}
protected function is_valid_image_file($file_path) {
+ if (!preg_match('/\.(gif|jpe?g|png)$/i', $file_path)) {
+ return false;
+ }
return !!$this->imagetype($file_path);
}
diff --git a/vendor/blueimp/jquery-file-upload/server/php/index.php b/vendor/blueimp/jquery-file-upload/server/php/index.php
index 9c2cfb8eb..6caabb710 100644
--- a/vendor/blueimp/jquery-file-upload/server/php/index.php
+++ b/vendor/blueimp/jquery-file-upload/server/php/index.php
@@ -9,7 +9,7 @@
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
-exit;
+
error_reporting(E_ALL | E_STRICT);
require('UploadHandler.php');
$upload_handler = new UploadHandler();
diff --git a/vendor/blueimp/jquery-file-upload/test/index.html b/vendor/blueimp/jquery-file-upload/test/index.html
index 0b5cf57b7..b8c585df5 100644
--- a/vendor/blueimp/jquery-file-upload/test/index.html
+++ b/vendor/blueimp/jquery-file-upload/test/index.html
@@ -20,7 +20,7 @@
jQuery File Upload Plugin Test
-
+