Compare commits

...

180 Commits
3.8.2 ... 3.8.7

Author SHA1 Message Date
Mario Vavti
d77c7d51e3 update changelog
(cherry picked from commit 4ff3c57976)
2018-12-14 21:47:20 +01:00
Mario Vavti
d51d0160d3 fix issue with linkdropper
(cherry picked from commit f81a3ba45d)
2018-12-14 21:32:23 +01:00
zotlabs
c2ad9d4996 regression: the ability to order apps messed up since adding pinned apps to the ordering
(cherry picked from commit 6464099364)
2018-12-14 21:31:02 +01:00
Mario
79f828125d version bump 2018-12-14 11:47:02 +01:00
Mario Vavti
ad4b18cbbe return on readImageBlob() exception
(cherry picked from commit 993db01400)
2018-12-14 11:31:11 +01:00
Mario Vavti
1bd49671b7 add photo_view_filter hook and fix minor issue with unset auto_save_draft variable which resultet in a javascript error
(cherry picked from commit 7894fed741)
2018-12-14 11:30:57 +01:00
zotlabs
9896057549 home notifications won't expand if there are more than 300 unseen network notifications ahead of them.
(cherry picked from commit 30efeb5bec)
2018-12-14 11:30:25 +01:00
phani00
44832bbacb change redbasic dark schema to make categories and highlights readable
additions to /view/theme/redbasic/schema/dark.css to change the appearance of category
badges and highlighted text ([hl]...[/hl]).

hl text changed from master: it's not 'strong' anymore. commented out the pseudo-class
selector that works in master but not in dev anymore.


(cherry picked from commit 18caf0273f)
2018-12-14 11:30:05 +01:00
zotlabs
f20a923dd7 total_identities restriction off by one
(cherry picked from commit e60fb17524)
2018-12-14 11:29:33 +01:00
zotlabs
30403da326 reset page title if article has no title.
(cherry picked from commit 8ab1f31058)
2018-12-14 11:29:06 +01:00
Mario Vavti
6b68a76bbe quickfix for es-es language 2018-12-03 21:22:02 +01:00
Mario Vavti
8f10b58cb1 version 3.8.6 2018-12-03 12:23:55 +01:00
Mario Vavti
f8bc408abc update strings 2018-12-03 12:07:56 +01:00
Mario Vavti
f581f6163a optimize autoload cache 2018-12-03 11:52:38 +01:00
Mario Vavti
88486a1278 changelog 2018-12-03 11:47:28 +01:00
Mario Vavti
9fcadc2d7c prevent incompatible export files (osada/zap) from being imported (manual patch from dev) 2018-12-03 11:08:39 +01:00
Mario Vavti
9ef6c57ca5 more notifications fixes 2018-12-03 10:46:49 +01:00
Mario Vavti
443d7684db catch exception if readImageBlob() receives bogus data 2018-12-03 10:45:43 +01:00
Mario Vavti
a3ba7f0788 fallback to url if we have not got an addr 2018-12-02 11:38:13 +01:00
Mario Vavti
f083c0cba1 fix filtering by addr in handleNotificationsItems() 2018-12-02 10:58:54 +01:00
Mario Vavti
defa2d9df1 make pdf preview 100% width and 300px height to match it openstreetmaps preview
(cherry picked from commit df84352385)
2018-12-02 10:18:37 +01:00
Mario Vavti
05c422ef23 redbasic sticky aside fixes
(cherry picked from commit 8d4f6a7865)
2018-12-02 10:18:20 +01:00
zotlabs
51d274961b typo
(cherry picked from commit 6f22e47feb)
2018-12-02 10:18:05 +01:00
zotlabs
4b4cc04897 allow notification filtering by name or addr
(cherry picked from commit c6acb6191c)
2018-12-02 10:17:45 +01:00
zotlabs
4bf3d4d87a attached photo permissions regression
(cherry picked from commit 6cade7d935)
2018-12-02 10:17:29 +01:00
Manuel Jiménez Friaza
71cc980e96 Revision 1 doc/es-es/about/about.bb
(cherry picked from commit 5ac08ec3aa)

(cherry picked from commit 37d563c30e)
2018-12-02 10:16:50 +01:00
Mario
58c0b81908 use flex for the default template
(cherry picked from commit 3775be4ce9)
2018-12-02 10:16:24 +01:00
M. Dent
3b42bd43ab Do not store serialized pconfig value received via to Module/Pconfig.php
(cherry picked from commit 6b02c664fb)
2018-12-02 10:15:55 +01:00
Mario
a151532ffa update jquery-file-upload and psr-log via composer
(cherry picked from commit c7ae3fdc9a)
2018-12-02 10:14:58 +01:00
Mario
a0d1ce77dc update imagesloaded to version 4.1.4 via composer
(cherry picked from commit c667572d3e)
2018-12-02 10:14:37 +01:00
Manuel Jiménez Friaza
863cae1bab Update es-es
(cherry picked from commit ca98a566ee)
2018-12-02 10:13:43 +01:00
zotlabs
4010ea814a fix mastodon tag notifications (again)
(cherry picked from commit 8e71324514)
2018-12-02 10:13:12 +01:00
zotlabs
8e25c091f4 no mention notifications from mastodon (and pleroma)
(cherry picked from commit ea235c0c67)
2018-12-02 10:12:44 +01:00
Mario Vavti
0bba9482df fix call to undefined function 2018-11-21 13:21:29 +01:00
Mario Vavti
f8a8559523 fix typo which prevented propagation of comments
(cherry picked from commit 0c94747ab1)
2018-11-20 10:09:46 +01:00
Mario Vavti
1044e8e91a version 3.8.5 2018-11-19 11:12:32 +01:00
Mario Vavti
ba4b1cb5af Merge branch 'master' of https://framagit.org/hubzilla/core 2018-11-19 11:10:36 +01:00
Mario Vavti
5cb4cdaa5e changelog 2018-11-19 11:10:22 +01:00
Mario
7be1d9e45a Merge branch 'patch-20181118a' into 'dev'
Patch 20181118a - fix delayed publication of posts

See merge request hubzilla/core!1398

(cherry picked from commit f34af496ec)

3787c490 Fix: delayed items propagate before publication on cloned channels
2018-11-19 10:45:01 +01:00
Mario Vavti
ae97649948 update sql schemas to include update column in pconfig table 2018-11-19 10:42:18 +01:00
Mario Vavti
f15e32d063 recalculate photo filesize when rotating an image 2018-11-17 09:41:26 +01:00
Mario Vavti
afc75af62f strlen($this->imageString()) does not return the correct size when dealing with os_storage images. use filesize() instead. 2018-11-16 22:14:11 +01:00
Mario
2778a7220f Merge branch 'master' into 'master'
delivery issue

See merge request hubzilla/core!1397
2018-11-16 10:29:45 +01:00
zotlabs
26f593afaa delivery issue 2018-11-15 13:52:25 -08:00
Mario Vavti
beac45b075 more changelog 2018-11-14 11:20:39 +01:00
Mario Vavti
dfc5159aa3 Merge branch 'dev' 2018-11-14 11:12:20 +01:00
Mario Vavti
886cdb440b changelog and version 2018-11-14 11:08:25 +01:00
Mario
6ed9443972 Merge branch 'patch-20181113b' into 'dev'
Patch 20181113b

See merge request hubzilla/core!1395
2018-11-14 09:30:54 +01:00
Mario
08e0f172de Merge branch 'dev' into 'dev'
Remove unneccessary fetch_image_from_url() function

See merge request hubzilla/core!1393
2018-11-14 09:30:28 +01:00
DM42.Net (Matt Dent)
f1d168f781 Fix double escaping after xss fix 2018-11-13 23:06:00 -05:00
DM42.Net (Matt Dent)
302d9796c4 Revert "Filter search box before display"
This reverts commit 35e66770be.
2018-11-13 22:59:36 -05:00
M. Dent
1260887fa7 Merge branch 'patch-20181113a' into 'dev'
Patch 20181113a

See merge request hubzilla/core!1394
2018-11-14 03:21:32 +01:00
DM42.Net (Matt Dent)
ce8073d25e Merge remote-tracking branch red/master into patch-20181113a. Add Mike's fix to search xss and Superblock fix. 2018-11-13 20:19:12 -05:00
zotlabs
31f4d9066b xss in search 2018-11-13 14:23:56 -08:00
DM42.Net (Matt Dent)
35e66770be Filter search box before display 2018-11-13 17:20:21 -05:00
Max Kostikov
cf2f7f2132 Update Photo.php 2018-11-13 12:52:35 +01:00
Max Kostikov
a145559662 Remove uneccessary include/photos.php 2018-11-13 11:45:18 +01:00
Max Kostikov
d029e3dc16 Text formatting in Photo.php 2018-11-13 11:39:42 +01:00
Max Kostikov
286326a98e Replace fetch_image_from_url() with z_fetch_url() 2018-11-13 11:38:49 +01:00
Max Kostikov
2f59d78737 Remove fetch_image_from_url() because of functions duplicate 2018-11-13 11:37:32 +01:00
Max Kostikov
adf4782076 Merge branch 'revert-6375f2d7' into 'dev'
Revert "Replace fetch_image_from_url() with z_fetch_url()"

See merge request hubzilla/core!1392
2018-11-13 11:36:02 +01:00
Max Kostikov
b38ffef2be Revert "Replace fetch_image_from_url() with z_fetch_url()"
This reverts commit 6375f2d73a
2018-11-13 11:25:46 +01:00
Max Kostikov
6375f2d73a Replace fetch_image_from_url() with z_fetch_url() 2018-11-13 11:25:14 +01:00
M. Dent
a7d3a49171 Merge branch 'fix-activity-filter-widget' into 'dev'
use the correct javascript function for this case

See merge request hubzilla/core!1390
2018-11-12 21:50:08 +01:00
M. Dent
920e7db709 Merge branch 'css-fixes' into 'dev'
css fixes

See merge request hubzilla/core!1391
2018-11-12 21:49:07 +01:00
zotlabs
4a6b45cf04 enotify::format hook for superblock 2018-11-12 11:13:36 -08:00
Mario Vavti
7bd60adfbe fix css issues in bbcode conversion and focus-light schema 2018-11-12 09:35:12 +01:00
Mario Vavti
c335719e8f use the correct javascript function for this case 2018-11-11 14:46:35 +01:00
Mario Vavti
d57cdf645e Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2018-11-11 14:01:25 +01:00
Mario
e47a96bf24 Merge branch 'dev' into 'dev'
Preserve photo modification date on edit

See merge request hubzilla/core!1389
2018-11-11 13:49:29 +01:00
Mario
daad607c7c Merge branch 'dev' into 'dev'
fix shared_header img expanding to 100% width when sharing a share

See merge request hubzilla/core!1387
2018-11-11 13:47:03 +01:00
Max Kostikov
29f1f9c872 Merge branch 'dev' into 'dev'
# Conflicts:
#   include/photo/photo_driver.php
2018-11-10 20:47:35 +01:00
Max Kostikov
a49cfa8142 Update photo_driver.php 2018-11-10 20:45:20 +01:00
Max Kostikov
b57d296adc Preserve photo modification date 2018-11-10 20:35:14 +01:00
Mario
01d8bd445e Merge branch 'dev' into 'dev'
Remove DNS check for database connection during installation...

See merge request hubzilla/core!1384
2018-11-10 15:02:27 +01:00
Mario Vavti
750d6f4be9 Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2018-11-10 12:22:09 +01:00
Max Kostikov
c6e14a696e Fixed wrong value assign on compare with 0 2018-11-10 11:56:34 +01:00
Max Kostikov
d34423fce9 Fixed wrong value assign on compare with 0 2018-11-10 11:53:49 +01:00
Mario
4999547f87 Merge branch 'dev' into 'dev'
Preserve received image modification date on caching

See merge request hubzilla/core!1386
2018-11-10 11:47:20 +01:00
Mario Vavti
fc5dc9717a fix shared_header img expanding to 100% width when sharing a share 2018-11-10 11:31:06 +01:00
Max Kostikov
d20759c141 Do not return default images from vCard 2018-11-10 11:11:23 +01:00
Max Kostikov
f7b00c62a4 Remove unnecessary Zulu timezone mention 2018-11-10 10:05:28 +01:00
Max Kostikov
32873ce70d Preserve received image modification date on caching 2018-11-09 22:20:41 +01:00
Max Kostikov
dc59561a95 Fixed timezone conversion 2018-11-09 22:17:11 +01:00
Mario
4bf3fdd898 Merge branch 'patch-1' into 'dev'
Return image modification date on remote fetch for caching

See merge request hubzilla/core!1383
2018-11-09 16:51:36 +01:00
Andrew Manning
108a892a11 Remove DNS check for database connection during installation. Causes friction with Docker deployment. 2018-11-09 05:31:55 -05:00
Max Kostikov
2c4bd9a3fe Workaround for local resource path to photo from Diaspora 2018-11-09 10:03:58 +01:00
Max Kostikov
098ec1abb4 remove image type double guess by checking HTTP headers 2018-11-08 22:43:17 +01:00
Max Kostikov
17cf824545 Return image modification date using HTTP 'Last-Modified' and '304 Not Modified' on remote fetch for caching 2018-11-08 18:00:18 +01:00
M. Dent
e35f5d3c93 Merge branch 'fix-photo' into 'dev'
Fix photo

See merge request hubzilla/core!1382
2018-11-08 13:09:05 +01:00
Mario
f4f98e5856 Merge branch 'patch-1' into 'fix-photo'
Correct "Content-Length:" calculation added

See merge request mario/core!1
2018-11-08 12:13:00 +01:00
Max Kostikov
dc0335d1d5 Correct "Content-Length:" calculation added 2018-11-08 11:53:27 +01:00
M. Dent
6013814cf4 Merge branch 'fix-photo' into 'dev'
$data only contains the link to the image if the image is in os storage. The…

See merge request hubzilla/core!1379
2018-11-08 11:25:36 +01:00
Mario Vavti
e0a0570cc4 $data only contains the link to the image if the image is in os storage. The size is calculatet wrong in this case and the download fails. rely on filesize from the db for content-length 2018-11-08 11:06:44 +01:00
Mario
61deb4fcfd Merge branch 'patch-1' into 'dev'
Disable image caching if personal or group permissions enabled

See merge request hubzilla/core!1377
2018-11-08 10:25:11 +01:00
Mario Vavti
7c4c60425b Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2018-11-08 10:16:17 +01:00
Mario Vavti
302f49baf2 provide a function to log to syslog 2018-11-08 10:12:33 +01:00
Max Kostikov
3f6cd5a663 Disable image caching if personal or group permissions enabled 2018-11-07 19:52:38 +01:00
M. Dent
1b232041c9 Merge branch 'patch-1' into 'dev'
Added `If-Modified-Since` header support for better image caching and fixed absent 404 for photos

See merge request hubzilla/core!1375
2018-11-07 18:22:55 +01:00
Max Kostikov
eaf117cce1 Added If-Modified-Since header support for better image caching and fixed absent 404 for photos 2018-11-07 18:22:55 +01:00
zotlabs
7148311953 Merge branch 'dev' of https://framagit.org/hubzilla/core into xdev_merge 2018-11-07 01:43:26 -08:00
Mario Vavti
c23dfa0d23 Merge remote-tracking branch 'mike/master' into dev 2018-11-07 10:15:40 +01:00
Mario Vavti
b08de33b0b fix es-es hstrings.php 2018-11-07 10:02:24 +01:00
Mario
fc1d8c0138 Merge branch 'revert-40d9277e' into 'dev'
Revert "remove 'Expiries' HTTP header"

See merge request hubzilla/core!1372
2018-11-07 09:36:30 +01:00
Max Kostikov
a5a77d1e7c Revert "remove 'Expiries' HTTP header"
This reverts commit 40d9277ef3
2018-11-07 08:41:32 +01:00
zotlabs
f57fcefe6b signature issue 2018-11-06 21:45:43 -08:00
M. Dent
6c6dca05e7 Merge branch 'patch-25' into 'dev'
'Last-Modified' and 'Content-Length' HTTP headers added for better image caching

See merge request hubzilla/core!1369
2018-11-06 19:25:38 +01:00
M. Dent
97b4a31b16 Merge branch 'patch-26' into 'dev'
New plural functions for JavaScript compatibility

See merge request hubzilla/core!1370
2018-11-06 18:26:58 +01:00
Max Kostikov
40d9277ef3 remove 'Expiries' HTTP header 2018-11-06 16:22:34 +01:00
Max Kostikov
009044b71e Update hmessages.po 2018-11-06 14:58:06 +01:00
Max Kostikov
4760a3f3e8 Update hmessages.po 2018-11-06 14:57:12 +01:00
Max Kostikov
3302012c02 New pt-br plural function for JavaScript compatibility 2018-11-06 14:55:58 +01:00
Max Kostikov
812c5a314f New nl plural function for JavaScript compatibility 2018-11-06 14:55:21 +01:00
Max Kostikov
c2da8c3fd4 New nb-no plural function for JavaScript compatibility 2018-11-06 14:54:49 +01:00
Max Kostikov
aa78640491 New it plural function for JavaScript compatibility 2018-11-06 14:54:06 +01:00
Max Kostikov
7c49688e1b New he plural function for JavaScript compatibility 2018-11-06 14:53:29 +01:00
Max Kostikov
dbe10c7965 New fi plural function for JavaScript compatibility 2018-11-06 14:52:58 +01:00
Max Kostikov
f1f5107282 New es plural function for JavaScript compatibility 2018-11-06 14:52:23 +01:00
Max Kostikov
cc06250bf8 New fr plural function for JavaScript compatibility 2018-11-06 14:50:37 +01:00
Max Kostikov
af1ea7f495 New plural function for JavaScript compatibility 2018-11-06 14:48:58 +01:00
Max Kostikov
3491c488d3 Update Photo.php 2018-11-06 13:51:01 +01:00
Max Kostikov
1828b6daab Update Photo.php 2018-11-06 13:41:41 +01:00
Max Kostikov
c26f45b7c2 Update Photo.php 2018-11-06 13:39:36 +01:00
Max Kostikov
e116b90116 'Last-Modified' and 'Content-Length' HTTP headers added for better image caching 2018-11-06 13:37:50 +01:00
zotlabs
43a5f928ba these changes needed to ensure cloning/syncing works in the future to non-zot6 enabled servers after the (coming) zot6 schema updates. This should probably be on a fast track to master branch 2018-11-05 16:57:32 -08:00
M. Dent
873fa16517 Merge branch 'patch-23' into 'dev'
Use modern get_config() syntax

See merge request hubzilla/core!1368
2018-11-06 01:27:06 +01:00
Max Kostikov
f7ce374a28 Update Photo.php 2018-11-05 21:26:10 +01:00
Max Kostikov
2dd124d09e Use modern get_config() syntax 2018-11-05 21:25:08 +01:00
Mario
d6523c67a6 Merge branch 'patch-20181028a' into 'dev'
Add timestamp to pconfig

See merge request hubzilla/core!1355
2018-11-05 10:40:29 +01:00
Mario Vavti
a9fd3608ea version 3.8.3 2018-11-05 10:26:59 +01:00
Mario Vavti
b25cace3ea update changelog 2018-11-05 10:25:57 +01:00
Mario Vavti
4320f047db update changelog and bump version 2018-11-05 10:22:56 +01:00
Mario Vavti
b4b3e7b9a4 update linkinfo from dev 2018-11-05 09:59:25 +01:00
Mario Vavti
b6938da552 Merge remote-tracking branch 'mike/master' into dev 2018-11-05 09:56:52 +01:00
Mario Vavti
4830a1559d Merge branch 'dev' 2018-11-05 09:55:23 +01:00
Mario
92ea3ef720 Merge branch 'dev' into 'dev'
more fixes for forum notifications handling: do not count likes/dislikes if…

See merge request hubzilla/core!1367
2018-11-05 09:42:07 +01:00
zotlabs
73d2719330 debug zot6 discovery 2018-11-04 19:35:55 -08:00
zotlabs
af82aab3a6 Merge branch 'dev' of https://framagit.org/hubzilla/core into xdev_merge 2018-11-04 13:58:02 -08:00
zotlabs
51b4b6216f z6 updates to owa, linkinfo improved image detection 2018-11-04 13:56:32 -08:00
Mario Vavti
de32b0bba5 more fixes for forum notifications handling: do not count likes/dislikes if likes notifications are disabled and also do not show like activities when clicking a forum notification and like notifications are disabled 2018-11-03 20:53:23 +01:00
Mario
de0fab78ed Merge branch 'dev' into 'dev'
Fixed typo at view/es-es/hstrings.php

See merge request hubzilla/core!1366
2018-11-03 20:11:14 +01:00
Manuel Jiménez Friaza
71425c3b23 Fixed typo at view/es-es/hstrings.php 2018-11-03 19:19:01 +01:00
Mario
75f7b1e261 Merge branch 'patch-3' into 'dev'
Update hmessages.po

See merge request hubzilla/core!1365
2018-11-03 13:22:34 +01:00
Mario
9af35d998f Merge branch 'patch-2' into 'dev'
Update hstrings.php

See merge request hubzilla/core!1364
2018-11-03 13:21:53 +01:00
Mario
34e3f3907a Merge branch 'patch-22' into 'dev'
More precise content encoding detection on conversion

See merge request hubzilla/core!1363
2018-11-03 13:21:22 +01:00
Max Kostikov
46b0510b99 Update Linkinfo.php 2018-11-03 10:41:31 +01:00
Max Kostikov
a7624ea48b Update Linkinfo.php 2018-11-03 00:10:05 +01:00
Max Kostikov
2f3b4a7aaf Update Linkinfo.php 2018-11-03 00:01:15 +01:00
Max Kostikov
a9bbe0b128 Update Linkinfo.php 2018-11-02 22:40:48 +01:00
Max Kostikov
0d9d0a4b70 more precise codepage detection 2018-11-02 22:37:53 +01:00
gia vec
8235d0bd50 Update hmessages.po 2018-11-02 19:41:07 +01:00
gia vec
c2e01bedc5 Update hstrings.php 2018-11-02 19:27:11 +01:00
Max Kostikov
32c4614a32 Workaround for incorrect ISO-8859-5 encoded content conversion 2018-11-02 10:52:52 +01:00
Mario
24ae6c91ea Merge branch 'patch-21' into 'dev'
Fix wrong image resize for some external images

See merge request hubzilla/core!1362
2018-11-02 10:20:18 +01:00
M.Dent
346a4f5933 strpos needs to test with ===0 not ==0 2018-11-01 20:23:22 -04:00
Max Kostikov
c6551336c8 Fix wrong image resize for some external images 2018-11-01 21:50:36 +01:00
Mario Vavti
3dab0d365d css fix for reshared-content images and whitespace 2018-10-31 13:20:09 +01:00
Mario Vavti
0252bac4ba Merge branch 'dev' of https://framagit.org/hubzilla/core into dev 2018-10-31 09:39:10 +01:00
Mario
b468069875 Merge branch 'patch-20' into 'dev'
Beautiful embedding for Hubzilla links

See merge request hubzilla/core!1360
2018-10-31 09:36:09 +01:00
Mike Macgirvin
7e1f431eca yet another blueimp vulnerability. Move to composer. 2018-10-31 15:56:08 +11:00
zotlabs
70c55da1df Merge branch 'dev' of https://framagit.org/hubzilla/core into xdev_merge 2018-10-30 18:11:49 -07:00
M. Dent
f9ab7647dd Merge branch 'composer-updates' into 'dev'
update html_to_markdown, smarty and sabredav libs via composer

See merge request hubzilla/core!1361
2018-10-31 01:32:44 +01:00
zotlabs
623aa7ea48 remove primary/clone counts from admin summary. The last checkins should fix this count "eventually" but the information has little direct value and may require location information for a local channel to change before it is actually corrected. 2018-10-30 17:30:59 -07:00
M. Dent
046d264688 Merge branch 'forum-ping' into 'dev'
fix forum ping results - the term query requires xchan_name instead of…

See merge request hubzilla/core!1358
2018-10-31 01:25:41 +01:00
M. Dent
944e168120 Merge branch 'wikilist-widget' into 'dev'
allow wiki_list widget to be used in any page

See merge request hubzilla/core!1359
2018-10-31 01:24:32 +01:00
zotlabs
9594105e57 typo 2018-10-30 17:21:39 -07:00
zotlabs
675343f575 issue syncing the channel_primary setting which shows up as a wrong count on the admin summary page 2018-10-30 17:18:15 -07:00
Mario Vavti
fc6ff45c49 fix another markdown test 2018-10-30 22:51:52 +01:00
Mario Vavti
b4bac88c39 fix markdown tests 2018-10-30 22:37:41 +01:00
Mario Vavti
c622ba84b9 really fix html2markdown() - when using environment, we must set the defaults 2018-10-30 22:16:37 +01:00
Max Kostikov
339f95c647 Update oembed.php 2018-10-30 16:49:48 +01:00
Max Kostikov
ec67e0ab22 Beautiful embedding for Hubzilla links 2018-10-30 15:38:19 +01:00
Mario Vavti
0b371c8103 fix html2markdown() and re-enable previously failing tests 2018-10-30 13:55:08 +01:00
Mario Vavti
2192ea6fdf update html_to_markdown, smarty and sabredav libs via composer 2018-10-30 12:12:07 +01:00
M.Dent
0060f88c45 Add tracking of deleted pconfig variables 2018-10-29 23:04:13 -04:00
Mario Vavti
1eac4db491 fix forum ping results - the term query requires xchan_name instead of xchan_hash. also improve the query itself - item_permission_sql() is redundant here since we always deal with local_channel() and use count(id) instead of sum(item_unseen) to get the unseen count 2018-10-29 23:01:13 +01:00
Mario Vavti
0d2c3be367 allow wiki_list widget to be used in any page 2018-10-29 22:55:24 +01:00
M.Dent
1241e778f9 Fix to set update time in pconfig on update 2018-10-28 17:30:22 -04:00
M.Dent
3ab0ef1902 Add timestamp and associated logic to pconfig 2018-10-28 17:23:31 -04:00
M.Dent
c7c35b8b5a DB Updates to prep for pconfig timestamps. 2018-10-28 17:20:29 -04:00
404 changed files with 10038 additions and 6412 deletions

View File

@@ -1,3 +1,76 @@
Hubzilla 3.8.7 (2018-12-14)
- Fix issue with linkdropper in comment area
- Fix regression wit app ordering
- Fix return if readImnageBlob() throws an exception
- Introduce photo_view_filter hook
- Fix home notifications not expanding in certain situations
- Fix for dark schema
- Fix total identities restriction
- Fix article page title not updating if article has no title
- Gallery: the gallery app will now act as the full-size photo viewer in /photos if installed
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
- Various css fixes
- Improve photo cache handling
- Provide a function hz_syslog() to log to syslog
- Fix request_target in z_post_url()
- Fix plural handling for various languages
- Some preparatory work for zot6
- Fix warning in gallery addon
- Fix date issue on xchan photo update in diaspora and pubcrawl addons
- Fix typos in startpage addon
- Improve activitypub addressing
- Fix taxonomy in activitypub direct messages
- Fix syntax error in diaspora addon
- New e-learning addon flashcards
- Remove DNS check for database connection during installation
- Implement timestamps for pconfig
Hubzilla 3.8.3 (2018-11-05)
- Do not count likes in forum notifications if likes notifications are disabled
- Fix typo in spanish translation which broke javascript
- Improve linkinfo charset handling and image detection
- Fix wrong image resize for some external images
- Move blueimp upload lib to composer and update to version 9.25
- Remove primary/clone counts from admin summary until we have a mechanism to update the fixed counts
- Fix html2markdown() and re-enable previously failing tests
- Improve look of oembed content for Hubzilla links
- Fix forum notifications count not correct
- Fix gallery addon which broke mod apps in some situations
- Fix wiki_list widget not working on every page respectively level
Hubzilla 3.8.2 (2018-10-29)
- Merge unmerged changes from dev into master
- Fix issues with forum handling in mod network and ping

View File

@@ -808,12 +808,14 @@ class Apps {
return($r);
}
static public function app_order($uid,$apps) {
static public function app_order($uid,$apps,$menu) {
if(! $apps)
return $apps;
$x = (($uid) ? get_pconfig($uid,'system','app_order') : get_config('system','app_order'));
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$x = (($uid) ? get_pconfig($uid,'system',$conf) : get_config('system',$conf));
if(($x) && (! is_array($x))) {
$y = explode(',',$x);
$y = array_map('trim',$y);
@@ -850,19 +852,25 @@ class Apps {
return false;
}
static function moveup($uid,$guid) {
static function moveup($uid,$guid,$menu) {
$syslist = array();
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$list = self::app_list($uid, false, [ $menu ]);
if($list) {
foreach($list as $li) {
$syslist[] = self::app_encode($li);
$papp = self::app_encode($li);
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
continue;
$syslist[] = $papp;
}
}
self::translate_system_apps($syslist);
usort($syslist,'self::app_name_compare');
$syslist = self::app_order($uid,$syslist);
$syslist = self::app_order($uid,$syslist,$menu);
if(! $syslist)
return;
@@ -887,23 +895,29 @@ class Apps {
$narr[] = $x['name'];
}
set_pconfig($uid,'system','app_order',implode(',',$narr));
set_pconfig($uid,'system',$conf,implode(',',$narr));
}
static function movedown($uid,$guid) {
static function movedown($uid,$guid,$menu) {
$syslist = array();
$list = self::app_list($uid, false, ['nav_featured_app', 'nav_pinned_app']);
$conf = (($menu === 'nav_featured_app') ? 'app_order' : 'app_pin_order');
$list = self::app_list($uid, false, [ $menu ]);
if($list) {
foreach($list as $li) {
$syslist[] = self::app_encode($li);
$papp = self::app_encode($li);
if($menu !== 'nav_pinned_app' && strpos($papp['categories'],'nav_pinned_app') !== false)
continue;
$syslist[] = $papp;
}
}
self::translate_system_apps($syslist);
usort($syslist,'self::app_name_compare');
$syslist = self::app_order($uid,$syslist);
$syslist = self::app_order($uid,$syslist,$menu);
if(! $syslist)
return;
@@ -928,7 +942,7 @@ class Apps {
$narr[] = $x['name'];
}
set_pconfig($uid,'system','app_order',implode(',',$narr));
set_pconfig($uid,'system',$conf,implode(',',$narr));
}

View File

@@ -825,9 +825,10 @@ class Enotify {
// convert this logic into a json array just like the system notifications
return array(
$x = array(
'notify_link' => $item['llink'],
'name' => $item['author']['xchan_name'],
'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']),
@@ -835,9 +836,19 @@ class Enotify {
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
'notify_id' => 'undefined',
'thread_top' => (($item['item_thread_top']) ? true : false),
'message' => strip_tags(bbcode($itemem_text))
'message' => strip_tags(bbcode($itemem_text)),
// these are for the superblock addon
'hash' => $item['author']['xchan_hash'],
'uid' => local_channel(),
'display' => true
);
call_hooks('enotify_format',$x);
if(! $x['display']) {
return [];
}
return $x;
}
}

View File

@@ -7,16 +7,10 @@ namespace Zotlabs\Lib;
*
*/
use Zotlabs\Lib\DReport;
use Zotlabs\Lib\Enotify;
use Zotlabs\Lib\Group;
use Zotlabs\Lib\Libsync;
use Zotlabs\Lib\Libzotdir;
use Zotlabs\Lib\System;
use Zotlabs\Lib\MessageFilter;
use Zotlabs\Lib\Queue;
use Zotlabs\Lib\Zotfinger;
use Zotlabs\Web\HTTPSig;
use Zotlabs\Zot6\HTTPSig;
use Zotlabs\Access\Permissions;
use Zotlabs\Access\PermissionLimits;
use Zotlabs\Daemon\Master;
require_once('include/crypto.php');
@@ -211,9 +205,10 @@ class Libzot {
if($channel) {
$headers = [
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
'Content-type' => 'application/x-zot+json'
'X-Zot-Token' => random_string(),
'Digest' => HTTPSig::generate_digest_header($data),
'Content-type' => 'application/x-zot+json',
'(request-target)' => 'post ' . get_request_string($url)
];
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false,'sha512',
@@ -378,13 +373,13 @@ class Libzot {
else {
// if we were just granted read stream permission and didn't have it before, try to pull in some posts
if((! $old_read_stream_perm) && (intval($permissions['view_stream'])))
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$r[0]['abook_id']));
Master::Summon([ 'Onepoll', $r[0]['abook_id'] ]);
}
}
else {
$p = \Zotlabs\Access\Permissions::connect_perms($channel['channel_id']);
$my_perms = \Zotlabs\Access\Permissions::serialise($p['perms']);
$p = Permissions::connect_perms($channel['channel_id']);
$my_perms = Permissions::serialise($p['perms']);
$automatic = $p['automatic'];
@@ -424,8 +419,8 @@ class Libzot {
);
if($new_connection) {
if(! \Zotlabs\Access\Permissions::PermsCompare($new_perms,$previous_perms))
\Zotlabs\Daemon\Master::Summon(array('Notifier','permissions_create',$new_connection[0]['abook_id']));
if(! Permissions::PermsCompare($new_perms,$previous_perms))
Master::Summon([ 'Notifier', 'permissions_create', $new_connection[0]['abook_id'] ]);
Enotify::submit(
[
'type' => NOTIFY_INTRO,
@@ -438,7 +433,7 @@ class Libzot {
if(intval($permissions['view_stream'])) {
if(intval(get_pconfig($channel['channel_id'],'perm_limits','send_stream') & PERMS_PENDING)
|| (! intval($new_connection[0]['abook_pending'])))
\Zotlabs\Daemon\Master::Summon(array('Onepoll',$new_connection[0]['abook_id']));
Master::Summon([ 'Onepoll', $new_connection[0]['abook_id'] ]);
}
@@ -975,39 +970,45 @@ class Libzot {
$x = json_decode($x,true);
}
if(! $x['success']) {
// handle remote validation issues
$b = q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
dbesc(($x['message']) ? $x['message'] : 'unknown delivery error'),
dbesc(datetime_convert()),
dbesc($outq['outq_hash'])
);
if(! is_array($x)) {
btlogger('failed communication - no response');
}
if(array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) {
foreach($x['delivery_report'] as $xx) {
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc($xx['sender'])
);
}
if($x) {
if(! $x['success']) {
// handle remote validation issues
$b = q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s'",
dbesc(($x['message']) ? $x['message'] : 'unknown delivery error'),
dbesc(datetime_convert()),
dbesc($outq['outq_hash'])
);
}
// we have a more descriptive delivery report, so discard the per hub 'queue' report.
if(is_array($x) && array_key_exists('delivery_report',$x) && is_array($x['delivery_report'])) {
foreach($x['delivery_report'] as $xx) {
call_hooks('dreport_process',$xx);
if(is_array($xx) && array_key_exists('message_id',$xx) && DReport::is_storable($xx)) {
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s','%s','%s','%s','%s' ) ",
dbesc($xx['message_id']),
dbesc($xx['location']),
dbesc($xx['recipient']),
dbesc($xx['name']),
dbesc($xx['status']),
dbesc(datetime_convert($xx['date'])),
dbesc($xx['sender'])
);
}
}
q("delete from dreport where dreport_queue = '%s' ",
dbesc($outq['outq_hash'])
);
// we have a more descriptive delivery report, so discard the per hub 'queue' report.
q("delete from dreport where dreport_queue = '%s' ",
dbesc($outq['outq_hash'])
);
}
}
// update the timestamp for this site
q("update site set site_dead = 0, site_update = '%s' where site_url = '%s'",
@@ -1092,13 +1093,27 @@ class Libzot {
return;
}
$message_request = ((array_key_exists('message_id',$env)) ? true : false);
if($message_request)
logger('processing message request');
$message_request = false;
$has_data = array_key_exists('data',$env) && $env['data'];
$data = (($has_data) ? $env['data'] : false);
$AS = null;
if($env['encoding'] === 'activitystreams') {
$AS = new ActivityStreams($data);
if(! $AS->is_valid()) {
logger('Activity rejected: ' . print_r($data,true));
return;
}
$arr = Activity::decode_note($AS);
logger($AS->debug());
}
$deliveries = null;
if(array_key_exists('recipients',$env) && count($env['recipients'])) {
@@ -1140,7 +1155,7 @@ class Libzot {
// and who are allowed to see them based on the sender's permissions
// @fixme;
$deliveries = self::public_recips($env);
$deliveries = self::public_recips($env,$AS);
}
@@ -1157,49 +1172,43 @@ class Libzot {
if(in_array($env['type'],['activity','response'])) {
if($env['encoding'] === 'zot') {
$arr = get_item_elements($data);
$v = validate_item_elements($data,$arr);
if(! $v['success']) {
logger('Activity rejected: ' . $v['message'] . ' ' . print_r($data,true));
return;
}
$arr = Activity::decode_note($AS);
//logger($AS->debug());
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($AS->actor['id'])
);
if($r) {
$arr['author_xchan'] = $r[0]['hubloc_hash'];
}
elseif($env['encoding'] === 'activitystreams') {
$AS = new \Zotlabs\Lib\ActivityStreams($data);
if(! $AS->is_valid()) {
logger('Activity rejected: ' . print_r($data,true));
return;
}
$arr = \Zotlabs\Lib\Activity::decode_note($AS);
logger($AS->debug());
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($env['sender'])
);
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($AS->actor['id'])
);
if($r) {
$arr['author_xchan'] = $r[0]['hubloc_hash'];
}
// @fixme (in individual delivery, change owner if needed)
// in individual delivery, change owner if needed
if($s) {
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
}
else {
$arr['owner_xchan'] = $env['sender'];
if($private) {
$arr['item_private'] = true;
}
// @fixme - spoofable
if($AS->data['hubloc']) {
$arr['item_verified'] = true;
}
if($AS->data['signed_data']) {
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
}
}
if($private) {
$arr['item_private'] = true;
}
// @fixme - spoofable
if($AS->data['hubloc']) {
$arr['item_verified'] = true;
}
if($AS->data['signed_data']) {
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
}
logger('Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
logger('Activity recipients: ' . print_r($deliveries,true), LOGGER_DATA, LOG_DEBUG);
@@ -1225,15 +1234,31 @@ class Libzot {
}
static function is_top_level($env) {
static function is_top_level($env,$act) {
if($env['encoding'] === 'zot' && array_key_exists('flags',$env) && in_array('thread_parent', $env['flags'])) {
return true;
}
if($env['encoding'] === 'activitystreams') {
if(array_key_exists('inReplyTo',$env['data']) && $env['data']['inReplyTo']) {
if($act) {
if(in_array($act->type, ['Like','Dislike'])) {
return false;
}
return true;
$x = self::find_parent($env,$act);
if($x === $act->id || $x === $act->obj['id']) {
return true;
}
}
return false;
}
static function find_parent($env,$act) {
if($act) {
if(in_array($act->type, ['Like','Dislike'])) {
return $act->obj['id'];
}
if($act->parent_id) {
return $act->parent_id;
}
}
return false;
}
@@ -1255,7 +1280,7 @@ class Libzot {
* @return NULL|array
*/
static function public_recips($msg) {
static function public_recips($msg, $act) {
require_once('include/channel.php');
@@ -1269,7 +1294,7 @@ class Libzot {
$perm = 'send_stream';
if(self::is_top_level($msg)) {
if(self::is_top_level($msg,$act)) {
$check_mentions = true;
}
}
@@ -1301,9 +1326,9 @@ class Libzot {
if($check_mentions) {
// It's a top level post. Look at the tags. See if any of them are mentions and are on this hub.
if(array_path_exists('data/object/tag',$msg)) {
if(is_array($msg['data']['object']['tag']) && $msg['data']['object']['tag']) {
foreach($msg['data']['object']['tag'] as $tag) {
if($act && $act->obj) {
if(is_array($act->obj['tag']) && $act->obj['tag']) {
foreach($act->obj['tag'] as $tag) {
if($tag['type'] === 'Mention' && (strpos($tag['href'],z_root()) !== false)) {
$address = basename($tag['href']);
if($address) {
@@ -1325,9 +1350,12 @@ class Libzot {
// everybody that stored a copy of the parent. This way we know we're covered. We'll check the
// comment permissions when we deliver them.
if(array_path_exists('data/inReplyTo',$msg)) {
$z = q("select owner_xchan as hash from item where parent_mid = '%s' ",
dbesc($msg['data']['inReplyTo'])
$thread_parent = self::find_parent($msg,$act);
if($thread_parent) {
$z = q("select channel_hash as hash from channel left join item on channel.channel_id = item.uid where ( item.thr_parent = '%s' OR item.parent_mid = '%s' ) ",
dbesc($thread_parent),
dbesc($thread_parent)
);
if($z) {
foreach($z as $zv) {
@@ -1341,7 +1369,7 @@ class Libzot {
// It's a bit of work since it's a multi-dimensional array
if($r) {
$r = array_unique($r);
$r = array_values(array_unique($r));
}
logger('public_recips: ' . print_r($r,true), LOGGER_DATA, LOG_DEBUG);
@@ -1378,7 +1406,7 @@ class Libzot {
$local_public = $public;
$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
$channel = channelx_by_hash($d);
@@ -1413,7 +1441,7 @@ class Libzot {
$local_public = true;
$r = q("select xchan_selfcensored from xchan where xchan_hash = '%s' limit 1",
dbesc($sender['hash'])
dbesc($sender)
);
// don't import sys channel posts from selfcensored authors
if($r && (intval($r[0]['xchan_selfcensored']))) {
@@ -1441,11 +1469,30 @@ class Libzot {
$arr['item_wall'] = 0;
}
if((! perm_is_allowed($channel['channel_id'],$sender,$perm)) && (! $tag_delivery) && (! $local_public)) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
$friendofriend = false;
if ((! $tag_delivery) && (! $local_public)) {
$allowed = (perm_is_allowed($channel['channel_id'],$sender,$perm));
if((! $allowed) && $perm === 'post_comments') {
$parent = q("select * from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
if ($parent) {
$allowed = can_comment_on_post($d,$parent[0]);
}
}
if($request) {
$allowed = true;
$friendofriend = true;
}
if (! $allowed) {
logger("permission denied for delivery to channel {$channel['channel_id']} {$channel['channel_address']}");
$DR->update('permission denied');
$result[] = $DR->get();
continue;
}
}
if($arr['mid'] != $arr['parent_mid']) {
@@ -1456,7 +1503,7 @@ class Libzot {
// As a side effect we will also do a preliminary check that we have the top-level-post, otherwise
// processing it is pointless.
$r = q("select route, id from item where mid = '%s' and uid = %d limit 1",
$r = q("select route, id, owner_xchan, item_private from item where mid = '%s' and uid = %d limit 1",
dbesc($arr['parent_mid']),
intval($channel['channel_id'])
);
@@ -1480,15 +1527,21 @@ class Libzot {
if((! $relay) && (! $request) && (! $local_public)
&& perm_is_allowed($channel['channel_id'],$sender,'send_stream')) {
\Zotlabs\Daemon\Master::Summon(array('Notifier', 'request', $channel['channel_id'], $sender, $arr['parent_mid']));
self::fetch_conversation($channel,$arr['parent_mid']);
}
continue;
}
if($relay) {
if($relay || $friendofriend || (intval($r[0]['item_private']) === 0 && intval($arr['item_private']) === 0)) {
// reset the route in case it travelled a great distance upstream
// use our parent's route so when we go back downstream we'll match
// with whatever route our parent has.
// Also friend-of-friend conversations may have been imported without a route,
// but we are now getting comments via listener delivery
// and if there is no privacy on this or the parent, we don't care about the route,
// so just set the owner and route accordingly.
$arr['route'] = $r[0]['route'];
$arr['owner_xchan'] = $r[0]['owner_xchan'];
}
else {
@@ -1546,13 +1599,13 @@ class Libzot {
$arr['aid'] = $channel['channel_account_id'];
$arr['uid'] = $channel['channel_id'];
$item_id = delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
$item_id = self::delete_imported_item($sender,$arr,$channel['channel_id'],$relay);
$DR->update(($item_id) ? 'deleted' : 'delete_failed');
$result[] = $DR->get();
if($relay && $item_id) {
logger('process_delivery: invoking relay');
\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
Master::Summon([ 'Notifier', 'relay', intval($item_id) ]);
$DR->update('relayed');
$result[] = $DR->get();
}
@@ -1662,7 +1715,7 @@ class Libzot {
if($relay && $item_id) {
logger('Invoking relay');
\Zotlabs\Daemon\Master::Summon(array('Notifier','relay',intval($item_id)));
Master::Summon([ 'Notifier', 'relay', intval($item_id) ]);
$DR->addto_update('relayed');
$result[] = $DR->get();
}
@@ -1676,6 +1729,98 @@ class Libzot {
return $result;
}
static public function fetch_conversation($channel,$mid) {
// Use Zotfinger to create a signed request
$a = Zotfinger::exec($mid,$channel);
logger('received conversation: ' . print_r($a,true), LOGGER_DATA);
if($a['data']['type'] !== 'OrderedCollection') {
return;
}
if(! intval($a['data']['totalItems'])) {
return;
}
$ret = [];
foreach($a['data']['orderedItems'] as $activity) {
$AS = new ActivityStreams($activity);
if(! $AS->is_valid()) {
logger('FOF Activity rejected: ' . print_r($activity,true));
continue;
}
$arr = Activity::decode_note($AS);
logger($AS->debug());
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($AS->actor['id'])
);
if(! $r) {
$y = import_author_xchan([ 'url' => $AS->actor['id'] ]);
if($y) {
$r = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($AS->actor['id'])
);
}
if(! $r) {
logger('FOF Activity: no actor');
continue;
}
}
if($AS->obj['actor'] && $AS->obj['actor']['id'] && $AS->obj['actor']['id'] !== $AS->actor['id']) {
$y = import_author_xchan([ 'url' => $AS->obj['actor']['id'] ]);
if(! $y) {
logger('FOF Activity: no object actor');
continue;
}
}
if($r) {
$arr['author_xchan'] = $r[0]['hubloc_hash'];
}
$s = q("select hubloc_hash from hubloc where hubloc_id_url = '%s' limit 1",
dbesc($a['signature']['signer'])
);
if($s) {
$arr['owner_xchan'] = $s[0]['hubloc_hash'];
}
else {
$arr['owner_xchan'] = $a['signature']['signer'];
}
// @fixme - spoofable
if($AS->data['hubloc']) {
$arr['item_verified'] = true;
}
if($AS->data['signed_data']) {
IConfig::Set($arr,'activitystreams','signed_data',$AS->data['signed_data'],false);
}
logger('FOF Activity received: ' . print_r($arr,true), LOGGER_DATA, LOG_DEBUG);
logger('FOF Activity recipient: ' . $channel['channel_hash'], LOGGER_DATA, LOG_DEBUG);
$result = self::process_delivery($arr['owner_xchan'],$arr, [ $channel['channel_hash'] ],false,false,true);
if ($result) {
$ret = array_merge($ret, $result);
}
}
return $ret;
}
/**
* @brief Remove community tag.
*
@@ -1900,7 +2045,7 @@ class Libzot {
foreach($deliveries as $d) {
$DR = new \Zotlabs\Lib\DReport(z_root(),$sender,$d,$arr['mid']);
$DR = new DReport(z_root(),$sender,$d,$arr['mid']);
$r = q("select * from channel where channel_hash = '%s' limit 1",
dbesc($d['hash'])
@@ -2112,7 +2257,8 @@ class Libzot {
if(intval($channel['channel_removed']) && $hub['hubloc_url'] === z_root())
$hub['hubloc_deleted'] = 1;
$ret[] = [
$z = [
'host' => $hub['hubloc_host'],
'address' => $hub['hubloc_addr'],
'id_url' => $hub['hubloc_id_url'],
@@ -2120,10 +2266,25 @@ class Libzot {
'url' => $hub['hubloc_url'],
'url_sig' => $hub['hubloc_url_sig'],
'site_id' => $hub['hubloc_site_id'],
'callback' => $hub['hubloc_callback'],
'callback' => $hub['hubloc_url'] . '/zot',
'sitekey' => $hub['hubloc_sitekey'],
'deleted' => (intval($hub['hubloc_deleted']) ? true : false)
];
// version compatibility tweaks
if(! strpos($z['url_sig'],'.')) {
$z['url_sig'] = 'sha256.' . $z['url_sig'];
}
if(! $z['id_url']) {
$z['id_url'] = $z['url'] . '/channel/' . substr($z['address'],0,strpos($z['address'],'@'));
}
if(! $z['site_id']) {
$z['site_id'] = Libzot::make_xchan_hash($z['url'],$z['sitekey']);
}
$ret[] = $z;
}
}
@@ -2331,6 +2492,10 @@ class Libzot {
// we may only end up with one; which results in posts with no author name or photo and are a bit
// of a hassle to repair. If either or both are missing, do a full discovery probe.
if(! array_key_exists('id',$x)) {
return import_author_activitypub($x);
}
$hash = self::make_xchan_hash($x['id'],$x['key']);
$desturl = $x['url'];
@@ -2502,7 +2667,7 @@ class Libzot {
}
else {
// check if it has characteristics of a public forum based on custom permissions.
$m = \Zotlabs\Access\Permissions::FilledAutoperms($e['channel_id']);
$m = Permissions::FilledAutoperms($e['channel_id']);
if($m) {
foreach($m as $k => $v) {
if($k == 'tag_deliver' && intval($v) == 1)
@@ -2584,13 +2749,13 @@ class Libzot {
];
$ret['channel_role'] = get_pconfig($e['channel_id'],'system','permissions_role','custom');
$ret['protocols'] = [ 'zot6' ];
$ret['searchable'] = $searchable;
$ret['adult_content'] = $adult_channel;
$ret['public_forum'] = $public_forum;
$ret['comments'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_comments'));
$ret['mail'] = map_scope(\Zotlabs\Access\PermissionLimits::Get($e['channel_id'],'post_mail'));
$ret['comments'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_comments'));
$ret['mail'] = map_scope(PermissionLimits::Get($e['channel_id'],'post_mail'));
if($deleted)
$ret['deleted'] = $deleted;

View File

@@ -57,6 +57,7 @@ class PConfig {
\App::$config[$uid][$c]['config_loaded'] = true;
}
\App::$config[$uid][$c][$k] = $rr['v'];
\App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
}
}
}
@@ -113,7 +114,7 @@ class PConfig {
* The value to store
* @return mixed Stored $value or false
*/
static public function Set($uid, $family, $key, $value) {
static public function Set($uid, $family, $key, $value, $updated=NULL) {
// this catches subtle errors where this function has been called
// with local_channel() when not logged in (which returns false)
@@ -130,29 +131,74 @@ class PConfig {
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
if (! $updated) {
$updated = datetime_convert();
}
$hash = hash('sha256',$family.':'.$key);
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
if (self::Get($uid, 'hz_delpconfig', $hash) > $updated) {
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
return self::Get($uid,$family,$key);
} else {
self::Delete($uid,'hz_delpconfig',$hash);
}
}
if(self::Get($uid, $family, $key) === false) {
if(! array_key_exists($uid, \App::$config))
\App::$config[$uid] = array();
if(! array_key_exists($family, \App::$config[$uid]))
\App::$config[$uid][$family] = array();
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
intval($uid),
dbesc($family),
dbesc($key),
dbesc($dbvalue)
dbesc($dbvalue),
dbesc($updated)
);
// There is a possible race condition if another process happens
// to insert something after this thread has Loaded and now. We should
// at least make a note of it if it happens.
if (!$ret) {
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
}
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
}
else {
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
dbesc($dbvalue),
intval($uid),
dbesc($family),
dbesc($key)
);
if ($new) {
// @NOTE There is still a possible race condition under limited circumstances
// where a value will be updated by another thread with more current data than
// we have. At this point there is no easy way to test for it, so we update
// and hope for the best.
$ret = q("UPDATE pconfig SET v = '%s', updated = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' ",
dbesc($dbvalue),
dbesc($updated),
intval($uid),
dbesc($family),
dbesc($key)
);
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
} else {
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
return self::Get($uid, $family, $key);
}
}
// keep a separate copy for all variables which were
// set in the life of this page. We need this to
// synchronise channel clones.
@@ -163,7 +209,11 @@ class PConfig {
\App::$config[$uid]['transient'][$family] = array();
\App::$config[$uid][$family][$key] = $value;
\App::$config[$uid]['transient'][$family][$key] = $value;
if ($new) {
\App::$config[$uid]['transient'][$family][$key] = $value;
\App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
}
if($ret)
return $value;
@@ -186,18 +236,29 @@ class PConfig {
* The configuration key to delete
* @return mixed
*/
static public function Delete($uid, $family, $key) {
static public function Delete($uid, $family, $key, $updated = NULL) {
if(is_null($uid) || $uid === false)
return false;
$updated = ($updated) ? $updated : datetime_convert();
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $updated);
if (! $newer) {
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
return false;
}
$ret = false;
if(array_key_exists($uid,\App::$config)
&& is_array(\App::$config['uid'])
&& array_key_exists($family,\App::$config['uid'])
&& array_key_exists($key, \App::$config[$uid][$family]))
if (isset(\App::$config[$uid][$family][$key])) {
unset(\App::$config[$uid][$family][$key]);
}
if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
}
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
intval($uid),
@@ -205,6 +266,22 @@ class PConfig {
dbesc($key)
);
if ($family != 'hz_delpconfig') {
$hash = hash('sha256',$family.':'.$key);
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
}
// Synchronize delete with clones.
if(! array_key_exists('transient', \App::$config[$uid]))
\App::$config[$uid]['transient'] = array();
if(! array_key_exists($family, \App::$config[$uid]['transient']))
\App::$config[$uid]['transient'][$family] = array();
if ($new) {
\App::$config[$uid]['transient'][$family]['pcfgdel:'.$key] = $updated;
}
return $ret;
}

View File

@@ -109,11 +109,9 @@ class Admin extends \Zotlabs\Web\Controller {
// available channels, primary and clones
$channels = array();
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0 and channel_system = 0");
$r = q("SELECT COUNT(*) AS total FROM channel WHERE channel_removed = 0 and channel_system = 0");
if ($r) {
$channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']);
$channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']);
$channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']);
}
// We can do better, but this is a quick queue status

View File

@@ -90,12 +90,12 @@ class Appman extends \Zotlabs\Web\Controller {
$channel = \App::get_channel();
if(argc() > 2) {
if(argc() > 3) {
if(argv(2) === 'moveup') {
Zlib\Apps::moveup(local_channel(),argv(1));
Zlib\Apps::moveup(local_channel(),argv(1),argv(3));
}
if(argv(2) === 'movedown') {
Zlib\Apps::movedown(local_channel(),argv(1));
Zlib\Apps::movedown(local_channel(),argv(1),argv(3));
}
goaway(z_root() . '/apporder');
}

View File

@@ -17,25 +17,28 @@ class Apporder extends \Zotlabs\Web\Controller {
nav_set_selected('Order Apps');
$syslist = array();
$list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
if($list) {
foreach($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li);
foreach( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) {
$syslist = [];
$list = Zlib\Apps::app_list(local_channel(), false, [ $l ]);
if($list) {
foreach($list as $li) {
$syslist[] = Zlib\Apps::app_encode($li);
}
}
}
Zlib\Apps::translate_system_apps($syslist);
Zlib\Apps::translate_system_apps($syslist);
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Zlib\Apps::app_order(local_channel(),$syslist);
$syslist = Zlib\Apps::app_order(local_channel(),$syslist, $l);
foreach($syslist as $app) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
else {
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
foreach($syslist as $app) {
if($l === 'nav_pinned_app') {
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
elseif(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
}
}
}

View File

@@ -375,8 +375,7 @@ class Display extends \Zotlabs\Web\Controller {
}
$o .= '</noscript>';
if ($items[0]['title'])
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
\App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
$o .= conversation($items, 'display', $update, 'client');
}

View File

@@ -127,6 +127,15 @@ class Import extends \Zotlabs\Web\Controller {
//
// }
// prevent incompatible osada or zap data from horking your database
if(array_path_exists('compatibility/codebase',$data)) {
notice('Data export format is not compatible with this software');
return;
}
if($moving)
$seize = 1;

View File

@@ -228,8 +228,13 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$header = $result['header'];
$body = $result['body'];
// Check codepage in HTTP headers or HTML if not exist
$cp = (preg_match('/Content-Type: text\/html; charset=(.+)\r\n/i', $header, $o) ? $o[1] : '');
if(empty($cp))
$cp = (preg_match('/meta.+content=["|\']text\/html; charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'AUTO');
$body = mb_convert_encoding($body, 'UTF-8', (preg_match('/meta.+content=["|\']text\/html;\s+charset=([^"|\']+)/i', $body, $o) ? $o[1] : 'UTF-8'));
$body = mb_convert_encoding($body, 'UTF-8', $cp);
$body = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new \DOMDocument();
@@ -265,20 +270,43 @@ class Linkinfo extends \Zotlabs\Web\Controller {
$attr["content"] = html_entity_decode($attr["content"], ENT_QUOTES, "UTF-8");
switch (strtolower($attr["name"])) {
case 'generator':
$siteinfo['generator'] = $attr['content'];
break;
case "fulltitle":
$siteinfo["title"] = $attr["content"];
$siteinfo["title"] = trim($attr["content"]);
break;
case "description":
$siteinfo["text"] = $attr["content"];
$siteinfo["text"] = trim($attr["content"]);
break;
case "thumbnail":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:image:src":
$siteinfo["image"] = $attr["content"];
break;
case "twitter:card":
if (($siteinfo["type"] == "") || ($attr["content"] == "photo")) {
$siteinfo["type"] = $attr["content"];
}
break;
case "twitter:description":
$siteinfo["text"] = trim($attr["content"]);
break;
case "twitter:title":
$siteinfo["title"] = trim($attr["content"]);
break;
case "dc.title":
$siteinfo["title"] = $attr["content"];
$siteinfo["title"] = trim($attr["content"]);
break;
case "dc.description":
$siteinfo["text"] = $attr["content"];
$siteinfo["text"] = trim($attr["content"]);
break;
case "keywords":
$keywords = explode(",", $attr["content"]);
break;
case "news_keywords":
$keywords = explode(",", $attr["content"]);
break;
}
}

View File

@@ -258,6 +258,10 @@ class Network extends \Zotlabs\Web\Controller {
}
elseif($pf && $unseen && $nouveau) {
$vnotify = get_pconfig(local_channel(), 'system', 'vnotify');
if(! ($vnotify & VNOTIFY_LIKE))
$likes_sql = " AND verb NOT IN ('" . dbesc(ACTIVITY_LIKE) . "', '" . dbesc(ACTIVITY_DISLIKE) . "') ";
// This is for nouveau view public forum cid queries (if a forum notification is clicked)
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
intval(local_channel()),
@@ -269,7 +273,7 @@ class Network extends \Zotlabs\Web\Controller {
if($p_str)
$p_sql = " OR item.parent IN ( $p_str ) ";
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 ";
$sql_extra = " AND ( owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' OR owner_xchan = '" . protect_sprintf(dbesc($cid_r[0]['abook_xchan'])) . "' $p_sql ) AND item_unseen = 1 $likes_sql ";
}
else {
// This is for threaded view cid queries (e.g. if a forum is selected from the forum filter)

View File

@@ -145,7 +145,7 @@ class New_channel extends \Zotlabs\Web\Controller {
$canadd = true;
if($r && ($limit !== false)) {
$channel_usage_message = sprintf( t("You have created %1$.0f of %2$.0f allowed channels."), $r[0]['total'], $limit);
if ($r[0]['total'] >= $limit) {
if ($r[0]['total'] > $limit) {
$canadd = false;
}
}

View File

@@ -31,15 +31,17 @@ class Owa extends \Zotlabs\Web\Controller {
if($keyId) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where hubloc_addr = '%s' ",
dbesc(str_replace('acct:','',$keyId))
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
dbesc(str_replace('acct:','',$keyId)),
dbesc($keyId)
);
if(! $r) {
$found = discover_by_webbie(str_replace('acct:','',$keyId));
if($found) {
$r = q("select * from hubloc left join xchan on hubloc_hash = xchan_hash
where hubloc_addr = '%s' ",
dbesc(str_replace('acct:','',$keyId))
where ( hubloc_addr = '%s' or hubloc_id_url = '%s' ) ",
dbesc(str_replace('acct:','',$keyId)),
dbesc($keyId)
);
}
}

View File

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

View File

@@ -4,13 +4,12 @@ namespace Zotlabs\Module;
require_once('include/security.php');
require_once('include/attach.php');
require_once('include/photo/photo_driver.php');
require_once('include/photos.php');
class Photo extends \Zotlabs\Web\Controller {
function init() {
$prvcachecontrol = false;
$streaming = null;
$channel = null;
@@ -32,26 +31,26 @@ class Photo extends \Zotlabs\Web\Controller {
}
$observer_xchan = get_observer_hash();
$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
$default = z_root() . '/' . get_default_profile_photo();
if(isset($type)) {
/**
* Profile photos - Access controls on default profile photos are not honoured since they need to be exchanged with remote sites.
*
*/
$default = get_default_profile_photo();
if($type === 'profile') {
switch($res) {
case 'm':
$resolution = 5;
$default = z_root() . '/' . get_default_profile_photo(80);
$default = get_default_profile_photo(80);
break;
case 's':
$resolution = 6;
$default = z_root() . '/' . get_default_profile_photo(48);
$default = get_default_profile_photo(48);
break;
case 'l':
default:
@@ -60,6 +59,8 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
$modified = filemtime($default);
$default = z_root() . '/' . $default;
$uid = $person;
$d = [ 'imgscale' => $resolution, 'channel_id' => $uid, 'default' => $default, 'data' => '', 'mimetype' => '' ];
@@ -78,17 +79,18 @@ class Photo extends \Zotlabs\Web\Controller {
intval(PHOTO_PROFILE)
);
if($r) {
$modified = strtotime($r[0]['edited'] . "Z");
$data = dbunescbin($r[0]['content']);
$mimetype = $r[0]['mimetype'];
}
if(intval($r[0]['os_storage']))
$data = file_get_contents($data);
}
if(! $data) {
$data = fetch_image_from_url($default,$mimetype);
}
if(! $mimetype) {
$mimetype = 'image/png';
$x = z_fetch_url($default,true,0,[ 'novalidate' => true ]);
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
$mimetype = 'image/png';
}
}
else {
@@ -124,9 +126,7 @@ class Photo extends \Zotlabs\Web\Controller {
$photo = substr($photo,0,-2);
// If viewing on a high-res screen, attempt to serve a higher resolution image:
if ($resolution == 2 && ($cookie_value > 1))
{
$resolution = 1;
}
}
$r = q("SELECT uid, photo_usage FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1",
@@ -163,10 +163,13 @@ class Photo extends \Zotlabs\Web\Controller {
if($exists && $allowed) {
$data = dbunescbin($e[0]['content']);
$filesize = $e[0]['filesize'];
$mimetype = $e[0]['mimetype'];
if(intval($e[0]['os_storage'])) {
$modified = strtotime($e[0]['edited'] . 'Z');
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;
}
else {
if(! $allowed) {
@@ -177,27 +180,40 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
} else {
http_status_exit(404,'not found');
}
}
header_remove('Pragma');
if($ismodified === gmdate("D, d M Y H:i:s", $modified) . " GMT") {
header_remove('Expires');
header_remove('Cache-Control');
header_remove('Set-Cookie');
http_status_exit(304,'not modified');
}
if(! isset($data)) {
if(isset($resolution)) {
switch($resolution) {
case 4:
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(),$mimetype);
$default = get_default_profile_photo();
break;
case 5:
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(80),$mimetype);
$default = get_default_profile_photo(80);
break;
case 6:
$data = fetch_image_from_url(z_root() . '/' . get_default_profile_photo(48),$mimetype);
$default = get_default_profile_photo(48);
break;
default:
killme();
// NOTREACHED
break;
}
$x = z_fetch_url(z_root() . '/' . $default,true,0,[ 'novalidate' => true ]);
$data = ($x['success'] ? $x['body'] : EMPTY_STR);
$mimetype = 'image/png';
}
}
@@ -210,15 +226,14 @@ class Photo extends \Zotlabs\Web\Controller {
}
}
// @FIXME Seems never invoked
// Writing in cachefile
if (isset($cachefile) && $cachefile != '')
if (isset($cachefile) && $cachefile != '') {
file_put_contents($cachefile, $data);
if(function_exists('header_remove')) {
header_remove('Pragma');
header_remove('pragma');
$modified = filemtime($cachefile);
}
header("Content-type: " . $mimetype);
if($prvcachecontrol) {
@@ -240,15 +255,16 @@ 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');
if(! $cache)
$cache = (3600 * 24); // 1 day
$cache = get_config('system','photo_cache_time', 86400); // 1 day by default
header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT");
header("Cache-Control: max-age=" . $cache);
}
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) {

View File

@@ -263,7 +263,8 @@ class Photos extends \Zotlabs\Web\Controller {
$fsize = strlen($data);
}
$x = q("update photo set content = '%s', filesize = %d, height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 0",
$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()),
dbescbin($data),
intval($fsize),
intval($height),
@@ -277,9 +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 content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 1",
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),
@@ -292,9 +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 content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 2",
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),
@@ -307,9 +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 content = '%s', height = %d, width = %d where resource_id = '%s' and uid = %d and imgscale = 3",
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),
@@ -612,9 +625,9 @@ class Photos extends \Zotlabs\Web\Controller {
nav_set_selected('Photos');
$o = '<script src="library/blueimp_upload/js/vendor/jquery.ui.widget.js"></script>
<script src="library/blueimp_upload/js/jquery.iframe-transport.js"></script>
<script src="library/blueimp_upload/js/jquery.fileupload.js"></script>';
$o = '<script src="vendor/blueimp/jquery-file-upload/js/vendor/jquery.ui.widget.js"></script>
<script src="vendor/blueimp/jquery-file-upload/js/jquery.iframe-transport.js"></script>
<script src="vendor/blueimp/jquery-file-upload/js/jquery.fileupload.js"></script>';
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
@@ -1109,6 +1122,7 @@ class Photos extends \Zotlabs\Web\Controller {
$comments = '';
if(! $r) {
if($observer && ($can_post || $can_comment)) {
$feature_auto_save_draft = ((feature_enabled($owner_uid, 'auto_save_draft')) ? "true" : "false");
$commentbox = replace_macros($cmnt_tpl,array(
'$return_path' => '',
'$mode' => 'photos',
@@ -1124,7 +1138,8 @@ class Photos extends \Zotlabs\Web\Controller {
'$submit' => t('Submit'),
'$preview' => t('Preview'),
'$ww' => '',
'$feature_encrypt' => false
'$feature_encrypt' => false,
'$auto_save_draft' => $feature_auto_save_draft
));
}
}
@@ -1257,8 +1272,14 @@ class Photos extends \Zotlabs\Web\Controller {
if(feature_enabled($owner_uid,'dislike'))
$response_verbs[] = 'dislike';
$responses = get_responses($conv_responses,$response_verbs,'',$link_item);
$hookdata = [
'onclick' => '$.colorbox({href: \'' . $photo['href'] . '\'}); return false;',
'raw_photo' => $ph[0],
'nickname' => \App::$data['channel']['channel_address']
];
call_hooks('photo_view_filter', $hookdata);
$photo_tpl = get_markup_template('photo_view.tpl');
$o .= replace_macros($photo_tpl, array(
@@ -1296,6 +1317,7 @@ class Photos extends \Zotlabs\Web\Controller {
'$comments' => $comments,
'$commentbox' => $commentbox,
'$paginate' => $paginate,
'$onclick' => $hookdata['onclick']
));
\App::$data['photo_html'] = $o;

View File

@@ -330,6 +330,7 @@ class Ping extends \Zotlabs\Web\Controller {
$notifs[] = array(
'notify_link' => z_root() . '/mail/' . $zz['id'],
'name' => $zz['xchan_name'],
'addr' => $zz['xchan_addr'],
'url' => $zz['xchan_url'],
'photo' => $zz['xchan_photo_s'],
'when' => relative_date($zz['created']),
@@ -346,6 +347,10 @@ class Ping extends \Zotlabs\Web\Controller {
if(argc() > 1 && (argv(1) === 'network' || argv(1) === 'home')) {
$result = array();
if(argv(1) === 'home') {
$sql_extra .= ' and item_wall = 1 ';
}
$r = q("SELECT * FROM item
WHERE uid = %d
AND item_unseen = 1
@@ -361,8 +366,6 @@ class Ping extends \Zotlabs\Web\Controller {
if($r) {
xchan_query($r);
foreach($r as $item) {
if((argv(1) === 'home') && (! intval($item['item_wall'])))
continue;
$result[] = \Zotlabs\Lib\Enotify::format($item);
}
}
@@ -383,6 +386,7 @@ class Ping extends \Zotlabs\Web\Controller {
$result[] = array(
'notify_link' => z_root() . '/connections/ifpending',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
'photo' => $rr['xchan_photo_s'],
'when' => relative_date($rr['abook_created']),
@@ -407,6 +411,7 @@ class Ping extends \Zotlabs\Web\Controller {
$result[] = array(
'notify_link' => z_root() . '/admin/accounts',
'name' => $rr['account_email'],
'addr' => $rr['account_email'],
'url' => '',
'photo' => z_root() . '/' . get_default_profile_photo(48),
'when' => relative_date($rr['account_created']),
@@ -444,6 +449,7 @@ class Ping extends \Zotlabs\Web\Controller {
$result[] = array(
'notify_link' => z_root() . '/events', /// @FIXME this takes you to an edit page and it may not be yours, we really want to just view the single event --> '/events/event/' . $rr['event_hash'],
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
'photo' => $rr['xchan_photo_s'],
'when' => $when,
@@ -460,7 +466,7 @@ class Ping extends \Zotlabs\Web\Controller {
if(argc() > 1 && (argv(1) === 'files')) {
$result = array();
$r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_url, xchan.xchan_photo_s FROM item
$r = q("SELECT item.created, xchan.xchan_name, xchan.xchan_addr, xchan.xchan_url, xchan.xchan_photo_s FROM item
LEFT JOIN xchan on author_xchan = xchan_hash
WHERE item.verb = '%s'
AND item.obj_type = '%s'
@@ -477,6 +483,7 @@ class Ping extends \Zotlabs\Web\Controller {
$result[] = array(
'notify_link' => z_root() . '/sharedwithme',
'name' => $rr['xchan_name'],
'addr' => $rr['xchan_addr'],
'url' => $rr['xchan_url'],
'photo' => $rr['xchan_photo_s'],
'when' => relative_date($rr['created']),
@@ -635,7 +642,6 @@ class Ping extends \Zotlabs\Web\Controller {
$forums = get_forum_channels(local_channel());
if($forums) {
$perms_sql = item_permissions_sql(local_channel());
$item_normal = item_normal();
$fcount = count($forums);
$forums['total'] = 0;
@@ -644,14 +650,14 @@ class Ping extends \Zotlabs\Web\Controller {
$p = q("SELECT oid AS parent FROM term WHERE uid = %d AND ttype = %d AND term = '%s'",
intval(local_channel()),
intval(TERM_FORUM),
dbesc($forums[$x]['xchan_hash'])
dbesc($forums[$x]['xchan_name'])
);
$p_str = ids_to_querystr($p, 'parent');
$p_sql = (($p_str) ? "OR parent IN ( $p_str )" : '');
$r = q("select sum(item_unseen) as unseen from item
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $perms_sql $item_normal",
$r = q("select count(id) as unseen from item
where uid = %d and ( owner_xchan = '%s' OR author_xchan = '%s' $p_sql ) and item_unseen = 1 $item_normal $sql_extra",
intval(local_channel()),
dbesc($forums[$x]['xchan_hash']),
dbesc($forums[$x]['xchan_hash'])
@@ -659,6 +665,7 @@ class Ping extends \Zotlabs\Web\Controller {
if($r[0]['unseen']) {
$forums[$x]['notify_link'] = (($forums[$x]['private_forum']) ? $forums[$x]['xchan_url'] : z_root() . '/network/?f=&pf=1&unseen=1&cid=' . $forums[$x]['abook_id']);
$forums[$x]['name'] = $forums[$x]['xchan_name'];
$forums[$x]['addr'] = $forums[$x]['xchan_addr'];
$forums[$x]['url'] = $forums[$x]['xchan_url'];
$forums[$x]['photo'] = $forums[$x]['xchan_photo_s'];
$forums[$x]['unseen'] = $r[0]['unseen'];

View File

@@ -6,7 +6,7 @@ class Search extends \Zotlabs\Web\Controller {
function init() {
if(x($_REQUEST,'search'))
\App::$data['search'] = $_REQUEST['search'];
\App::$data['search'] = escape_tags($_REQUEST['search']);
}
@@ -46,12 +46,12 @@ class Search extends \Zotlabs\Web\Controller {
if(x(\App::$data,'search'))
$search = trim(\App::$data['search']);
else
$search = ((x($_GET,'search')) ? trim(rawurldecode($_GET['search'])) : '');
$search = ((x($_GET,'search')) ? trim(escape_tags(rawurldecode($_GET['search']))) : '');
$tag = false;
if(x($_GET,'tag')) {
$tag = true;
$search = ((x($_GET,'tag')) ? trim(rawurldecode($_GET['tag'])) : '');
$search = ((x($_GET,'tag')) ? trim(escape_tags(rawurldecode($_GET['tag']))) : '');
}
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
@@ -227,9 +227,9 @@ class Search extends \Zotlabs\Web\Controller {
}
if($tag)
$o .= '<h2>' . sprintf( t('Items tagged with: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
$o .= '<h2>' . sprintf( t('Items tagged with: %s'),$search) . '</h2>';
else
$o .= '<h2>' . sprintf( t('Search results for: %s'),htmlspecialchars($search, ENT_COMPAT,'UTF-8')) . '</h2>';
$o .= '<h2>' . sprintf( t('Search results for: %s'),$search) . '</h2>';
$o .= conversation($items,'search',$update,'client');

View File

@@ -19,7 +19,7 @@ class Zot extends \Zotlabs\Web\Controller {
function init() {
$zot = new ZotProtocol\Receiver(new ZotProtocol\Zot6Handler());
json_return_and_die($zot->run(),'application/x-zot+jzon');
json_return_and_die($zot->run(),'application/x-zot+json');
}
}

26
Zotlabs/Update/_1225.php Normal file
View File

@@ -0,0 +1,26 @@
<?php
namespace Zotlabs\Update;
class _1225 {
function run() {
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
$r1 = q("ALTER TABLE pconfig ADD updated timestamp NOT NULL DEFAULT '0001-01-01 00:00:00' ");
$r2 = q("create index \"pconfig_updated_idx\" on pconfig (\"updated\")");
$r = ($r1 && $r2);
}
else {
$r = q("ALTER TABLE `pconfig` ADD `updated` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' ,
ADD INDEX `pconfig_updated` (`updated`)");
}
if($r)
return UPDATE_SUCCESS;
return UPDATE_FAILED;
}
}

View File

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

View File

@@ -6,10 +6,6 @@ class Wiki_list {
function widget($arr) {
if(argc() < 3) {
return;
}
$channel = channelx_by_n(\App::$profile_uid);
$wikis = \Zotlabs\Lib\NativeWiki::listwikis($channel,get_observer_hash());

View File

@@ -50,11 +50,10 @@ require_once('include/attach.php');
require_once('include/bbcode.php');
define ( 'PLATFORM_NAME', 'hubzilla' );
define ( 'STD_VERSION', '3.8.2' );
define ( 'STD_VERSION', '3.8.7' );
define ( 'ZOT_REVISION', '6.0a' );
define ( 'DB_UPDATE_VERSION', 1224 );
define ( 'DB_UPDATE_VERSION', 1225 );
define ( 'PROJECT_BASE', __DIR__ );

View File

@@ -39,7 +39,9 @@
"lukasreschke/id3parser": "^0.0.1",
"smarty/smarty": "~3.1",
"ramsey/uuid": "^3.8",
"twbs/bootstrap": "4.1.3"
"twbs/bootstrap": "4.1.3",
"blueimp/jquery-file-upload": "^9.25",
"desandro/imagesloaded": "^4.1"
},
"require-dev" : {
"phpunit/phpunit" : "@stable",

341
composer.lock generated
View File

@@ -4,8 +4,63 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b7862124a9afe837c7eef8ee66f02ff4",
"content-hash": "fe5e71d7076eeddf1c174be4a5c052dd",
"packages": [
{
"name": "blueimp/jquery-file-upload",
"version": "v9.28.0",
"source": {
"type": "git",
"url": "https://github.com/vkhramtsov/jQuery-File-Upload.git",
"reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/vkhramtsov/jQuery-File-Upload/zipball/ff5accfe2e5c4a522777faa980a90cf86a636d1d",
"reference": "ff5accfe2e5c4a522777faa980a90cf86a636d1d",
"shasum": ""
},
"type": "library",
"autoload": {
"classmap": [
"server/php/UploadHandler.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sebastian Tschan",
"homepage": "https://blueimp.net"
}
],
"description": "File Upload widget for jQuery.",
"homepage": "https://github.com/blueimp/jQuery-File-Upload",
"keywords": [
"bootstrap",
"chunk",
"cross-domain",
"cross-site",
"drag",
"drop",
"file",
"gae",
"go",
"jquery",
"multiple",
"php",
"preview",
"progress",
"python",
"resume",
"selection",
"upload",
"widget"
],
"time": "2018-11-13T05:41:39+00:00"
},
{
"name": "bshaffer/oauth2-server-php",
"version": "v1.10.0",
@@ -108,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",
@@ -157,16 +251,16 @@
},
{
"name": "league/html-to-markdown",
"version": "4.7.0",
"version": "4.8.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/html-to-markdown.git",
"reference": "76c076483cef89860d32a3fd25312f5a42848a8c"
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/76c076483cef89860d32a3fd25312f5a42848a8c",
"reference": "76c076483cef89860d32a3fd25312f5a42848a8c",
"url": "https://api.github.com/repos/thephpleague/html-to-markdown/zipball/f9a879a068c68ff47b722de63f58bec79e448f9d",
"reference": "f9a879a068c68ff47b722de63f58bec79e448f9d",
"shasum": ""
},
"require": {
@@ -185,7 +279,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.8-dev"
"dev-master": "4.9-dev"
}
},
"autoload": {
@@ -198,17 +292,17 @@
"MIT"
],
"authors": [
{
"name": "Colin O'Dell",
"email": "colinodell@gmail.com",
"homepage": "http://www.colinodell.com",
"role": "Lead Developer"
},
{
"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"
}
],
"description": "An HTML-to-markdown conversion helper for PHP",
@@ -217,7 +311,7 @@
"html",
"markdown"
],
"time": "2018-05-19T23:47:12+00:00"
"time": "2018-09-18T12:18:08+00:00"
},
{
"name": "lukasreschke/id3parser",
@@ -391,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": {
@@ -434,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",
@@ -520,16 +614,16 @@
},
{
"name": "sabre/dav",
"version": "3.2.2",
"version": "3.2.3",
"source": {
"type": "git",
"url": "https://github.com/sabre-io/dav.git",
"reference": "e987775e619728f12205606c9cc3ee565ffb1516"
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sabre-io/dav/zipball/e987775e619728f12205606c9cc3ee565ffb1516",
"reference": "e987775e619728f12205606c9cc3ee565ffb1516",
"url": "https://api.github.com/repos/sabre-io/dav/zipball/a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
"reference": "a9780ce4f35560ecbd0af524ad32d9d2c8954b80",
"shasum": ""
},
"require": {
@@ -599,7 +693,7 @@
"framework",
"iCalendar"
],
"time": "2017-02-15T03:06:08+00:00"
"time": "2018-10-19T09:58:27+00:00"
},
{
"name": "sabre/event",
@@ -1002,16 +1096,16 @@
},
{
"name": "smarty/smarty",
"version": "v3.1.32",
"version": "v3.1.33",
"source": {
"type": "git",
"url": "https://github.com/smarty-php/smarty.git",
"reference": "ac9d4b587e5bf53381e21881820a9830765cb459"
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/ac9d4b587e5bf53381e21881820a9830765cb459",
"reference": "ac9d4b587e5bf53381e21881820a9830765cb459",
"url": "https://api.github.com/repos/smarty-php/smarty/zipball/dd55b23121e55a3b4f1af90a707a6c4e5969530f",
"reference": "dd55b23121e55a3b4f1af90a707a6c4e5969530f",
"shasum": ""
},
"require": {
@@ -1051,11 +1145,11 @@
"keywords": [
"templating"
],
"time": "2018-04-24T14:53:33+00:00"
"time": "2018-09-12T20:54:16+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.9.0",
"version": "v1.10.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -2160,16 +2254,16 @@
},
{
"name": "php-mock/php-mock-phpunit",
"version": "2.1.1",
"version": "2.1.2",
"source": {
"type": "git",
"url": "https://github.com/php-mock/php-mock-phpunit.git",
"reference": "ff1cc1d4e7478ce74221e05742588619bee84f69"
"reference": "57b92e621f14c2c07a4567cd29ed4e87de0d2912"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/ff1cc1d4e7478ce74221e05742588619bee84f69",
"reference": "ff1cc1d4e7478ce74221e05742588619bee84f69",
"url": "https://api.github.com/repos/php-mock/php-mock-phpunit/zipball/57b92e621f14c2c07a4567cd29ed4e87de0d2912",
"reference": "57b92e621f14c2c07a4567cd29ed4e87de0d2912",
"shasum": ""
},
"require": {
@@ -2210,7 +2304,7 @@
"test",
"test double"
],
"time": "2018-04-06T13:54:43+00:00"
"time": "2018-10-07T14:38:37+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@@ -2481,16 +2575,16 @@
},
{
"name": "phpunit/php-code-coverage",
"version": "6.0.7",
"version": "6.1.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "865662550c384bc1db7e51d29aeda1c2c161d69a"
"reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/865662550c384bc1db7e51d29aeda1c2c161d69a",
"reference": "865662550c384bc1db7e51d29aeda1c2c161d69a",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
"reference": "807e6013b00af69b6c5d9ceb4282d0393dbb9d8d",
"shasum": ""
},
"require": {
@@ -2501,7 +2595,7 @@
"phpunit/php-text-template": "^1.2.1",
"phpunit/php-token-stream": "^3.0",
"sebastian/code-unit-reverse-lookup": "^1.0.1",
"sebastian/environment": "^3.1",
"sebastian/environment": "^3.1 || ^4.0",
"sebastian/version": "^2.0.1",
"theseer/tokenizer": "^1.1"
},
@@ -2514,7 +2608,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.0-dev"
"dev-master": "6.1-dev"
}
},
"autoload": {
@@ -2540,25 +2634,28 @@
"testing",
"xunit"
],
"time": "2018-06-01T07:51:50+00:00"
"time": "2018-10-31T16:06:48+00:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "2.0.1",
"version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c"
"reference": "050bedf145a257b1ff02746c31894800e5122946"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cecbc684605bb0cc288828eb5d65d93d5c676d3c",
"reference": "cecbc684605bb0cc288828eb5d65d93d5c676d3c",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/050bedf145a257b1ff02746c31894800e5122946",
"reference": "050bedf145a257b1ff02746c31894800e5122946",
"shasum": ""
},
"require": {
"php": "^7.1"
},
"require-dev": {
"phpunit/phpunit": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
@@ -2587,7 +2684,7 @@
"filesystem",
"iterator"
],
"time": "2018-06-11T11:44:00+00:00"
"time": "2018-09-13T20:33:42+00:00"
},
{
"name": "phpunit/php-text-template",
@@ -2681,16 +2778,16 @@
},
{
"name": "phpunit/php-token-stream",
"version": "3.0.0",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace"
"reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/21ad88bbba7c3d93530d93994e0a33cd45f02ace",
"reference": "21ad88bbba7c3d93530d93994e0a33cd45f02ace",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/c99e3be9d3e85f60646f152f9002d46ed7770d18",
"reference": "c99e3be9d3e85f60646f152f9002d46ed7770d18",
"shasum": ""
},
"require": {
@@ -2726,20 +2823,20 @@
"keywords": [
"tokenizer"
],
"time": "2018-02-01T13:16:43+00:00"
"time": "2018-10-30T05:52:18+00:00"
},
{
"name": "phpunit/phpunit",
"version": "7.3.2",
"version": "7.4.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "34705f81bddc3f505b9599a2ef96e2b4315ba9b8"
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/34705f81bddc3f505b9599a2ef96e2b4315ba9b8",
"reference": "34705f81bddc3f505b9599a2ef96e2b4315ba9b8",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
"reference": "b1be2c8530c4c29c3519a052c9fb6cee55053bbd",
"shasum": ""
},
"require": {
@@ -2760,11 +2857,11 @@
"phpunit/php-timer": "^2.0",
"sebastian/comparator": "^3.0",
"sebastian/diff": "^3.0",
"sebastian/environment": "^3.1",
"sebastian/environment": "^3.1 || ^4.0",
"sebastian/exporter": "^3.1",
"sebastian/global-state": "^2.0",
"sebastian/object-enumerator": "^3.0.3",
"sebastian/resource-operations": "^1.0",
"sebastian/resource-operations": "^2.0",
"sebastian/version": "^2.0.1"
},
"conflict": {
@@ -2784,7 +2881,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "7.3-dev"
"dev-master": "7.4-dev"
}
},
"autoload": {
@@ -2810,7 +2907,7 @@
"testing",
"xunit"
],
"time": "2018-08-22T06:39:21+00:00"
"time": "2018-11-14T16:52:02+00:00"
},
{
"name": "psr/container",
@@ -3391,25 +3488,25 @@
},
{
"name": "sebastian/resource-operations",
"version": "1.0.0",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/resource-operations.git",
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52"
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
"reference": "ce990bb21759f94aeafd30209e8cfcdfa8bc3f52",
"url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"reference": "4d7a795d35b889bf80a0cc04e08d77cedfa917a9",
"shasum": ""
},
"require": {
"php": ">=5.6.0"
"php": "^7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
"dev-master": "2.0-dev"
}
},
"autoload": {
@@ -3429,7 +3526,7 @@
],
"description": "Provides a list of PHP built-in functions that operate on resources",
"homepage": "https://www.github.com/sebastianbergmann/resource-operations",
"time": "2015-07-28T20:34:47+00:00"
"time": "2018-10-04T04:07:39+00:00"
},
{
"name": "sebastian/version",
@@ -3476,7 +3573,7 @@
},
{
"name": "symfony/browser-kit",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/browser-kit.git",
@@ -3533,16 +3630,16 @@
},
{
"name": "symfony/class-loader",
"version": "v3.4.15",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/class-loader.git",
"reference": "31db283fc86d3143e7ff87e922177b457d909c30"
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/31db283fc86d3143e7ff87e922177b457d909c30",
"reference": "31db283fc86d3143e7ff87e922177b457d909c30",
"url": "https://api.github.com/repos/symfony/class-loader/zipball/5605edec7b8f034ead2497ff4aab17bb70d558c1",
"reference": "5605edec7b8f034ead2497ff4aab17bb70d558c1",
"shasum": ""
},
"require": {
@@ -3585,20 +3682,20 @@
],
"description": "Symfony ClassLoader Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T11:19:56+00:00"
"time": "2018-10-31T09:06:03+00:00"
},
{
"name": "symfony/config",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "76015a3cc372b14d00040ff58e18e29f69eba717"
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/76015a3cc372b14d00040ff58e18e29f69eba717",
"reference": "76015a3cc372b14d00040ff58e18e29f69eba717",
"url": "https://api.github.com/repos/symfony/config/zipball/991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"reference": "991fec8bbe77367fc8b48ecbaa8a4bd6e905a238",
"shasum": ""
},
"require": {
@@ -3648,20 +3745,20 @@
],
"description": "Symfony Config Component",
"homepage": "https://symfony.com",
"time": "2018-08-08T06:37:38+00:00"
"time": "2018-10-31T09:09:42+00:00"
},
{
"name": "symfony/console",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "ca80b8ced97cf07390078b29773dc384c39eee1f"
"reference": "432122af37d8cd52fba1b294b11976e0d20df595"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/ca80b8ced97cf07390078b29773dc384c39eee1f",
"reference": "ca80b8ced97cf07390078b29773dc384c39eee1f",
"url": "https://api.github.com/repos/symfony/console/zipball/432122af37d8cd52fba1b294b11976e0d20df595",
"reference": "432122af37d8cd52fba1b294b11976e0d20df595",
"shasum": ""
},
"require": {
@@ -3716,20 +3813,20 @@
],
"description": "Symfony Console Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T11:24:31+00:00"
"time": "2018-10-31T09:30:44+00:00"
},
{
"name": "symfony/css-selector",
"version": "v3.4.15",
"version": "v3.4.18",
"source": {
"type": "git",
"url": "https://github.com/symfony/css-selector.git",
"reference": "edda5a6155000ff8c3a3f85ee5c421af93cca416"
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/edda5a6155000ff8c3a3f85ee5c421af93cca416",
"reference": "edda5a6155000ff8c3a3f85ee5c421af93cca416",
"url": "https://api.github.com/repos/symfony/css-selector/zipball/3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"reference": "3503415d4aafabc31cd08c3a4ebac7f43fde8feb",
"shasum": ""
},
"require": {
@@ -3769,20 +3866,20 @@
],
"description": "Symfony CssSelector Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T09:06:28+00:00"
"time": "2018-10-02T16:33:53+00:00"
},
{
"name": "symfony/dependency-injection",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
"reference": "bae4983003c9d451e278504d7d9b9d7fc1846873"
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/bae4983003c9d451e278504d7d9b9d7fc1846873",
"reference": "bae4983003c9d451e278504d7d9b9d7fc1846873",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/e72ee2c23d952e4c368ee98610fa22b79b89b483",
"reference": "e72ee2c23d952e4c368ee98610fa22b79b89b483",
"shasum": ""
},
"require": {
@@ -3840,20 +3937,20 @@
],
"description": "Symfony DependencyInjection Component",
"homepage": "https://symfony.com",
"time": "2018-08-08T11:48:58+00:00"
"time": "2018-10-31T10:54:16+00:00"
},
{
"name": "symfony/dom-crawler",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dom-crawler.git",
"reference": "1c4519d257e652404c3aa550207ccd8ada66b38e"
"reference": "80e60271bb288de2a2259662cff125cff4f93f95"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/1c4519d257e652404c3aa550207ccd8ada66b38e",
"reference": "1c4519d257e652404c3aa550207ccd8ada66b38e",
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/80e60271bb288de2a2259662cff125cff4f93f95",
"reference": "80e60271bb288de2a2259662cff125cff4f93f95",
"shasum": ""
},
"require": {
@@ -3897,20 +3994,20 @@
],
"description": "Symfony DomCrawler Component",
"homepage": "https://symfony.com",
"time": "2018-07-26T11:00:49+00:00"
"time": "2018-10-02T12:40:59+00:00"
},
{
"name": "symfony/event-dispatcher",
"version": "v4.1.4",
"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": {
@@ -3960,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.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e"
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e",
"reference": "c0f5f62db218fa72195b8b8700e4b9b9cf52eb5e",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"reference": "fd7bd6535beb1f0a0a9e3ee960666d0598546981",
"shasum": ""
},
"require": {
@@ -4010,20 +4107,20 @@
],
"description": "Symfony Filesystem Component",
"homepage": "https://symfony.com",
"time": "2018-08-18T16:52:46+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": {
@@ -4069,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.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f"
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/fa2182669f7983b7aa5f1a770d053f79f0ef144f",
"reference": "fa2182669f7983b7aa5f1a770d053f79f0ef144f",
"url": "https://api.github.com/repos/symfony/translation/zipball/aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
"reference": "aa04dc1c75b7d3da7bd7003104cd0cfc5dff635c",
"shasum": ""
},
"require": {
@@ -4138,20 +4235,20 @@
],
"description": "Symfony Translation Component",
"homepage": "https://symfony.com",
"time": "2018-08-07T12:45:11+00:00"
"time": "2018-10-28T18:38:52+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.1.4",
"version": "v4.1.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/yaml.git",
"reference": "b832cc289608b6d305f62149df91529a2ab3c314"
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/b832cc289608b6d305f62149df91529a2ab3c314",
"reference": "b832cc289608b6d305f62149df91529a2ab3c314",
"url": "https://api.github.com/repos/symfony/yaml/zipball/367e689b2fdc19965be435337b50bc8adf2746c9",
"reference": "367e689b2fdc19965be435337b50bc8adf2746c9",
"shasum": ""
},
"require": {
@@ -4197,7 +4294,7 @@
],
"description": "Symfony Yaml Component",
"homepage": "https://symfony.com",
"time": "2018-08-18T16:52:46+00:00"
"time": "2018-10-02T16:36:10+00:00"
},
{
"name": "theseer/tokenizer",

View File

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

View File

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

View File

@@ -502,6 +502,9 @@ Hooks allow plugins/addons to "hook into" the code at many points and alter the
[zrl=[baseurl]/help/hook/photo_upload_form]photo_upload_form[/zrl]
Called when generating a photo upload form
[zrl=[baseurl]/help/hook/photo_view_filter]photo_view_filter[/zrl]
Called before the data is handed over to the photo_view template
[zrl=[baseurl]/help/hook/poke_verbs]poke_verbs[/zrl]
Called when generating the list of actions for "poke" module

View File

@@ -1198,24 +1198,24 @@ function bbcode($Text, $options = []) {
// Images
// [img]pathtoimage[/img]
if (strpos($Text,'[/img]') !== false) {
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[img\](.*?)\[\/img\]/ism", '<img style="max-width: 100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" style="max-width=100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[zmg\](.*?)\[\/zmg\]/ism", '<img class="zrl" style="max-width: 100%;" src="$1" alt="' . t('Image/photo') . '" />', $Text);
}
// [img float={left, right}]pathtoimage[/img]
if (strpos($Text,'[/img]') !== false) {
$Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[img float=left\](.*?)\[\/img\]/ism", '<img src="$1" style="max-width: 100%; float: left;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/img]') !== false) {
$Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img style="max-width=100%;" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[img float=right\](.*?)\[\/img\]/ism", '<img src="$1" style="max-width: 100%; float: right;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
$Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: left;" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[zmg float=left\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="max-width: 100%; float: left;" alt="' . t('Image/photo') . '" />', $Text);
}
if (strpos($Text,'[/zmg]') !== false) {
$Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img style="max-width=100%;" class="zrl" src="$1" style="float: right;" alt="' . t('Image/photo') . '" />', $Text);
$Text = preg_replace("/\[zmg float=right\](.*?)\[\/zmg\]/ism", '<img class="zrl" src="$1" style="max-width: 100%; float: right;" alt="' . t('Image/photo') . '" />', $Text);
}
// [img=widthxheight]pathtoimage[/img]

View File

@@ -59,8 +59,8 @@ function set_pconfig($uid, $family, $key, $value) {
return Zlib\PConfig::Set($uid,$family,$key,$value);
}
function del_pconfig($uid, $family, $key) {
return Zlib\PConfig::Delete($uid,$family,$key);
function del_pconfig($uid, $family, $key, $updated = NULL) {
return Zlib\PConfig::Delete($uid,$family,$key,$updated);
}
function load_xconfig($xchan) {

View File

@@ -173,14 +173,14 @@ abstract class dba_driver {
return false;
}
if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1') && (! strpbrk($server,':;'))) {
if(! z_dns_check($server)) {
$this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
$this->connected = false;
$this->db = null;
return false;
}
}
// if(strlen($server) && ($server !== 'localhost') && ($server !== '127.0.0.1') && (! strpbrk($server,':;'))) {
// if(! z_dns_check($server)) {
// $this->error = sprintf( t('Cannot locate DNS info for database server \'%s\''), $server);
// $this->connected = false;
// $this->db = null;
// return false;
// }
// }
return true;
}
@@ -468,7 +468,7 @@ function db_columns($table) {
if(ACTIVE_DBTYPE === DBTYPE_POSTGRES) {
$r = q("SELECT column_name as field FROM information_schema.columns WHERE table_schema = 'public' AND table_name = '%s'",
dbesc($table)
);
);
if($r) {
return ids_to_array($r,'field');
}

View File

@@ -186,31 +186,30 @@ function hubloc_change_primary($hubloc) {
logger('no hubloc');
return false;
}
logger('setting primary: ' . $hubloc['hubloc_url'] . ((intval($hubloc['hubloc_primary'])) ? ' true' : ' false'));
// See if this is a local hubloc and if so update the primary for the corresponding channel record.
if($hubloc['hubloc_url'] === z_root()) {
$r = q("select channel_id from channel where channel_hash = '%s' limit 1",
dbesc($hubloc['hubloc_hash'])
);
if($r) {
q("update channel set channel_primary = %d where channel_id = %d",
intval($hubloc['hubloc_primary']),
intval($r[0]['channel_id'])
);
}
}
// we only need to proceed further if this particular hubloc is now primary
if(! (intval($hubloc['hubloc_primary']))) {
logger('not primary: ' . $hubloc['hubloc_url']);
return false;
}
logger('setting primary: ' . $hubloc['hubloc_url']);
// See if there's a local channel
$r = q("select channel_id, channel_primary from channel where channel_hash = '%s' limit 1",
dbesc($hubloc['hubloc_hash'])
);
if($r) {
if(! $r[0]['channel_primary']) {
q("update channel set channel_primary = 1 where channel_id = %d",
intval($r[0]['channel_id'])
);
}
else {
q("update channel set channel_primary = 0 where channel_id = %d",
intval($r[0]['channel_id'])
);
}
}
// do we even have an xchan for this hubloc and if so is it already set as primary?
$r = q("select * from xchan where xchan_hash = '%s' limit 1",

View File

@@ -93,8 +93,7 @@ function import_channel($channel, $account_id, $seize, $newname = '') {
'channel_w_comment', 'channel_w_mail', 'channel_w_like', 'channel_w_tagwall',
'channel_w_chat', 'channel_w_storage', 'channel_w_pages', 'channel_a_republish',
'channel_a_delegate', 'perm_limits', 'channel_password', 'channel_salt',
'channel_moved', 'channel_primary', 'channel_removed', 'channel_deleted',
'channel_system'
'channel_moved', 'channel_removed', 'channel_deleted', 'channel_system'
];
$clean = array();

View File

@@ -608,8 +608,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();
@@ -2627,28 +2625,30 @@ function tag_deliver($uid, $item_id) {
$plustagged = false;
$matches = array();
$pattern = '/[\!@]\!?\[zrl\=' . preg_quote($term['url'],'/') . '\]' . preg_quote($term['term'],'/') . '\[\/zrl\]/';
$pattern = '/[\!@]\!?\[[uz]rl\=' . preg_quote($term['url'],'/') . '\](.*?)\[\/[uz]rl\]/';
if(preg_match($pattern,$body,$matches))
$tagged = true;
// original red forum tagging sequence @forumname+
$pattern = '/\[url\=' . preg_quote($term['url'],'/') . '\]\@(.*?)\[\/url\]/';
if(preg_match($pattern,$body,$matches))
$tagged = true;
// standard forum tagging sequence !forumname
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
$forumpattern = '/\!\!?\[[uz]rl\=([^\]]*?)\]((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$forumpattern2 = '/\[[uz]rl\=([^\]]*?)\]\!((?:.(?!\[[uz]rl\=))*?)\[\/[uz]rl\]/';
$found = false;
$matches = array();
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$plustagged = true;
$found = true;
break;
}
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
@@ -2656,13 +2656,12 @@ function tag_deliver($uid, $item_id) {
}
}
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$plustagged = true;
$found = true;
break;
}
logger('forum ' . $term['term'] . ' exceeded max_tagged_forums - ignoring');
@@ -2884,18 +2883,19 @@ function tgroup_check($uid, $item) {
$body = preg_replace('/\[share(.*?)\[\/share\]/','',$item['body']);
$pluspattern = '/@\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\+\[\/zrl\]/';
$forumpattern = '/\!\!?\[zrl\=([^\]]*?)\]((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$forumpattern2 = '/\[zrl\=([^\]]*?)\]\!((?:.(?!\[zrl\=))*?)\[\/zrl\]/';
$found = false;
$matches = array();
if(preg_match_all($pluspattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_MENTION) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$found = true;
break;
@@ -2905,10 +2905,10 @@ function tgroup_check($uid, $item) {
}
}
if(preg_match_all($forumpattern,$body,$matches,PREG_SET_ORDER)) {
if(preg_match_all($forumpattern2,$body,$matches,PREG_SET_ORDER)) {
foreach($matches as $match) {
$matched_forums ++;
if($term['url'] === $match[1] && $term['term'] === $match[2] && intval($term['ttype']) === TERM_FORUM) {
if($term['url'] === $match[1] && intval($term['ttype']) === TERM_FORUM) {
if($matched_forums <= $max_forums) {
$found = true;
break;
@@ -4610,10 +4610,10 @@ function fix_attached_photo_permissions($uid,$xchan_hash,$body,
if(! stristr($image,z_root() . '/photo/'))
continue;
$image_uri = substr($image,strrpos($image,'/') + 1);
if(strpos($image_uri,'-') !== false)
$image_uri = substr($image_uri,0, strpos($image_uri,'-'));
if(strpos($image_uri,'.') !== false)
$image_uri = substr($image_uri,0, strpos($image_uri,'.'));
if(strrpos($image_uri,'-') !== false)
$image_uri = substr($image_uri,0, strrpos($image_uri,'-'));
if(strrpos($image_uri,'.') !== false)
$image_uri = substr($image_uri,0, strrpos($image_uri,'.'));
if(! strlen($image_uri))
continue;
$srch = '<' . $xchan_hash . '>';

View File

@@ -248,20 +248,12 @@ function bb_to_markdown($Text, $options = []) {
// Convert it to HTML - don't try oembed
$Text = bbcode($Text, [ 'tryoembed' => false ]);
// Markdownify does not preserve previously escaped html entities such as <> and &.
//$Text = str_replace(array('&lt;','&gt;','&amp;'),array('&_lt_;','&_gt_;','&_amp_;'),$Text);
// Now convert HTML to Markdown
$Text = html2markdown($Text);
//html2markdown adds backslashes infront of hashes after a new line. remove them
$Text = str_replace("\n\#", "\n#", $Text);
// It also adds backslashes to our attempt at getting around the html entity preservation for some weird reason.
//$Text = str_replace(array('&\\_lt\\_;','&\\_gt\\_;','&\\_amp\\_;'),array('&lt;','&gt;','&amp;'),$Text);
// If the text going into bbcode() has a plain URL in it, i.e.
// with no [url] tags around it, it will come out of parseString()
// looking like: <http://url.com>, which gets removed by strip_tags().
@@ -291,12 +283,24 @@ function bb_to_markdown($Text, $options = []) {
* If the HTML text can not get parsed it will return an empty string.
*
* @param string $html The HTML code to convert
* @param array $options an array of options to pass to the environment
* @return string Markdown representation of the given HTML text, empty on error
*/
function html2markdown($html,$options = []) {
function html2markdown($html, $options = []) {
$markdown = '';
$internal_errors = libxml_use_internal_errors(true);
if(! $options) {
$options = [
'header_style' => 'setext', // Set to 'atx' to output H1 and H2 headers as # Header1 and ## Header2
'suppress_errors' => true, // Set to false to show warnings when loading malformed HTML
'strip_tags' => false, // Set to true to strip tags that don't have markdown equivalents. N.B. Strips tags, not their content. Useful to clean MS Word HTML output.
'bold_style' => '**', // DEPRECATED: Set to '__' if you prefer the underlined style
'italic_style' => '*', // DEPRECATED: Set to '_' if you prefer the underlined style
'remove_nodes' => '', // space-separated list of dom nodes that should be removed. example: 'meta style script'
'hard_break' => false, // Set to true to turn <br> into `\n` instead of ` \n`
'list_item_style' => '-', // Set the default character for each <li> in a <ul>. Can be '-', '*', or '+'
];
}
$environment = Environment::createDefaultEnvironment($options);
$environment->addConverter(new TableConverter());
@@ -308,8 +312,6 @@ function html2markdown($html,$options = []) {
logger("Invalid HTML. HTMLToMarkdown library threw an exception.");
}
libxml_use_internal_errors($internal_errors);
return $markdown;
}

View File

@@ -222,6 +222,9 @@ function nav($template = 'default') {
if(! $settings_url && isset(App::$nav_sel['settings_url']))
$settings_url = App::$nav_sel['settings_url'];
$pinned_list = [];
$syslist = [];
//app bin
if($is_owner) {
if(get_pconfig(local_channel(), 'system','import_system_apps') !== datetime_convert('UTC','UTC','now','Y-m-d')) {
@@ -234,14 +237,29 @@ function nav($template = 'default') {
set_pconfig(local_channel(), 'system','force_import_system_apps', STD_VERSION);
}
$syslist = array();
$list = Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
$list = Apps::app_list(local_channel(), false, [ 'nav_pinned_app' ]);
if($list) {
foreach($list as $li) {
$pinned_list[] = Apps::app_encode($li);
}
}
Apps::translate_system_apps($pinned_list);
usort($pinned_list,'Zotlabs\\Lib\\Apps::app_name_compare');
$pinned_list = Apps::app_order(local_channel(),$pinned_list, 'nav_pinned_app');
$syslist = [];
$list = Apps::app_list(local_channel(), false, [ 'nav_featured_app' ]);
if($list) {
foreach($list as $li) {
$syslist[] = Apps::app_encode($li);
}
}
Apps::translate_system_apps($syslist);
}
else {
$syslist = Apps::get_system_apps(true);
@@ -249,26 +267,38 @@ function nav($template = 'default') {
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
$syslist = Apps::app_order(local_channel(),$syslist);
$syslist = Apps::app_order(local_channel(),$syslist, 'nav_featured_app');
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
if($pinned_list) {
foreach($pinned_list as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
else {
$nav_apps[] = Apps::app_render($app,'nav');
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
}
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') !== false) {
$navbar_apps[] = Apps::app_render($app,'navbar');
}
if($syslist) {
foreach($syslist as $app) {
if(\App::$nav_sel['name'] == $app['name'])
$app['active'] = true;
if($is_owner) {
if(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Apps::app_render($app,'nav');
}
}
else {
$nav_apps[] = Apps::app_render($app,'nav');
elseif(! $is_owner && strpos($app['requires'], 'local_channel') === false) {
if(strpos($app['categories'],'nav_pinned_app') === false) {
$nav_apps[] = Apps::app_render($app,'nav');
}
}
}
}

View File

@@ -233,7 +233,7 @@ function z_post_url($url, $params, $redirects = 0, $opts = array()) {
return $ret;
if(! array_key_exists('request_target',$opts)) {
$opts['request_target'] = 'get ' . get_request_string($url);
$opts['request_target'] = 'post ' . get_request_string($url);
}
@curl_setopt($ch, CURLOPT_HEADER, true);
@@ -711,9 +711,9 @@ function scale_external_images($s, $include_link = true, $scale_replace = false)
foreach($matches as $mtch) {
logger('data: ' . $mtch[2] . ' ' . $mtch[3]);
if(substr($mtch[1],0,1) == '=') {
if(substr($mtch[2],0,1) == '=') {
$owidth = intval(substr($mtch[2],1));
if(intval($owidth) > 0 && intval($owidth) < 1024)
if($owidth > 0 && $owidth < 1024)
continue;
}

View File

@@ -221,7 +221,11 @@ function oembed_fetch_url($embedurl){
if(strpos(strtolower($embedurl),'.pdf') !== false) {
$action = 'allow';
$j = [ 'html' => '<object data="' . $embedurl . '" type="application/pdf" width="500" height="720">' . '<a href="' . $embedurl . '">' . t('View PDF') . '</a></object>', 'width' => 500, 'height' => 720, 'type' => 'pdf' ];
$j = [
'html' => '<object data="' . $embedurl . '" type="application/pdf" style="width: 100%; height: 300px;"></object>',
'title' => t('View PDF'),
'type' => 'pdf'
];
}
@@ -272,6 +276,7 @@ function oembed_fetch_url($embedurl){
}
$j['embedurl'] = $embedurl;
$j['zrl'] = $is_matrix;
// logger('fetch return: ' . print_r($j,true));
@@ -335,7 +340,11 @@ function oembed_format_object($j){
case "rich": {
// not so safe..
$ret.= $jhtml;
if($j['zrl']) {
$ret = ((preg_match('/^<div[^>]+>(.*?)<\/div>$/is',$j['html'],$o)) ? $o[1] : $j['html']);
} else {
$ret.= $jhtml;
};
}; break;
}

View File

@@ -350,8 +350,7 @@ abstract class photo_driver {
$p['allow_gid'] = (($arr['allow_gid']) ? $arr['allow_gid'] : '');
$p['deny_cid'] = (($arr['deny_cid']) ? $arr['deny_cid'] : '');
$p['deny_gid'] = (($arr['deny_gid']) ? $arr['deny_gid'] : '');
$p['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
$p['edited'] = (($arr['edited']) ? $arr['edited'] : $p['created']);
$p['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
$p['title'] = (($arr['title']) ? $arr['title'] : '');
$p['description'] = (($arr['description']) ? $arr['description'] : '');
$p['photo_usage'] = intval($arr['photo_usage']);
@@ -365,13 +364,15 @@ abstract class photo_driver {
if(! intval($p['imgscale']))
logger('save: ' . print_r($arr,true), LOGGER_DATA);
$x = q("select id from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
$x = q("select id, created from photo where resource_id = '%s' and uid = %d and xchan = '%s' and imgscale = %d limit 1",
dbesc($p['resource_id']),
intval($p['uid']),
dbesc($p['xchan']),
intval($p['imgscale'])
);
if($x) {
$p['created'] = (($x['created']) ? $x['created'] : $p['edited']);
$r = q("UPDATE photo set
aid = %d,
uid = %d,
@@ -412,7 +413,7 @@ abstract class photo_driver {
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']),
@@ -427,6 +428,7 @@ abstract class photo_driver {
);
}
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' )",
@@ -443,7 +445,7 @@ abstract class photo_driver {
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']),
@@ -464,11 +466,6 @@ abstract class photo_driver {
/**
* Guess image mimetype from filename or from Content-Type header
*
@@ -485,11 +482,11 @@ function guess_image_type($filename, $headers = '') {
$h = explode("\n",$headers);
foreach ($h as $l) {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[$k] = $v;
$hdrs[strtolower($k)] = $v;
}
logger('Curl headers: '.var_export($hdrs, true), LOGGER_DEBUG);
if (array_key_exists('Content-Type', $hdrs))
$type = $hdrs['Content-Type'];
if (array_key_exists('content-type', $hdrs))
$type = $hdrs['content-type'];
}
if (is_null($type)){
@@ -570,122 +567,166 @@ function delete_thing_photo($url,$ob_hash) {
function import_xchan_photo($photo,$xchan,$thing = false) {
/**
* @brief fetches an photo from external site and prepares its miniatures.
*
* @param string $photo
* external URL to fetch base image
* @param string $xchan
* channel unique hash
* @param boolean $thing
* TRUE if this is a thing URL
* @param boolean $force
* TRUE if ignore image modification date check (force fetch)
*
* @return array of results
* * \e string \b 0 => local URL to full image
* * \e string \b 1 => local URL to standard thumbnail
* * \e string \b 2 => local URL to micro thumbnail
* * \e string \b 3 => image type
* * \e boolean \b 4 => TRUE if fetch failure
* * \e string \b 5 => modification date
*/
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
$album = (($thing) ? 'Things' : 'Contact Photos');
function import_xchan_photo($photo,$xchan,$thing = false,$force = false) {
logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
$modified = '';
if($thing)
$hash = photo_new_resource();
else {
$r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
dbesc($xchan),
intval(PHOTO_XCHAN)
);
if($r) {
$hash = $r[0]['resource_id'];
}
else {
$hash = photo_new_resource();
}
}
$flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
$album = (($thing) ? 'Things' : 'Contact Photos');
$photo_failure = false;
$img_str = '';
logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
if($photo) {
$filename = basename($photo);
if($thing) {
$hash = photo_new_resource();
}
else {
$r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
dbesc($xchan),
intval(PHOTO_XCHAN)
);
if($r) {
$hash = $r[0]['resource_id'];
$modified = $r[0]['edited'];
$type = $r[0]['mimetype'];
}
else {
$hash = photo_new_resource();
}
}
$result = z_fetch_url($photo,true);
$photo_failure = false;
$img_str = '';
if($result['success']) {
$img_str = $result['body'];
$type = guess_image_type($photo, $result['header']);
if($photo) {
$filename = basename($photo);
$h = explode("\n",$result['header']);
if($h) {
foreach($h as $hl) {
if(stristr($hl,'content-type:')) {
if(! stristr($hl,'image/')) {
$photo_failure = true;
}
}
}
}
}
}
else {
$photo_failure = true;
}
if($force || $modified == '') {
$result = z_fetch_url($photo,true);
}
else {
$h = array('headers' => array("If-Modified-Since: " . gmdate("D, d M Y H:i:s", strtotime($modified . "Z")) . " GMT"));
$result = z_fetch_url($photo,true,0,$h);
}
if(! $photo_failure) {
$img = photo_factory($img_str, $type);
if($img->is_valid()) {
$width = $img->getWidth();
$height = $img->getHeight();
if($width && $height) {
if(($width / $height) > 1.2) {
// crop out the sides
$margin = $width - $height;
$img->cropImage(300,($margin / 2),0,$height,$height);
}
elseif(($height / $width) > 1.2) {
// crop out the bottom
$margin = $height - $width;
$img->cropImage(300,0,0,$width,$width);
if($result['success']) {
$img_str = $result['body'];
$type = guess_image_type($photo, $result['header']);
$modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
}
else {
$img->scaleImageSquare(300);
}
if(is_null($type))
$photo_failure = true;
}
elseif($result['return_code'] == 304) {
$photo = z_root() . '/photo/' . $hash . '-4';
$thumb = z_root() . '/photo/' . $hash . '-5';
$micro = z_root() . '/photo/' . $hash . '-6';
}
else {
$photo_failure = true;
}
}
else
$photo_failure = true;
}
else
$photo_failure = true;
$p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4);
if(! $photo_failure && $result['return_code'] != 304) {
$img = photo_factory($img_str, $type);
if($img->is_valid()) {
$width = $img->getWidth();
$height = $img->getHeight();
$r = $img->save($p);
if($width && $height) {
if(($width / $height) > 1.2) {
// crop out the sides
$margin = $width - $height;
$img->cropImage(300,($margin / 2),0,$height,$height);
}
elseif(($height / $width) > 1.2) {
// crop out the bottom
$margin = $height - $width;
$img->cropImage(300,0,0,$width,$width);
if($r === false)
$photo_failure = true;
}
else {
$img->scaleImageSquare(300);
}
$img->scaleImage(80);
$p['imgscale'] = 5;
$r = $img->save($p);
}
else
$photo_failure = true;
if($r === false)
$photo_failure = true;
$img->scaleImage(48);
$p['imgscale'] = 6;
$r = $img->save($p);
$p = array(
'xchan' => $xchan,
'resource_id' => $hash,
'filename' => basename($photo),
'album' => $album,
'photo_usage' => $flags,
'imgscale' => 4,
'edited' => $modified
);
if($r === false)
$photo_failure = true;
$r = $img->save($p);
$photo = z_root() . '/photo/' . $hash . '-4';
$thumb = z_root() . '/photo/' . $hash . '-5';
$micro = z_root() . '/photo/' . $hash . '-6';
}
else {
logger('import_xchan_photo: invalid image from ' . $photo);
$photo_failure = true;
}
}
if($photo_failure) {
$photo = z_root() . '/' . get_default_profile_photo();
$thumb = z_root() . '/' . get_default_profile_photo(80);
$micro = z_root() . '/' . get_default_profile_photo(48);
$type = 'image/png';
}
if($r === false)
$photo_failure = true;
return(array($photo,$thumb,$micro,$type,$photo_failure));
$img->scaleImage(80);
$p['imgscale'] = 5;
$r = $img->save($p);
if($r === false)
$photo_failure = true;
$img->scaleImage(48);
$p['imgscale'] = 6;
$r = $img->save($p);
if($r === false)
$photo_failure = true;
$photo = z_root() . '/photo/' . $hash . '-4';
$thumb = z_root() . '/photo/' . $hash . '-5';
$micro = z_root() . '/photo/' . $hash . '-6';
}
else {
logger('import_xchan_photo: invalid image from ' . $photo);
$photo_failure = true;
}
}
if($photo_failure) {
$default = get_default_profile_photo();
$photo = z_root() . '/' . $default;
$thumb = z_root() . '/' . get_default_profile_photo(80);
$micro = z_root() . '/' . get_default_profile_photo(48);
$type = 'image/png';
$modified = gmdate('Y-m-d H:i:s', filemtime($default));
}
logger('HTTP code: ' . $result['return_code'] . '; modified: ' . $modified . '; failure: ' . ($photo_failure ? 'yes' : 'no') . '; URL: ' . $photo, LOGGER_DEBUG);
return(array($photo,$thumb,$micro,$type,$photo_failure,$modified));
}
@@ -700,16 +741,8 @@ function import_channel_photo_from_url($photo,$aid,$uid) {
$img_str = $result['body'];
$type = guess_image_type($photo, $result['header']);
$h = explode("\n",$result['header']);
if($h) {
foreach($h as $hl) {
if(stristr($hl,'content-type:')) {
if(! stristr($hl,'image/')) {
$photo_failure = true;
}
}
}
}
if(is_null($type))
$photo_failure = true;
}
}
else {

View File

@@ -31,8 +31,13 @@ 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));
return;
}
/**
* Setup the image to the format it will be saved to
@@ -205,4 +210,4 @@ class photo_imagick extends photo_driver {
}
}

View File

@@ -1011,23 +1011,3 @@ function profile_photo_set_profile_perms($uid, $profileid = 0) {
}
}
}
function fetch_image_from_url($url,&$mimetype) {
$redirects = 0;
$x = z_fetch_url($url,true,$redirects,[ 'novalidate' => true ]);
if($x['success']) {
$hdrs = [];
$h = explode("\n",$x['header']);
foreach ($h as $l) {
list($k,$v) = array_map("trim", explode(":", trim($l), 2));
$hdrs[strtolower($k)] = $v;
}
if (array_key_exists('content-type', $hdrs))
$mimetype = $hdrs['content-type'];
return $x['body'];
}
return EMPTY_STR;
}

View File

@@ -633,6 +633,19 @@ function attribute_contains($attr, $s) {
return false;
}
/**
* @brief Log to syslog
*
* @param string $msg Message to log
* @param int $priority - compatible with syslog
*/
function hz_syslog($msg, $priority = LOG_INFO) {
openlog("hz-log", LOG_PID | LOG_PERROR, LOG_LOCAL0);
syslog($priority, $msg);
closelog();
}
/**
* @brief Logging function for Hubzilla.
*
@@ -3204,6 +3217,28 @@ function array2XML($obj, $array) {
}
}
function array_path_exists($str,$arr) {
$ptr = $arr;
$search = explode('/', $str);
if($search) {
foreach($search as $s) {
if(array_key_exists($s,$ptr)) {
$ptr = $ptr[$s];
}
else {
return false;
}
}
return true;
}
return false;
}
/**
* @brief Inserts an array into $table.
*
@@ -3219,8 +3254,16 @@ function create_table_from_array($table, $arr, $binary_fields = []) {
if(! ($arr && $table))
return false;
$columns = db_columns($table);
$clean = [];
foreach($arr as $k => $v) {
if(! in_array($k,$columns)) {
continue;
}
$matches = false;
if(preg_match('/([^a-zA-Z0-9\-\_\.])/',$k,$matches)) {
return false;
@@ -3404,7 +3447,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)
);
@@ -3459,3 +3502,4 @@ function print_val($v) {
return $v;
}

View File

@@ -1,5 +1,7 @@
<?php
use Zotlabs\Zot6\HTTPSig;
function xchan_store_lowlevel($arr) {
@@ -39,6 +41,13 @@ function xchan_store_lowlevel($arr) {
function xchan_store($arr) {
$update_photo = false;
$update_name = false;
if(! ($arr['guid'] || $arr['hash'])) {
$arr = json_decode(file_get_contents('php://input'),true);
}
logger('xchan_store: ' . print_r($arr,true));
if(! $arr['hash'])
@@ -49,57 +58,90 @@ function xchan_store($arr) {
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
dbesc($arr['hash'])
);
if($r)
return true;
if(! $r) {
if(! $arr['network'])
$arr['network'] = 'unknown';
if(! $arr['name'])
$arr['name'] = 'unknown';
if(! $arr['url'])
$arr['url'] = z_root();
if(! $arr['photo'])
$arr['photo'] = z_root() . '/' . get_default_profile_photo();
$update_photo = true;
if(! $arr['network'])
$arr['network'] = 'unknown';
if(! $arr['name'])
$arr['name'] = 'unknown';
if(! $arr['url'])
$arr['url'] = z_root();
if(! $arr['photo'])
$arr['photo'] = z_root() . '/' . get_default_profile_photo();
if($arr['network'] === 'zot') {
if((! $arr['key']) || (! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key']))) {
logger('Unable to verify signature for ' . $arr['hash']);
return false;
if($arr['network'] === 'zot6') {
if((! $arr['key']) || (! Libzot::verify($arr['id'],$arr['id_sig'],$arr['key']))) {
logger('Unable to verify signature for ' . $arr['hash']);
return false;
}
}
}
$x = [];
foreach($arr as $k => $v) {
if($k === 'key') {
$x['xchan_pubkey'] = $v;
continue;
}
if($k === 'photo') {
continue;
if($arr['network'] === 'zot') {
if((! $arr['key']) || (! rsa_verify($arr['guid'],base64url_decode($arr['guid_sig']),$arr['key']))) {
logger('Unable to verify signature for ' . $arr['hash']);
return false;
}
}
$columns = db_columns('xchan');
$x = [];
foreach($arr as $k => $v) {
if($k === 'key') {
$x['xchan_pubkey'] = HTTPSig::convertKey(escape_tags($v));;
continue;
}
if($k === 'photo') {
continue;
}
$x['xchan_' . $k] = $v;
if(in_array($columns,'xchan_' . $k))
$x['xchan_' . $k] = escape_tags($v);
}
$x['xchan_name_date'] = datetime_convert();
$x['xchan_photo_date'] = datetime_convert();
$x['xchan_system'] = false;
$result = xchan_store_lowlevel($x);
if(! $result)
return $result;
}
else {
if($r[0]['network'] === 'zot6') {
return true;
}
if($r[0]['xchan_photo_date'] < datetime_convert('UTC','UTC',$arr['photo_date'])) {
$update_photo = true;
}
if($r[0]['xchan_name_date'] < datetime_convert('UTC','UTC',$arr['name_date'])) {
$update_name = true;
}
}
if($update_photo && $arr['photo']) {
$photos = import_xchan_photo($arr['photo'],$arr['hash']);
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($arr['hash'])
);
}
if($update_name && $arr['name']) {
$x = q("update xchan set xchan_name = '%s', xchan_name_date = '%s' where xchan_hash = '%s'",
dbesc(escape_tags($arr['name'])),
dbesc(datetime_convert()),
dbesc($arr['hash'])
);
}
$x['xchan_name_date'] = datetime_convert();
$r = xchan_store_lowlevel($x);
if(! $r)
return $r;
$photos = import_xchan_photo($arr['photo'],$arr['hash']);
$r = q("update xchan set xchan_photo_date = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s' where xchan_hash = '%s'",
dbesc(datetime_convert()),
dbesc($photos[0]),
dbesc($photos[1]),
dbesc($photos[2]),
dbesc($photos[3]),
dbesc($arr['hash'])
);
return $r;
return true;
}

View File

@@ -1187,13 +1187,13 @@ function zot_fetch($arr) {
$zret = zot6_check_sig();
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $data['sender']['guid'] && $data['msg']) {
if($zret['success'] && $zret['hubloc'] && $zret['hubloc']['hubloc_guid'] === $arr['sender']['guid'] && $arr['msg']) {
logger('zot6_delivery',LOGGER_DEBUG);
logger('zot6_data: ' . print_r($data,true),LOGGER_DATA);
logger('zot6_data: ' . print_r($arr,true),LOGGER_DATA);
$ret['collected'] = true;
$import = [ 'success' => true, 'body' => json_encode( [ 'success' => true, 'pickup' => [ [ 'notify' => $data, 'message' => json_decode($data['msg'],true) ] ] ] ) ];
$import = [ 'success' => true, 'body' => json_encode( [ 'success' => true, 'pickup' => [ [ 'notify' => $arr, 'message' => json_decode($arr['msg'],true) ] ] ] ) ];
$hubs = [ $zret['hubloc'] ] ;
}
@@ -3507,8 +3507,41 @@ function process_channel_sync_delivery($sender, $arr, $deliveries) {
if(array_key_exists('config',$arr) && is_array($arr['config']) && count($arr['config'])) {
foreach($arr['config'] as $cat => $k) {
foreach($arr['config'][$cat] as $k => $v)
set_pconfig($channel['channel_id'],$cat,$k,$v);
$pconfig_updated = [];
$pconfig_del = [];
foreach($arr['config'][$cat] as $k => $v) {
if (strpos($k,'pcfgud:')===0) {
$realk = substr($k,7);
$pconfig_updated[$realk] = $v;
unset($arr['config'][$cat][$k]);
}
if (strpos($k,'pcfgdel:')===0) {
$realk = substr($k,8);
$pconfig_del[$realk] = datetime_convert();
unset($arr['config'][$cat][$k]);
}
}
foreach($arr['config'][$cat] as $k => $v) {
if (!isset($pconfig_updated[$k])) {
$pconfig_updated[$k] = NULL;
}
set_pconfig($channel['channel_id'],$cat,$k,$v,$pconfig_updated[$k]);
}
foreach($pconfig_del as $k => $updated) {
del_pconfig($channel['channel_id'],$cat,$k,$updated);
}
}
}

View File

@@ -910,7 +910,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 '',
@@ -922,15 +921,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` (

View File

@@ -891,7 +891,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,
@@ -900,7 +899,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");
@@ -910,9 +908,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,

File diff suppressed because one or more lines are too long

View File

@@ -52,12 +52,12 @@ class MarkdownTest extends UnitTestCase {
' &nbsp;',
''
],
/* it is not clear why this test fails
'strong, b, em, i, bib' => [
'<strong>strong</strong> <b>bold</b> <em>em</em> <i>italic</i> <b>bo<i>italic</i>ld</b>',
'**strong** **bold** _em_ _italic_ **bo_italic_ld**'
'**strong** **bold** *em* *italic* **bo*italic*ld**'
],
*/
'empty tags' => [
'text1 <b></b> text2 <i></i>',
'text1 text2'
@@ -70,10 +70,6 @@ class MarkdownTest extends UnitTestCase {
'&amp; lt &lt; gt &gt;',
'& lt < gt >'
],
'our escaped HTML entities' => [
'&_lt_; &_gt_; &_amp_;',
'&\_lt\_; &\_gt\_; &\_amp\_;'
],
'linebreak' => [
"line1<br>line2\nline3",
"line1 \nline2 line3"
@@ -84,15 +80,15 @@ class MarkdownTest extends UnitTestCase {
],
'unordered list' => [
'<ul><li>Item 1</li><li>Item 2</li><li>Item <b>3</b></li></ul>',
"- Item 1\n- Item 2\n- Item 3"
"- Item 1\n- Item 2\n- Item **3**"
],
'ordered list' => [
'<ol><li>Item 1</li><li>Item 2</li><li>Item <b>3</b></li></ol>',
"1. Item 1\n2. Item 2\n3. Item 3"
"1. Item 1\n2. Item 2\n3. Item **3**"
],
'nested lists' => [
'<ul><li>Item 1<ol><li>Item 1a</li><li>Item <b>1b</b></ol></li><li>Item 2</li></ul>',
"- Item 1\n 1. Item 1a\n 2. Item 1b\n- Item 2"
"- Item 1\n 1. Item 1a\n 2. Item **1b**\n- Item 2"
],
'img' => [
'<img src="/path/to/img.png" alt="alt text" title="title text">',
@@ -118,12 +114,10 @@ class MarkdownTest extends UnitTestCase {
'<code>&lt;p&gt;HTML text&lt;/p&gt;</code>',
'`<p>HTML text</p>`'
],
/* it is not clear why this test fails
'pre' => [
'<pre> line with spaces </pre>',
'` line with spaces `'
'<pre> one line with spaces </pre>',
"```\n one line with spaces \n```"
],
*/
'div p' => [
'<div>div</div><div><p>p</p></div>',
"<div>div</div><div>p\n\n</div>"

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,22 @@
# jQuery File Upload Plugin
## Demo
[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
## Description
File Upload widget with multiple file selection, drag&amp;drop support, progress bars, validation and preview images, audio and video for jQuery.
Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.
## Demo
[Demo File Upload](https://blueimp.github.io/jQuery-File-Upload/)
## ⚠️ Security Notice
Security related releases:
* [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) Mitigates some [Potential vulnerabilities with PHP+ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick).
* [v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1) Fixes a [Remote code execution vulnerability in the PHP component](VULNERABILITIES.md#remote-code-execution-vulnerability-in-the-php-component).
* v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1) Fixes an [Open redirect vulnerability in the GAE components](VULNERABILITIES.md#open-redirect-vulnerability-in-the-gae-components).
* Commit [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a) (*fixed in all tagged releases*) Fixes a [Cross-site scripting vulnerability in the Iframe Transport](VULNERABILITIES.md#cross-site-scripting-vulnerability-in-the-iframe-transport).
Please read the [SECURITY](SECURITY.md) document for instructions on how to securely configure your Webserver for file uploads.
## Setup
* [How to setup the plugin on your website](https://github.com/blueimp/jQuery-File-Upload/wiki/Setup)
* [How to use only the basic plugin (minimal setup guide).](https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin)
@@ -15,7 +25,7 @@ Supports cross-domain, chunked and resumable file uploads and client-side image
* **Multiple file upload:**
Allows to select multiple files at once and upload them simultaneously.
* **Drag & Drop support:**
Allows to upload files by dragging them from your desktop or filemanager and dropping them on your browser window.
Allows to upload files by dragging them from your desktop or file manager and dropping them on your browser window.
* **Upload progress bar:**
Shows a progress bar indicating the upload progress for individual files and for all uploads combined.
* **Cancelable uploads:**

View File

@@ -0,0 +1,133 @@
# File Upload Security
For an in-depth understanding of the potential security risks of providing file uploads and possible mitigations, please refer to the [OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload) documentation.
To securely setup the project to serve uploaded files, please refer to the sample [Secure file upload serving configurations](#secure-file-upload-serving-configurations).
To mitigate potential vulnerabilities in image processing libraries, please refer to the [Secure image processing configurations](#secure-image-processing-configurations).
By default, all sample upload handlers allow only upload of image files, which mitigates some attack vectors, but should not be relied on as the only protection.
Please also have a look at the [list of fixed vulnerabilities](VULNERABILITIES.md) in jQuery File Upload, which relates mostly to the sample server-side upload handlers and how they have been configured.
## Purpose of this project
Please note that this project is not a complete file management product, but foremost a client-side file upload library for [jQuery](https://jquery.com/).
The server-side sample upload handlers are just examples to demonstrate the client-side file upload functionality.
To make this very clear, there is **no user authentication** by default:
* **everyone can upload files**
* **everyone can delete uploaded files**
In some cases this can be acceptable, but for most projects you will want to extend the sample upload handlers to integrate user authentication, or implement your own.
It is also up to you to configure your Webserver to securely serve the uploaded files, e.g. using the [sample server configurations](#secure-file-upload-serving-configurations).
## Mitigations against file upload risks
### Prevent code execution on the server
To prevent execution of scripts or binaries on server-side, the upload directory must be configured to not execute files in the upload directory (e.g. `server/php/files` as the default for the PHP upload handler) and only treat uploaded files as static content.
The recommended way to do this is to configure the upload directory path to point outside of the web application root.
Then the Webserver can be configured to serve files from the upload directory with their default static files handler only.
Limiting file uploads to a whitelist of safe file types (e.g. image files) also mitigates this issue, but should not be the only protection.
### Prevent code execution in the browser
To prevent execution of scripts on client-side, the following headers must
be sent when delivering generic uploaded files to the client:
```
Content-Type: application/octet-stream
X-Content-Type-Options: nosniff
```
The `Content-Type: application/octet-stream` header instructs browsers to display a download dialog instead of parsing it and possibly executing script content e.g. in HTML files.
The `X-Content-Type-Options: nosniff` header prevents browsers to try to detect the file mime type despite the given content-type header.
For known safe files, the content-type header can be adjusted using a **whitelist**, e.g. sending `Content-Type: image/png` for PNG files.
### Prevent distribution of malware
To prevent attackers from uploading and distributing malware (e.g. computer viruses), it is recommended to limit file uploads only to a whitelist of safe file types.
Please note that the detection of file types in the sample file upload handlers is based on the file extension and not the actual file content. This makes it still possible for attackers to upload malware by giving their files an image file extension, but should prevent automatic execution on client computers when opening those files.
It does not protect at all from exploiting vulnerabilities in image display programs, nor from users renaming file extensions to inadvertently execute the contained malicious code.
## Secure file upload serving configurations
The following configurations serve uploaded files as static files with the proper headers as [mitigation against file upload risks](#mitigations-against-file-upload-risks).
Please do not simply copy&paste these configurations, but make sure you understand what they are doing and that you have implemented them correctly.
> Always test your own setup and make sure that it is secure!
e.g. try uploading PHP scripts (as "example.php", "example.php.png" and "example.png") to see if they get executed by your Webserver.
### Apache config
Add the following directive to the Apache config, replacing the directory path with the absolute path to the upload directory:
```ApacheConf
<Directory "/path/to/project/server/php/files">
# To enable the Headers module, execute the following command and reload Apache:
# sudo a2enmod headers
# The following directives prevent the execution of script files
# in the context of the website.
# They also force the content-type application/octet-stream and
# force browsers to display a download dialog for non-image files.
SetHandler default-handler
ForceType application/octet-stream
Header set Content-Disposition attachment
# The following unsets the forced type and Content-Disposition headers
# for known image files:
<FilesMatch "(?i)\.(gif|jpe?g|png)$">
ForceType none
Header unset Content-Disposition
</FilesMatch>
# The following directive prevents browsers from MIME-sniffing the content-type.
# This is an important complement to the ForceType directive above:
Header set X-Content-Type-Options nosniff
</Directory>
```
### NGINX config
Add the following directive to the NGINX config, replacing the directory path with the absolute path to the upload directory:
```Nginx
location ^~ /path/to/project/server/php/files {
root html;
default_type application/octet-stream;
types {
image/gif gif;
image/jpeg jpg;
image/png png;
}
add_header X-Content-Type-Options 'nosniff';
if ($request_filename ~ /(((?!\.(jpg)|(png)|(gif)$)[^/])+$)) {
add_header Content-Disposition 'attachment; filename="$1"';
# Add X-Content-Type-Options again, as using add_header in a new context
# dismisses all previous add_header calls:
add_header X-Content-Type-Options 'nosniff';
}
}
```
## Secure image processing configurations
The following configuration mitigates [potential image processing vulnerabilities with ImageMagick](VULNERABILITIES.md#potential-vulnerabilities-with-php-imagemagick) by limiting the attack vectors to a small subset of image types (`GIF/JPEG/PNG`).
Please also consider using alternative, safer image processing libraries like [libvips](https://github.com/libvips/libvips) or [imageflow](https://github.com/imazen/imageflow).
## ImageMagick config
It is recommended to disable all non-required ImageMagick coders via [policy.xml](https://wiki.debian.org/imagemagick/security).
To do so, locate the ImageMagick `policy.xml` configuration file and add the following policies:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- ... -->
<policymap>
<!-- ... -->
<policy domain="delegate" rights="none" pattern="*" />
<policy domain="coder" rights="none" pattern="*" />
<policy domain="coder" rights="read | write" pattern="{GIF,JPEG,PNG}" />
</policymap>
```

View File

@@ -0,0 +1,65 @@
# ⚠️ List of fixed vulnerabilities
## Potential vulnerabilities with PHP+ImageMagick
> Mitigated: 2018-10-25 (GMT)
The sample [PHP upload handler](server/php/UploadHandler.php) before [v9.25.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.25.1) did not validate file signatures before invoking [ImageMagick](https://www.imagemagick.org/) (via [Imagick](http://php.net/manual/en/book.imagick.php)).
Verifying those [magic bytes](https://en.wikipedia.org/wiki/List_of_file_signatures) mitigates potential vulnerabilities when handling input files other than `GIF/JPEG/PNG`.
Please also configure ImageMagick to only enable the coders required for `GIF/JPEG/PNG` processing, e.g. with the sample [ImageMagick config](SECURITY.md#imagemagick-config).
**Further information:**
* Commit containing the mitigation: [fe44d34](https://github.com/blueimp/jQuery-File-Upload/commit/fe44d34be43be32c6b8d507932f318dababb25dd)
* [ImageTragick](https://imagetragick.com/)
* [CERT Vulnerability Note VU#332928](https://www.kb.cert.org/vuls/id/332928)
* [ImageMagick CVE entries](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=imagemagick)
## Remote code execution vulnerability in the PHP component
> Fixed: 2018-10-23 (GMT)
The sample [PHP upload handler](server/php/UploadHandler.php) before [v9.24.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/v9.24.1) allowed to upload all file types by default.
This opens up a remote code execution vulnerability, unless the server is configured to not execute (PHP) files in the upload directory (`server/php/files`).
The provided [.htaccess](server/php/files/.htaccess) file includes instructions for Apache to disable script execution, however [.htaccess support](https://httpd.apache.org/docs/current/howto/htaccess.html) is disabled by default since Apache `v2.3.9` via [AllowOverride Directive](https://httpd.apache.org/docs/current/mod/core.html#allowoverride).
**You are affected if you:**
1. A) Uploaded jQuery File Upload < `v9.24.1` on a Webserver that executes files with `.php` as part of the file extension (e.g. "example.php.png"), e.g. Apache with `mod_php` enabled and the following directive (*not a recommended configuration*):
```ApacheConf
AddHandler php5-script .php
```
B) Uploaded jQuery File Upload < `v9.22.1` on a Webserver that executes files with the file extension `.php`, e.g. Apache with `mod_php` enabled and the following directive:
```ApacheConf
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
```
2. Did not actively configure your Webserver to not execute files in the upload directory (`server/php/files`).
3. Are running Apache `v2.3.9+` with the default `AllowOverride` Directive set to `None` or another Webserver with no `.htaccess` support.
**How to fix it:**
1. Upgrade to the latest version of jQuery File Upload.
2. Configure your Webserver to not execute files in the upload directory, e.g. with the [sample Apache configuration](SECURITY.md#apache-config)
**Further information:**
* Commits containing the security fix: [aeb47e5](https://github.com/blueimp/jQuery-File-Upload/commit/aeb47e51c67df8a504b7726595576c1c66b5dc2f), [ad4aefd](https://github.com/blueimp/jQuery-File-Upload/commit/ad4aefd96e4056deab6fea2690f0d8cf56bb2d7d)
* [Full disclosure post on Hacker News](https://news.ycombinator.com/item?id=18267309).
* [CVE-2018-9206](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-9206)
* [OWASP - Unrestricted File Upload](https://www.owasp.org/index.php/Unrestricted_File_Upload)
## Open redirect vulnerability in the GAE components
> Fixed: 2015-06-12 (GMT)
The sample Google App Engine upload handlers before v[9.10.1](https://github.com/blueimp/jQuery-File-Upload/releases/tag/9.10.1) accepted any URL as redirect target, making it possible to use the Webserver's domain for phishing attacks.
**Further information:**
* Commit containing the security fix: [f74d2a8](https://github.com/blueimp/jQuery-File-Upload/commit/f74d2a8c3e3b1e8e336678d2899facd5bcdb589f)
* [OWASP - Unvalidated Redirects and Forwards Cheat Sheet](https://www.owasp.org/index.php/Unvalidated_Redirects_and_Forwards_Cheat_Sheet)
## Cross-site scripting vulnerability in the Iframe Transport
> Fixed: 2012-08-09 (GMT)
The [redirect page](cors/result.html) for the [Iframe Transport](js/jquery.iframe-transport.js) before commit [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a) (*fixed in all tagged releases*) allowed executing arbitrary JavaScript in the context of the Webserver.
**Further information:**
* Commit containing the security fix: [4175032](https://github.com/blueimp/jQuery-File-Upload/commit/41750323a464e848856dc4c5c940663498beb74a)
* [OWASP - Cross-site Scripting (XSS)](https://www.owasp.org/index.php/Cross-site_Scripting_(XSS))

View File

@@ -22,7 +22,7 @@
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support, progress bars, validation and preview images, audio and video for AngularJS. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap styles -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Generic page styles -->
<link rel="stylesheet" href="css/style.css">
<!-- blueimp Gallery styles -->
@@ -177,8 +177,8 @@
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" integrity="sha384-r6jjWwxAypHaESwS5an5J9dkfzwQuKVNV9FZM9B6fnt8PFuY0cVwLhV7BltCZhLy" crossorigin="anonymous"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
@@ -186,7 +186,7 @@
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- blueimp Gallery script -->
<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->

View File

@@ -20,7 +20,7 @@
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;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.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap styles -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Generic page styles -->
<link rel="stylesheet" href="css/style.css">
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
@@ -96,15 +96,15 @@
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
<script src="https://blueimp.github.io/JavaScript-Load-Image/js/load-image.all.min.js"></script>
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->

View File

@@ -20,7 +20,7 @@
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support and progress bar for jQuery. Supports cross-domain, chunked and resumable file uploads. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap styles -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Generic page styles -->
<link rel="stylesheet" href="css/style.css">
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
@@ -96,7 +96,7 @@
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
@@ -104,7 +104,7 @@
<!-- The basic File Upload plugin -->
<script src="js/jquery.fileupload.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script>
/*jslint unparam: true */
/*global window, $ */

View File

@@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
"version": "9.23.0",
"version": "9.28.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

@@ -0,0 +1,39 @@
{
"name": "blueimp/jquery-file-upload"
, "description": "File Upload widget for jQuery."
, "keywords": ["jquery",
"file",
"upload",
"widget",
"multiple",
"selection",
"drag",
"drop",
"progress",
"preview",
"cross-domain",
"cross-site",
"chunk",
"resume",
"gae",
"go",
"python",
"php",
"bootstrap"]
, "homepage": "https://github.com/blueimp/jQuery-File-Upload"
, "authors": [
{
"name": "Sebastian Tschan",
"homepage": "https://blueimp.net"
}
]
, "support": {
"forum": "https://groups.google.com/forum/#!forum/jquery-fileupload"
}
, "license": "MIT"
, "autoload": {
"classmap": [
"server/php/UploadHandler.php"
]
}
}

View File

@@ -15,7 +15,7 @@
<head>
<meta charset="utf-8">
<title>jQuery File Upload Plugin postMessage API</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
</head>
<body>
<script>

View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -22,7 +22,7 @@
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Bootstrap styles -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Generic page styles -->
<link rel="stylesheet" href="css/style.css">
<!-- blueimp Gallery styles -->
@@ -216,7 +216,7 @@
</tr>
{% } %}
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<!-- The jQuery UI widget factory, can be omitted if jQuery UI is already included -->
<script src="js/vendor/jquery.ui.widget.js"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
@@ -226,7 +226,7 @@
<!-- The Canvas to Blob plugin is included for image resizing functionality -->
<script src="https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js"></script>
<!-- Bootstrap JS is not required, but included for the responsive demo navigation -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- blueimp Gallery script -->
<script src="https://blueimp.github.io/Gallery/js/jquery.blueimp-gallery.min.js"></script>
<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->

View File

@@ -22,7 +22,7 @@
<meta name="description" content="File Upload widget with multiple file selection, drag&amp;drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- jQuery UI styles -->
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" id="theme">
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" integrity="sha384-ufZtQaOYGuy/CibAC5jmelOpBu3H78Js7HrXSLo4LGccHUrGGHXt+uaTcDbio3kI" crossorigin="anonymous">
<!-- Generic page styles -->
<link rel="stylesheet" href="css/style.css">
<!-- Demo styles -->
@@ -201,8 +201,8 @@
</tr>
{% } %}
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha384-xBuQ/xzmlsLoJpyjoggmTEz8OWUFM0/RC5BsqQBDX2v5cMvDHcMakNTNrHIW2I5f" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha384-Dziy8F2VlJQLMShA6FHWNul/veM9bCkRUaLqr199K94ntO5QUrLJBEbYegdSkkqX" crossorigin="anonymous"></script>
<!-- The Templates plugin is included to render the upload/download listings -->
<script src="https://blueimp.github.io/JavaScript-Templates/js/tmpl.min.js"></script>
<!-- The Load Image plugin is included for the preview images and image resizing functionality -->

View File

@@ -1,6 +1,6 @@
{
"name": "blueimp-file-upload",
"version": "9.23.0",
"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": [

View File

@@ -1,5 +1,3 @@
application: jquery-file-upload
version: 2
runtime: go
api_version: go1

View File

@@ -1,5 +1,3 @@
application: jquery-file-upload
version: 1
runtime: python27
api_version: 1
threadsafe: true

Some files were not shown because too many files have changed in this diff Show More