Compare commits
523 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
1da3828a09 | ||
|
982ff8733f | ||
|
ebe374d572 | ||
|
dd45e7b4eb | ||
|
63eb0e3a38 | ||
|
f472071f6f | ||
|
7b695aa684 | ||
|
de4b5978c3 | ||
|
f23f8f7f5d | ||
|
f64acadd58 | ||
|
68ea1d0289 | ||
|
1574043a9e | ||
|
a2a5580e68 | ||
|
2696cf9b9e | ||
|
d9f962ee6f | ||
|
7468d8a000 | ||
|
270bb4e2d9 | ||
|
d3d9b06eb7 | ||
|
e7131bc8f8 | ||
|
1df1c15e48 | ||
|
986244eeea | ||
|
526bc36b40 | ||
|
9bdb7bef5d | ||
|
54e7d5d260 | ||
|
5265c190d4 | ||
|
4b7c052ed8 | ||
|
b62e7e7d8b | ||
|
fd290882fd | ||
|
09015f8924 | ||
|
b5f382f0ea | ||
|
ccd13dd643 | ||
|
d66715648a | ||
|
e07ff7d3fb | ||
|
0d60789f69 | ||
|
e769fbaffb | ||
|
5721f9f3a9 | ||
|
cca9f2392e | ||
|
928fa44154 | ||
|
a795f03c48 | ||
|
8f7b869c08 | ||
|
c5294f994e | ||
|
34f52e47eb | ||
|
f950d27b3d | ||
|
2a2da48d18 | ||
|
0b1cd826b0 | ||
|
b3525b8657 | ||
|
8d5556764c | ||
|
f965209eee | ||
|
5c526995d8 | ||
|
50ee82e8bd | ||
|
8a3c909c74 | ||
|
3a8e1e0484 | ||
|
3b53cd56ef | ||
|
30e88a4f6b | ||
|
e5f47cd14b | ||
|
6368b09337 | ||
|
b97102da01 | ||
|
dbeae16dc1 | ||
|
edbcba6f11 | ||
|
ed876a9c52 | ||
|
67fe8fc4a7 | ||
|
55b530f0fd | ||
|
3a2c3ea8fa | ||
|
aae51a9b23 | ||
|
cd2b811555 | ||
|
15d1a6c937 | ||
|
9ab335626c | ||
|
451db7dd98 | ||
|
d6293730fc | ||
|
8e410f14b1 | ||
|
49000dadda | ||
|
9bde18492a | ||
|
b22fa9f7f4 | ||
|
a7b2d23e9b | ||
|
ba94f824b9 | ||
|
8aec437c23 | ||
|
98f656cfcb | ||
|
e558ddae3f | ||
|
2c665e5e4c | ||
|
2fe3d16bbe | ||
|
2844f276b9 | ||
|
414b5ea6f3 | ||
|
c42dcd5ac9 | ||
|
b9723aa85b | ||
|
03fb13e749 | ||
|
e04f04ef0f | ||
|
0f3c2c4b24 | ||
|
8a94a4938f | ||
|
b553ffd55d | ||
|
e45958b967 | ||
|
0bfdb45b41 | ||
|
8cbccb20ef | ||
|
f506f73d3f | ||
|
7734bbfe4d | ||
|
d35c5bcb2f | ||
|
c699d3a17a | ||
|
d16ac62a51 | ||
|
2fa5b8c0a2 | ||
|
15feeb7bfe | ||
|
02ecc93998 | ||
|
34291d5938 | ||
|
e726adc27b | ||
|
642f460dca | ||
|
1d7d9818fa | ||
|
c2dcc68803 | ||
|
d7c9f2ccba | ||
|
7dd61c05dc | ||
|
1c1155513a | ||
|
f84151e1fe | ||
|
4b13f0e025 | ||
|
2869ccfe39 | ||
|
8ead4745f8 | ||
|
15b241cc3e | ||
|
2b07a69b93 | ||
|
5068ce0569 | ||
|
0b1b11ea53 | ||
|
ea9f169a6c | ||
|
cbd7f89066 | ||
|
146ff6f703 | ||
|
326ae5ff6b | ||
|
8c16f12d7a | ||
|
477228d4ff | ||
|
9baaa6fa56 | ||
|
7834274bff | ||
|
d2565d0f61 | ||
|
4fde0bf62e | ||
|
a679081993 | ||
|
177292de13 | ||
|
efcb4abfd0 | ||
|
1501d1c570 | ||
|
59a56ac77f | ||
|
35f09f4f74 | ||
|
421dfce599 | ||
|
b240c15014 | ||
|
9de8df496a | ||
|
4f65066572 | ||
|
c38687725d | ||
|
099f236f45 | ||
|
996cd7e2ab | ||
|
77df590f65 | ||
|
ce064188c6 | ||
|
5d6f59a598 | ||
|
f4a4cf1402 | ||
|
032ef0ca34 | ||
|
5a7e8d8520 | ||
|
63146821d7 | ||
|
9ed8eac8c6 | ||
|
40bb1699a5 | ||
|
74827133b2 | ||
|
7c8706757d | ||
|
3dc066a143 | ||
|
43251ed8ce | ||
|
1a16822987 | ||
|
fdd4c1b9d1 | ||
|
1bd1050160 | ||
|
525a0478b0 | ||
|
ce28760c2a | ||
|
438cb1d7e0 | ||
|
87c8cf4892 | ||
|
f2fefb91d5 | ||
|
4d05d477f8 | ||
|
cc95c3e9c8 | ||
|
f0a7a6a1e2 | ||
|
4090843fef | ||
|
c6c18261a0 | ||
|
d9e83eb53a | ||
|
1cf404177d | ||
|
ed9ffec5ba | ||
|
582607c0f0 | ||
|
6cd5826d21 | ||
|
b7e953f50e | ||
|
9f630b6653 | ||
|
3017dbc8c1 | ||
|
5d33b34be7 | ||
|
f2104b0a5a | ||
|
84b004399e | ||
|
e8a01f0916 | ||
|
4f1d579ba1 | ||
|
c34d8286a3 | ||
|
4eb389f2d9 | ||
|
999ac60a87 | ||
|
30af694e30 | ||
|
fa76da1dab | ||
|
1500691cc2 | ||
|
fae5ea749a | ||
|
c2dac55edb | ||
|
4c5a74284b | ||
|
d0a3cfe765 | ||
|
580f1f1213 | ||
|
b87d164f2f | ||
|
f3c8f342ff | ||
|
63a1d8d0db | ||
|
93f5cc1e60 | ||
|
68a503049b | ||
|
fae43010c5 | ||
|
30351f5ade | ||
|
325a5b4af4 | ||
|
021c81cb62 | ||
|
7099e09a5c | ||
|
97b990c9bf | ||
|
db3d99f7c7 | ||
|
8fb4f37670 | ||
|
dfd4115f7a | ||
|
e58ad35fb0 | ||
|
31db5078c1 | ||
|
40c78d23e6 | ||
|
ec1d6d537e | ||
|
06bfd2b502 | ||
|
fd708b28b8 | ||
|
03e3281beb | ||
|
f247b9ce20 | ||
|
67909b55fc | ||
|
43ba690eda | ||
|
3425267368 | ||
|
0c3d9af333 | ||
|
67c2b309d1 | ||
|
df0fa9883c | ||
|
9821a39549 | ||
|
692e117c8a | ||
|
d96ca61f2b | ||
|
fc58b8cc0d | ||
|
c8503daf5a | ||
|
45e1f93e56 | ||
|
77807d439e | ||
|
e062c4e6b5 | ||
|
755edd2110 | ||
|
f51124397f | ||
|
e42111545b | ||
|
5112b4b963 | ||
|
99c5c7ab28 | ||
|
edb1473f13 | ||
|
f2171173fe | ||
|
7f30863df2 | ||
|
a6a2c02b6a | ||
|
d3ee99d677 | ||
|
4abfd4053a | ||
|
05e0ed5173 | ||
|
00b480527a | ||
|
e4231efd20 | ||
|
922d2165b3 | ||
|
9cee52c668 | ||
|
50e32c3d8a | ||
|
5e576bff63 | ||
|
e1338f5a7f | ||
|
672143d3a2 | ||
|
2d94a038a5 | ||
|
174d55cf3d | ||
|
f2889d24e6 | ||
|
db58b62235 | ||
|
f3b560b453 | ||
|
43e064749c | ||
|
4af339da63 | ||
|
4cd6e7ec91 | ||
|
197b5de9da | ||
|
cdfddc0fc5 | ||
|
f4d3ec908d | ||
|
918aaa64e2 | ||
|
2417396a93 | ||
|
0a051ff2cd | ||
|
d702133ded | ||
|
2aaee311f3 | ||
|
e8d431c2f6 | ||
|
0f4c012321 | ||
|
f13a8f725c | ||
|
e6690c818d | ||
|
5d32aa94d9 | ||
|
d413b6eba8 | ||
|
f0847e6f32 | ||
|
50d7554ccd | ||
|
b28d3015fe | ||
|
75d521d42a | ||
|
1ebaacfd5e | ||
|
52cd8652bb | ||
|
c6bdf7e891 | ||
|
11e19a06b7 | ||
|
880ca35681 | ||
|
650e98b2a9 | ||
|
f84946c135 | ||
|
508969a183 | ||
|
c39e3613a8 | ||
|
4eec9a2fba | ||
|
6d1b64065a | ||
|
5751437c93 | ||
|
9fa0490c44 | ||
|
6711ceb662 | ||
|
dc7677f5fa | ||
|
78fb6f55ed | ||
|
c5981cbc9a | ||
|
2f52b6c164 | ||
|
5d59462e49 | ||
|
1b09c64856 | ||
|
24b90b475b | ||
|
2312f03eac | ||
|
1d09e4b620 | ||
|
6ea1cf71b5 | ||
|
302fe94705 | ||
|
38ea8d1d86 | ||
|
67ed7e40be | ||
|
20f211b70a | ||
|
ebb07def7e | ||
|
55ab968edf | ||
|
3f6d6745de | ||
|
d1daae1b59 | ||
|
350ea2bf28 | ||
|
2f73d24ab1 | ||
|
1a05696a84 | ||
|
fc804751a2 | ||
|
938ef930d4 | ||
|
ee21d87d1b | ||
|
b1888afa10 | ||
|
856cc7d6b8 | ||
|
d79e81a069 | ||
|
f7d9523c7d | ||
|
d93e1c84ac | ||
|
2a7ff3018b | ||
|
c83da012ff | ||
|
46e9c4299e | ||
|
e1af81ea55 | ||
|
99848ab3bb | ||
|
90d48d60d8 | ||
|
48c0efd20e | ||
|
adfc748bfa | ||
|
5cef672f9a | ||
|
015c7243b9 | ||
|
d1480d9f56 | ||
|
f3cb17ac3b | ||
|
fb2d2c5585 | ||
|
945ba5d788 | ||
|
3e7edf504d | ||
|
3285c71995 | ||
|
669e111118 | ||
|
360fda15e9 | ||
|
2018b88093 | ||
|
837b9224cc | ||
|
c22da3da1c | ||
|
470915a55b | ||
|
d9a67d64b1 | ||
|
2a26c898ca | ||
|
69fc10d5ad | ||
|
3647b74d33 | ||
|
441946b9d3 | ||
|
d376d2a590 | ||
|
9328edfdcd | ||
|
d105f324af | ||
|
23213a91ed | ||
|
184c544a24 | ||
|
6cc60ba477 | ||
|
c5578d7964 | ||
|
95cf1aafa0 | ||
|
f72a3113f5 | ||
|
3c29b46c42 | ||
|
f2397c942c | ||
|
eb2df761d5 | ||
|
1ce8ce896b | ||
|
85daf26eb1 | ||
|
286be43963 | ||
|
d951534d8f | ||
|
515f3bf111 | ||
|
3852b5ce7f | ||
|
d753ae4cf1 | ||
|
2ce1e3678a | ||
|
365d690d7d | ||
|
e75616517d | ||
|
5cb2fa5981 | ||
|
e854562803 | ||
|
fad9594b31 | ||
|
1447499776 | ||
|
4fe3b5c6a6 | ||
|
417da13353 | ||
|
69dc1b03c3 | ||
|
d7089ab471 | ||
|
039f56f390 | ||
|
d7cae1ce2a | ||
|
d7cf7316be | ||
|
b4cbb3aeb1 | ||
|
de3012ccf1 | ||
|
53a0920f20 | ||
|
5fe9021375 | ||
|
fd28550ad2 | ||
|
c0cb21a07c | ||
|
c865f17dc0 | ||
|
e23f86faa9 | ||
|
7ba1217a13 | ||
|
60ac0cef5c | ||
|
a42b236587 | ||
|
8db5d3ba5c | ||
|
d05fd9632e | ||
|
ca0bc2bb7b | ||
|
3fbb955cf2 | ||
|
04b4897dd8 | ||
|
c2bc6a04ab | ||
|
96c61fc5f2 | ||
|
1b82fb7349 | ||
|
7b28c42693 | ||
|
58ffa31e91 | ||
|
0b5bad4aa7 | ||
|
2bce61d18b | ||
|
9cebd24987 | ||
|
0d2c90cc2e | ||
|
54c88dfae9 | ||
|
d1c23477df | ||
|
8fb1356623 | ||
|
d2fec56456 | ||
|
bd2d99aced | ||
|
71308fe8c1 | ||
|
da649e397e | ||
|
1dbcfaa2c6 | ||
|
2d471e39dc | ||
|
e5dec8671e | ||
|
5fa2aa6d48 | ||
|
0edac8810b | ||
|
b085a3243c | ||
|
d256e8e9f2 | ||
|
250d286f1d | ||
|
eac9c8a7e6 | ||
|
a67213627c | ||
|
852d19f209 | ||
|
b1f091e4d7 | ||
|
8cd583fd8c | ||
|
bf190be5b4 | ||
|
092e7378cd | ||
|
2a59392ba8 | ||
|
feabaedd83 | ||
|
c9b8f404e0 | ||
|
39df2a475e | ||
|
957abf1c1b | ||
|
7c34911b1c | ||
|
7688bf3f21 | ||
|
242cb047d4 | ||
|
43fbbfe0df | ||
|
72bdca009c | ||
|
fef93af0a6 | ||
|
3e7a76cc64 | ||
|
49c4aa1a54 | ||
|
afbbc9cd72 | ||
|
05bec13bdc | ||
|
8fc321ca62 | ||
|
6590ca02de | ||
|
20fc4ee021 | ||
|
a322254f2a | ||
|
fd7b668a16 | ||
|
5786fd2221 | ||
|
419b4ecfde | ||
|
69920fb717 | ||
|
863a979754 | ||
|
8d66fbccfa | ||
|
a4caaefd32 | ||
|
e50e687191 | ||
|
c96f121d41 | ||
|
72b7b19937 | ||
|
4e3d295c90 | ||
|
3b1554db2e | ||
|
37d07a7d2a | ||
|
75fbf21e6b | ||
|
27b61b1456 | ||
|
9f4f967ead | ||
|
9763c46b7e | ||
|
f682325924 | ||
|
abe362bdd4 | ||
|
ea331b043c | ||
|
1a4a921528 | ||
|
1982fc807f | ||
|
30fd17c58d | ||
|
4ebee195cc | ||
|
98eeff7538 | ||
|
f2fdc91ad5 | ||
|
d88c25c982 | ||
|
f70fd95361 | ||
|
be3a272a80 | ||
|
631eb4b2c2 | ||
|
6a1d1867f0 | ||
|
b3b566c907 | ||
|
dd5023e494 | ||
|
18bc12c21c | ||
|
1d4dc7e27c | ||
|
0d84c77c6c | ||
|
400eb748eb | ||
|
73b30de9cb | ||
|
7a8d0a03f6 | ||
|
d140620008 | ||
|
50a1e0c618 | ||
|
ef73880459 | ||
|
98f3242e73 | ||
|
0b7365e2db | ||
|
f88dc84091 | ||
|
3099562a21 | ||
|
588d22974c | ||
|
4c2bbe3c41 | ||
|
b634c08d0e | ||
|
2d9d4dfeb3 | ||
|
d882b3274b | ||
|
1aa48ddfaa | ||
|
ad02d5589d | ||
|
0e8991fec2 | ||
|
b651604e8b | ||
|
1932e72603 | ||
|
be4eb4eeb8 | ||
|
89fa36ce2a | ||
|
80df97e734 | ||
|
8dd7fab38d | ||
|
400d5790f3 | ||
|
c8e83d6edc | ||
|
c8b8c6cb14 | ||
|
44dcbeaaa4 | ||
|
0c23843b61 | ||
|
0a34b96e11 | ||
|
f30d2b489a | ||
|
81c740178d | ||
|
36b5f6acfe | ||
|
eae88b0815 | ||
|
58c9f516b3 | ||
|
8ce4814835 | ||
|
2656aeaf9c | ||
|
bf3ea2cd47 | ||
|
07cd0c870f | ||
|
2b1e672316 | ||
|
5adb41a0ed | ||
|
98fa996b3f | ||
|
07e890a79a | ||
|
3f9e39a9e3 | ||
|
b51bcba263 | ||
|
17d004d52b | ||
|
d94e61a7b6 |
5
.openshift/README.md
Normal file
@@ -0,0 +1,5 @@
|
||||
The OpenShift `php` cartridge documentation can be found at:
|
||||
http://openshift.github.io/documentation/oo_cartridge_guide.html#php
|
||||
|
||||
For information about .openshift directory, consult the documentation:
|
||||
http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory
|
3
.openshift/action_hooks/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
For information about action hooks, consult the documentation:
|
||||
|
||||
http://openshift.github.io/documentation/oo_user_guide.html#action-hooks
|
178
.openshift/action_hooks/deploy
Executable file
@@ -0,0 +1,178 @@
|
||||
#!/bin/bash
|
||||
# This deploy hook gets executed after dependencies are resolved and the
|
||||
# build hook has been run but before the application has been started back
|
||||
# up again. This script gets executed directly, so it could be python, php,
|
||||
# ruby, etc.
|
||||
|
||||
# Bash help: http://www.panix.com/~elflord/unix/bash-tute.html
|
||||
|
||||
# For information about action hooks supported by OpenShift, consult the documentation:
|
||||
# http://openshift.github.io/documentation/oo_user_guide.html#the-openshift-directory
|
||||
|
||||
####
|
||||
|
||||
# Hubzilla specific deploy script
|
||||
|
||||
# Place this file in /.openshift/action_hooks/ (The .openshift folder will be in the root of your repo)
|
||||
# The file name should be "deploy" such that you have:
|
||||
# .openshift/action_hooks/deploy
|
||||
|
||||
# Conventions: Vars in curley braces have the slash after implied so no need to add it.
|
||||
# e.g. ${OPENSHIFT_REPO_DIR}php/foobar = /repo/php/foobar
|
||||
# See all OpenShift vars here:
|
||||
# https://www.openshift.com/developers/openshift-environment-variables
|
||||
|
||||
# HME - NOTE - leftover from original openshift-drupal-deploy
|
||||
# In config.php you can leverage the enviroment variables like this:
|
||||
# // Define env vars.
|
||||
# if (array_key_exists('OPENSHIFT_APP_NAME', $_SERVER)) {
|
||||
# $src = $_SERVER;
|
||||
# } else {
|
||||
# $src = $_ENV;
|
||||
# }
|
||||
#
|
||||
# $conf["file_private_path"] = $src['OPENSHIFT_DATA_DIR'] . "private";
|
||||
# $conf["file_temporary_path"] = $src['OPENSHIFT_DATA_DIR'] . "tmp";
|
||||
|
||||
|
||||
####
|
||||
|
||||
# Start Deploy
|
||||
|
||||
echo "Starting Deploy..."
|
||||
|
||||
# Let's create the Hubzilla files directory in the Openshift data folder ($OPENSHIFT_DATA_DIR).
|
||||
|
||||
echo "Check for the files directory called store, if not created - create it"
|
||||
|
||||
if [ ! -d ${OPENSHIFT_DATA_DIR}store ]; then
|
||||
mkdir -p ${OPENSHIFT_DATA_DIR}"store/[data]/smarty3"
|
||||
echo "Done creating files directory"
|
||||
|
||||
else
|
||||
|
||||
echo "The files directory called store already exists"
|
||||
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
# Set permissions on the files directory.
|
||||
|
||||
echo "Now chmod 777 -R files"
|
||||
|
||||
chmod -R 777 ${OPENSHIFT_DATA_DIR}store
|
||||
|
||||
echo "chmod done, permissions set to 777"
|
||||
|
||||
####
|
||||
|
||||
# Symlink our files folder to the repo.
|
||||
|
||||
# Note the "php" directory below seems to be the best way to serve OpenShift files.
|
||||
# This is good as that allows us for directories one level above such as tmp and private
|
||||
|
||||
echo "Create sym links for writeable directories"
|
||||
|
||||
ln -sf ${OPENSHIFT_DATA_DIR}store ${OPENSHIFT_REPO_DIR}store
|
||||
|
||||
echo "Files sym links created"
|
||||
|
||||
####
|
||||
|
||||
# Copy .htconfig.php from the repo, rename it and place it in the data directory.
|
||||
# if it's there already, skip it.
|
||||
|
||||
if [ ! -f ${OPENSHIFT_DATA_DIR}.htconfig.php ];
|
||||
|
||||
then
|
||||
|
||||
cp ${OPENSHIFT_REPO_DIR}.htconfig.php ${OPENSHIFT_DATA_DIR}.htconfig.php
|
||||
|
||||
echo ".htconfig.php copied."
|
||||
|
||||
else
|
||||
|
||||
echo "Looks like the .htconfig.php file is already there, we won't overwrite it."
|
||||
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
# symlink the .htconfig.php file.
|
||||
|
||||
echo "Create sym link for .htconfig.php"
|
||||
|
||||
ln -sf ${OPENSHIFT_DATA_DIR}.htconfig.php ${OPENSHIFT_REPO_DIR}.htconfig.php
|
||||
|
||||
echo ".htconfig.php symlink created"
|
||||
|
||||
####
|
||||
# Copy .htaccess from the repo, rename it and place it in the data directory.
|
||||
# if it's there already, skip it.
|
||||
|
||||
if [ ! -f ${OPENSHIFT_DATA_DIR}.htaccess ];
|
||||
|
||||
then
|
||||
|
||||
cp ${OPENSHIFT_REPO_DIR}.htaccess ${OPENSHIFT_DATA_DIR}.htaccess
|
||||
|
||||
echo ".htaccess copied."
|
||||
|
||||
else
|
||||
|
||||
echo "Looks like the .htaccess file is already there, we won't overwrite it."
|
||||
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
# symlink the .htaccess file.
|
||||
|
||||
echo "Create sym link for .htaccess"
|
||||
|
||||
ln -sf ${OPENSHIFT_DATA_DIR}.htaccess ${OPENSHIFT_REPO_DIR}.htaccess
|
||||
|
||||
echo ".htaccess symlink created"
|
||||
|
||||
####
|
||||
|
||||
echo "Check for the poller at .openshift/cron/minutely/poller , if not created - create it"
|
||||
|
||||
if [ ! -f ${OPENSHIFT_REPO_DIR}.openshift/cron/minutely/poller ]; then
|
||||
printf '%s\n' '#!/bin/bash' 'if [ ! -f $OPENSHIFT_DATA_DIR/last_run ]; then' ' touch $OPENSHIFT_DATA_DIR/last_run' 'fi' 'if [[ $(find $OPENSHIFT_DATA_DIR/last_run -mmin +9) ]]; then #run every 10 mins' ' rm -f $OPENSHIFT_DATA_DIR/last_run' ' touch $OPENSHIFT_DATA_DIR/last_run' ' # The command(s) that you want to run every 10 minutes' 'cd /var/lib/openshift/${OPENSHIFT_APP_UUID}/app-root/repo; /opt/rh/php54/root/usr/bin/php include/poller.php' 'fi' >${OPENSHIFT_REPO_DIR}.openshift/cron/minutely/poller
|
||||
echo "Done creating file .openshift/cron/minutely/poller"
|
||||
|
||||
else
|
||||
|
||||
echo "The poller already exists"
|
||||
|
||||
fi
|
||||
|
||||
####
|
||||
|
||||
# Set permissions on the poller script to make it executable.
|
||||
|
||||
echo "Now chmod 777 -R poller"
|
||||
|
||||
chmod -R 777 ${OPENSHIFT_REPO}.openshift/cron/minutely/poller
|
||||
|
||||
echo "chmod done, permissions set to 777 on poller script."
|
||||
|
||||
####
|
||||
|
||||
### echo "Check for the hot deploy marker at .openshift/markers/hot_deploy , if not created - create it"
|
||||
|
||||
### if [ ! -f ${OPENSHIFT_REPO_DIR}.openshift/markers/hot_deploy ]; then
|
||||
|
||||
### touch ${OPENSHIFT_REPO_DIR}.openshift/markers/hot_deploy
|
||||
|
||||
### echo "Done creating file .openshift/markers/hot_deploy"
|
||||
|
||||
### else
|
||||
|
||||
### echo "The hot deploy marker already exists"
|
||||
|
||||
### fi
|
||||
|
||||
####
|
27
.openshift/cron/README.cron
Normal file
@@ -0,0 +1,27 @@
|
||||
Run scripts or jobs on a periodic basis
|
||||
=======================================
|
||||
Any scripts or jobs added to the minutely, hourly, daily, weekly or monthly
|
||||
directories will be run on a scheduled basis (frequency is as indicated by the
|
||||
name of the directory) using run-parts.
|
||||
|
||||
run-parts ignores any files that are hidden or dotfiles (.*) or backup
|
||||
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved}
|
||||
|
||||
The presence of two specially named files jobs.deny and jobs.allow controls
|
||||
how run-parts executes your scripts/jobs.
|
||||
jobs.deny ===> Prevents specific scripts or jobs from being executed.
|
||||
jobs.allow ===> Only execute the named scripts or jobs (all other/non-named
|
||||
scripts that exist in this directory are ignored).
|
||||
|
||||
The principles of jobs.deny and jobs.allow are the same as those of cron.deny
|
||||
and cron.allow and are described in detail at:
|
||||
http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/ch-Automating_System_Tasks.html#s2-autotasks-cron-access
|
||||
|
||||
See: man crontab or above link for more details and see the the weekly/
|
||||
directory for an example.
|
||||
|
||||
PLEASE NOTE: The Cron cartridge must be installed in order to run the configured jobs.
|
||||
|
||||
For more information about cron, consult the documentation:
|
||||
http://openshift.github.io/documentation/oo_cartridge_guide.html#cron
|
||||
http://openshift.github.io/documentation/oo_user_guide.html#cron
|
0
.openshift/cron/daily/.gitignore
vendored
Normal file
0
.openshift/cron/hourly/.gitignore
vendored
Normal file
0
.openshift/cron/minutely/.gitignore
vendored
Normal file
0
.openshift/cron/monthly/.gitignore
vendored
Normal file
16
.openshift/cron/weekly/README
Normal file
@@ -0,0 +1,16 @@
|
||||
Run scripts or jobs on a weekly basis
|
||||
=====================================
|
||||
Any scripts or jobs added to this directory will be run on a scheduled basis
|
||||
(weekly) using run-parts.
|
||||
|
||||
run-parts ignores any files that are hidden or dotfiles (.*) or backup
|
||||
files (*~ or *,) or named *.{rpmsave,rpmorig,rpmnew,swp,cfsaved} and handles
|
||||
the files named jobs.deny and jobs.allow specially.
|
||||
|
||||
In this specific example, the chronograph script is the only script or job file
|
||||
executed on a weekly basis (due to white-listing it in jobs.allow). And the
|
||||
README and chrono.dat file are ignored either as a result of being black-listed
|
||||
in jobs.deny or because they are NOT white-listed in the jobs.allow file.
|
||||
|
||||
For more details, please see ../README.cron file.
|
||||
|
1
.openshift/cron/weekly/chrono.dat
Normal file
@@ -0,0 +1 @@
|
||||
Time And Relative D...n In Execution (Open)Shift!
|
3
.openshift/cron/weekly/chronograph
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "`date`: `cat $(dirname \"$0\")/chrono.dat`"
|
12
.openshift/cron/weekly/jobs.allow
Normal file
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Script or job files listed in here (one entry per line) will be
|
||||
# executed on a weekly-basis.
|
||||
#
|
||||
# Example: The chronograph script will be executed weekly but the README
|
||||
# and chrono.dat files in this directory will be ignored.
|
||||
#
|
||||
# The README file is actually ignored due to the entry in the
|
||||
# jobs.deny which is checked before jobs.allow (this file).
|
||||
#
|
||||
chronograph
|
||||
|
7
.openshift/cron/weekly/jobs.deny
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Any script or job files listed in here (one entry per line) will NOT be
|
||||
# executed (read as ignored by run-parts).
|
||||
#
|
||||
|
||||
README
|
||||
|
4
.openshift/markers/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
For information about markers, consult the documentation:
|
||||
|
||||
http://openshift.github.io/documentation/oo_user_guide.html#markers
|
||||
http://openshift.github.io/documentation/oo_cartridge_guide.html#php-markers
|
0
.openshift/pear.txt
Normal file
13
README.md
@@ -1,11 +1,11 @@
|
||||
|
||||
Hubzilla
|
||||
========
|
||||
Hubzilla - Community Server
|
||||
===========================
|
||||
|
||||
###Websites. Redefined.
|
||||
Help us redefine the web - using integrated and united community websites.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
**What are Hubs?**
|
||||
|
||||
@@ -37,6 +37,3 @@ Possible website applications include
|
||||
* dating websites
|
||||
* pretty much anything you can do on a traditional blog or community website, but that you could do better if you could easily connect it with other websites or privately share things across website boundaries.
|
||||
|
||||
|
||||
|
||||
This project is under development and is not yet available for general use.
|
44
boot.php
@@ -7,12 +7,12 @@
|
||||
/**
|
||||
* Hubzilla.
|
||||
*
|
||||
* The Hubzilla (aka "Red") is an open source decentralised communications
|
||||
* Hubzilla is an open source decentralised communications
|
||||
* platform combined with a decentralised identity/authentication framework
|
||||
* wrapped in an extensible content management system, providing website designers
|
||||
* the ability to embed fully decentralised communications and social tools
|
||||
* into many traditional website designs (blogs, forums, small business
|
||||
* websites, charitable organisations, etc.). Red also provides DNS mobility
|
||||
* websites, charitable organisations, etc.). Hubzilla also provides DNS mobility
|
||||
* and internet scale privacy/access control.
|
||||
*
|
||||
* This allows any individual website to participate in a matrix of linked
|
||||
@@ -43,13 +43,14 @@ require_once('include/taxonomy.php');
|
||||
require_once('include/identity.php');
|
||||
require_once('include/Contact.php');
|
||||
require_once('include/account.php');
|
||||
require_once('include/AccessList.php');
|
||||
|
||||
|
||||
define ( 'PLATFORM_NAME', 'hubzilla' );
|
||||
define ( 'RED_VERSION', trim(file_get_contents('version.inc')) . 'R');
|
||||
define ( 'RED_VERSION', trim(file_get_contents('version.inc')) . 'H');
|
||||
define ( 'ZOT_REVISION', 1 );
|
||||
|
||||
define ( 'DB_UPDATE_VERSION', 1145 );
|
||||
define ( 'DB_UPDATE_VERSION', 1156 );
|
||||
|
||||
/**
|
||||
* @brief Constant with a HTML line break.
|
||||
@@ -80,9 +81,8 @@ $DIRECTORY_FALLBACK_SERVERS = array(
|
||||
'https://zothub.com',
|
||||
'https://zotid.net',
|
||||
'https://red.zottel.red',
|
||||
'https://redmatrix.info',
|
||||
'https://my.federated.social',
|
||||
'https://redmatrix.nl'
|
||||
'https://gravizot.de',
|
||||
'https://my.federated.social'
|
||||
);
|
||||
|
||||
|
||||
@@ -333,6 +333,12 @@ define ( 'MENU_ITEM_ZID', 0x0001);
|
||||
define ( 'MENU_ITEM_NEWWIN', 0x0002);
|
||||
define ( 'MENU_ITEM_CHATROOM', 0x0004);
|
||||
|
||||
|
||||
|
||||
define ( 'SITE_TYPE_ZOT', 0);
|
||||
define ( 'SITE_TYPE_NOTZOT', 1);
|
||||
define ( 'SITE_TYPE_UNKNOWN', 2);
|
||||
|
||||
/**
|
||||
* Poll/Survey types
|
||||
*/
|
||||
@@ -717,7 +723,6 @@ class App {
|
||||
set_include_path(
|
||||
'include' . PATH_SEPARATOR
|
||||
. 'library' . PATH_SEPARATOR
|
||||
. 'library/phpsec' . PATH_SEPARATOR
|
||||
. 'library/langdet' . PATH_SEPARATOR
|
||||
. '.' );
|
||||
|
||||
@@ -801,7 +806,7 @@ class App {
|
||||
$this->is_mobile = $mobile_detect->isMobile();
|
||||
$this->is_tablet = $mobile_detect->isTablet();
|
||||
|
||||
$this->head_set_icon('/images/rm-32.png');
|
||||
$this->head_set_icon('/images/hz-32.png');
|
||||
|
||||
BaseObject::set_app($this);
|
||||
|
||||
@@ -1056,18 +1061,7 @@ class App {
|
||||
}
|
||||
|
||||
function set_template_engine($engine = 'smarty3') {
|
||||
|
||||
$this->theme['template_engine'] = $engine;
|
||||
|
||||
/*if ($engine) {
|
||||
case 'smarty3':
|
||||
if(!is_writable(TEMPLATE_BUILD_PATH))
|
||||
echo "<b>ERROR</b> folder <tt>" . TEMPLATE_BUILD_PATH . "</tt> must be writable by webserver."; killme();
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}*/
|
||||
}
|
||||
|
||||
function get_template_ldelim($engine = 'smarty3') {
|
||||
@@ -2002,6 +1996,11 @@ function load_pdl(&$a) {
|
||||
require_once('include/comanche.php');
|
||||
|
||||
if (! count($a->layout)) {
|
||||
|
||||
$arr = array('module' => $a->module, 'layout' => '');
|
||||
call_hooks('load_pdl',$arr);
|
||||
$s = $arr['layout'];
|
||||
|
||||
$n = 'mod_' . $a->module . '.pdl' ;
|
||||
$u = comanche_get_channel_id();
|
||||
if($u)
|
||||
@@ -2014,6 +2013,7 @@ function load_pdl(&$a) {
|
||||
$a->pdl = $s;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2271,7 +2271,7 @@ function cert_bad_email() {
|
||||
'$error' => t('Website SSL certificate is not valid. Please correct.')
|
||||
));
|
||||
|
||||
$subject = email_header_encode(sprintf(t('[red] Website SSL error for %s'), $a->get_hostname()));
|
||||
$subject = email_header_encode(sprintf(t('[hubzilla] Website SSL error for %s'), $a->get_hostname()));
|
||||
mail($a->config['system']['admin_email'], $subject, $email_msg,
|
||||
'From: Administrator' . '@' . $a->get_hostname() . "\n"
|
||||
. 'Content-type: text/plain; charset=UTF-8' . "\n"
|
||||
@@ -2312,7 +2312,7 @@ function check_cron_broken() {
|
||||
'$lastdate' => (($d)? $d : t('never'))
|
||||
));
|
||||
|
||||
$subject = email_header_encode(sprintf(t('[red] Cron tasks not running on %s'), $a->get_hostname()));
|
||||
$subject = email_header_encode(sprintf(t('[hubzilla] Cron tasks not running on %s'), $a->get_hostname()));
|
||||
mail($a->config['system']['admin_email'], $subject, $email_msg,
|
||||
'From: Administrator' . '@' . $a->get_hostname() . "\n"
|
||||
. 'Content-type: text/plain; charset=UTF-8' . "\n"
|
||||
|
@@ -1,25 +1,28 @@
|
||||
#Privacy Policy
|
||||
Privacy Policy
|
||||
==============
|
||||
|
||||
|
||||
##Summary##
|
||||
|
||||
##Summary
|
||||
|
||||
Q: Who can see my content?
|
||||
|
||||
A: By default ANYBODY on the internet, UNLESS you restrict it. The $Projectname allows you to choose the privacy level you desire. Restricted content will NOT be visible to spy networks and their advertisers. It will be protected against eavesdropping by outsiders - to the best of our ability. Hub administrators with sufficient skills and patience MAY be able to eavesdrop on some private communications but they must expend effort to do so. Privacy modes exist within the $Projectname which are even resistant to eavesdropping by skilled and determined hub administrators.
|
||||
A: By default ANYBODY on the internet, UNLESS you restrict it. $Projectname allows you to choose the privacy level you desire. Restricted content will NOT be visible to "spy networks" and advertisers. It will be protected against eavesdropping by outsiders - to the best of our ability. Hub administrators with sufficient skills and patience MAY be able to eavesdrop on some private communications but they must expend effort to do so. Privacy modes exist within $Projectname which are even resistant to eavesdropping by skilled and determined hub administrators.
|
||||
|
||||
Q: Can my content be censored?
|
||||
|
||||
A: The $Projectname (the network) CANNOT censor your content. Server and hub administrators are subject to local laws and MAY remove objectionable content from their site/hub. Anybody MAY become a hub administrator, including you; and therefore publish content which might otherwise be censored. You still MAY be subject to local laws.
|
||||
A: $Projectname (the network) CANNOT censor your content. Server and hub administrators are subject to local laws and MAY remove objectionable content from their site/hub. Anybody MAY become a hub administrator, including you; and therefore publish content which might otherwise be censored. You still MAY be subject to local laws.
|
||||
|
||||
|
||||
##Definitions
|
||||
|
||||
**$Projectname**
|
||||
|
||||
Otherwise referred to as "the network", the $Projectname is a collection of individual computers/servers (aka **hubs**) which connect together to form a larger cooperative network.
|
||||
Otherwise referred to as "the network", $Projectname is a collection of individual computers/servers (aka **hubs**) which connect together to form a larger cooperative network.
|
||||
|
||||
**hub**
|
||||
|
||||
An individual computer or server connected to the $Projectname. These are provided by a **hub administrator** and may be public or private, paid or free.
|
||||
An individual computer or server connected to $Projectname. These are provided by a **hub administrator** and may be public or private, paid or free.
|
||||
|
||||
**hub administrator**
|
||||
|
||||
@@ -29,7 +32,7 @@ The system operator of an individual hub.
|
||||
|
||||
**Public Information**
|
||||
|
||||
Any information or anything posted by you within the $Projectname MAY be public or visible to anybody on the internet. To the extent possible, the $Projectname allows you to protect content and restrict who can view it.
|
||||
Any information or anything posted by you within $Projectname MAY be public or visible to anybody on the internet. To the extent possible, $Projectname allows you to protect content and restrict who can view it.
|
||||
|
||||
Your profile photo, your channel name, and the location (URL or network address) of your channel are visible to anybody on the internet and privacy controls will not affect the display of these items.
|
||||
|
||||
@@ -37,7 +40,7 @@ You MAY additionally provide other profile information. Any information which yo
|
||||
|
||||
**Content**
|
||||
|
||||
Content you provide (status posts, photos, files, etc.) belongs to you. The $Projectname default is to publish content openly and visible to anybody on the internet (PUBLIC). You MAY control this in your channel settings and restrict the default permissions or you MAY restrict the visibility of any single published item separately (PRIVATE). The $Projectname developers will ensure that restricted content is ONLY visible to those in the restriction list - to the best of their ability.
|
||||
Content you provide (status posts, photos, files, etc.) belongs to you. The $Projectname default is to publish content openly and visible to anybody on the internet (PUBLIC). You MAY control this in your channel settings and restrict the default permissions or you MAY restrict the visibility of any single published item separately (PRIVATE). $Projectname developers will ensure that restricted content is ONLY visible to those in the restriction list - to the best of their ability.
|
||||
|
||||
Content (especially status posts) that you share with other networks or that you have made visible to anybody on the internet (PUBLIC) cannot easily be taken back once it has been published. It MAY be shared with other networks and made available through RSS/Atom feeds. It may also be syndicated on other $Projectname sites. It MAY appear on spy networks and internet searches. If you do not wish this default behaviour please adjust your channel settings and restrict who can see your content.
|
||||
|
||||
@@ -48,25 +51,27 @@ Comments to posts that were created by others and posts which are designated as
|
||||
|
||||
**Private Information**
|
||||
|
||||
$Projectname developers will ensure that any content you provide which is designated as PRIVATE will be protected against eavesdropping - to the best of their ability. Private content is generally hidden or obscured even from hub administrators. It is also stripped from email notifications. It is difficult but NOT impossible for this content to be seen by a hub administrator. This is a side effect of the physical laws of the universe. Unfortunately, if a database needs to decrypt a post at display time, it must have the means to decrypt the post! End to end encryption is also provided and this CANNOT be seen, even by a determined administrator.
|
||||
$Projectname developers will ensure that any content you provide which is designated as PRIVATE will be protected against eavesdropping - to the best of their ability. Private content is generally hidden or obscured even from hub administrators. It is also stripped from email notifications. It is difficult but NOT impossible for this content to be seen by a hub administrator. End to end encryption is provided as an optional feature and this CANNOT be seen, even by a determined administrator.
|
||||
|
||||
##Identity Privacy
|
||||
|
||||
Privacy for your identity is another aspect. Because you have a decentralized identity in the $Projectname, your privacy extends beyond your home hub. If you want to have complete control of your privacy and security you should run your own hub on a dedicated server. For many people, this is complicated and may stretch their technical abilities. So let's list a few precautions you can make to assure your privacy as much as possible.
|
||||
Privacy for your identity is another aspect. Because you have a decentralized identity in $Projectname, your privacy extends beyond your home hub. If you want to have complete control of your privacy and security you should run your own hub on a dedicated server. For many people, this is complicated and may stretch their technical abilities. So let's list a few precautions you can make to assure your privacy as much as possible.
|
||||
|
||||
A decentralized identity has a lot of advantages and gives you al lot of interesting features, but you should be aware of the fact that your identity is known by other hubs in the $Projectname network. One of those advantages is that other channels can serve you customized content and allow you to see private things (such as private photos which others wish to share with you). Because of this those channels need to know who you are. But we understand that sometimes those other channels know more from you than you might desire. For instance the plug-in Visage that can tell a channel owner the last time you visit their profile. You can easily OPT-OUT of this low level and we think, harmless tracking.
|
||||
|
||||
* You can enable [Do Not Track (DNT)](http://donottrack.us/) in your web browser. We respect this new privacy policy proposal. All modern browsers support DNT. You will find it in the privacy settings of your browsers or else you can consult the web browser's manual. This will not affect the functionality of the $Projectname. This setting is probably enough for most people.
|
||||
* You can enable [Do Not Track (DNT)](http://donottrack.us/) in your web browser. We respect this new privacy policy proposal. All modern browsers support DNT. You will find it in the privacy settings of your browsers or else you can consult the web browser's manual. This will not affect the functionality of $Projectname. This setting is probably enough for most people.
|
||||
|
||||
*You can [disable publication](settings) of your channel in our channel directory. If you want people to find your channel, you should give your channel address directly to them. We think this is a good indication that you prefer extra privacy and automatically enable "Do Not Track" if this is the case.
|
||||
|
||||
* You can have a blocked hub. That means that all channels and content on that hub is not public, and not visible to the outside world. This is something only your hub administrator can do. We also respect this and automatically enable "Do Not Track" if it is set.
|
||||
|
||||
###Censorship
|
||||
|
||||
The $Projectname is a global network which is inclusive of all religions and cultures. This does not imply that every member of the network feels the same way you do on contentious issues, and some people may be STRONGLY opposed to the content you post. In general, if you wish to post something that you know may nor be universally acceptable, the best approach is to restrict the audience using privacy controls to a small circle of friends.
|
||||
$Projectname is a global network which is inclusive of all religions and cultures. This does not imply that every member of the network feels the same way you do on contentious issues, and some people may be STRONGLY opposed to the content you post. In general, if you wish to post something that you know may nor be universally acceptable, the best approach is to restrict the audience using privacy controls to a small circle of friends.
|
||||
|
||||
The $Projectname as a network provider is unable to censor content. However, hub administrators MAY censor any content which appears on their hub to comply with local laws or even personal judgement. Their decision is final. If you have issues with any hub administrator, you may move your account and postings to another site which is more in line with your expectations. Please check (periodically) the [Terms of Service](help/TermsOfService) of your hub to learn about any rules or guidelines. If your content consists of material which is illegal or may cause issues, you are STRONGLY encouraged to host your own (become a hub administrator). You may still find that your content is blocked on some hubs, but the $Projectname as a network cannot block it from being posted.
|
||||
$Projectname as a network provider is unable to censor content. However, hub administrators MAY censor any content which appears on their hub to comply with local laws or even personal judgement. Their decision is final. If you have issues with any hub administrator, you may move your account and postings to another site which is more in line with your expectations. Please check (periodically) the [Terms of Service](help/TermsOfService) of your hub to learn about any rules or guidelines. If your content consists of material which is illegal or may cause issues, you are STRONGLY encouraged to host your own (become a hub administrator). You may still find that your content is blocked on some hubs, but $Projectname as a network cannot block it from being posted.
|
||||
|
||||
The $Projectname RECOMMENDS that hub administrators provide a grace period of 1-2 days between warning an account holder of content that needs to be removed and physically removing or disabling the account. This will give the content owner an opportunity to export their channel meta-data and import it to another site. In rare cases the content may be of such a nature to justify the immediate termination of the account. This is a hub decision, not a $Projectname decision.
|
||||
$Projectname RECOMMENDS that hub administrators provide a grace period of 1-2 days between warning an account holder of content that needs to be removed and physically removing or disabling the account. This will give the content owner an opportunity to export their channel meta-data and import it to another site. In rare cases the content may be of such a nature to justify the immediate termination of the account. This is a hub decision, not a $Projectname decision.
|
||||
|
||||
If you typically and regularly post content of an adult or offensive nature, you are STRONGLY encouraged to mark your account "NSFW" (Not Safe For Work). This will prevent the display of your profile photo in the directory except to viewers that have chosen to disable "safe mode". If your profile photo is found by directory administrators to be adult or offensive, the directory administrator MAY flag your profile photo as NSFW. There is currently no official mechanism to contest or reverse this decision, which is why you SHOULD mark your own account NSFW if it is likely to be inappropriate for general audiences.
|
||||
|
||||
|
@@ -99,6 +99,14 @@ Some/many of these widgets have restrictions which may restrict the type of page
|
||||
* channel_id - if not your own
|
||||
<br /> <br />
|
||||
|
||||
* tasklist - provide a task or to-do list for the currently logged-in channel.
|
||||
* args:
|
||||
* all - display completed tasks if all is non-zero.
|
||||
<br /> <br />
|
||||
|
||||
* forums - provide a list of connected public forums with unseen counts for the current logged-in channel.
|
||||
<br /> <br />
|
||||
|
||||
|
||||
Creating New Widgets
|
||||
====================
|
||||
|
14
doc/about.bb
@@ -1,8 +1,8 @@
|
||||
[b]About[/b]
|
||||
|
||||
The $Projectname is a decentralized communication network, which aims to provide communication that is censorship-resistant, privacy-respecting, and thus free from the oppressive claws of contemporary corporate communication giants. These giants function primarily as spy networks for paying clients of all sorts and types, in addition to monopolizing and centralizing the Internet; a feature that was not part of the original and revolutionary goals that produced the World Wide Web.
|
||||
$Projectname is a decentralized communication network, which aims to provide communication that is censorship-resistant, privacy-respecting, and thus free from the oppressive claws of contemporary corporate communication giants. These giants function primarily as spy networks for paying clients of all sorts and types, in addition to monopolizing and centralizing the Internet; a feature that was not part of the original and revolutionary goals that produced the World Wide Web.
|
||||
|
||||
The $Projectname is free and open source. It is designed to scale from a $35 Raspberry Pi, to top of the line AMD and Intel Xeon-powered multi-core enterprise servers. It can be used to support communication between a few individuals, or scale to many thousands and more.
|
||||
$Projectname is free and open source. It is designed to scale from a $35 Raspberry Pi, to top of the line AMD and Intel Xeon-powered multi-core enterprise servers. It can be used to support communication between a few individuals, or scale to many thousands and more.
|
||||
|
||||
Red aims to be skill and resource agnostic. It is easy to use by everyday computer users, as well as by systems administrators and developers.
|
||||
|
||||
@@ -10,15 +10,15 @@ How you use it depends on how you want to use it.
|
||||
|
||||
It is written in the PHP scripting language, thus making it trivial to install on any hosting platform in use today. This includes self-hosting at home, at hosting providers such as [url=http://mediatemple.com/]Media Temple[/url] and [url=http://www.dreamhost.com/]Dreamhost[/url], or on virtual and dedicated servers, offered by the likes of [url=https://www.linode.com]Linode[/url], [url=http://greenqloud.com]GreenQloud[/url] or [url=https://aws.amazon.com]Amazon AWS[/url].
|
||||
|
||||
In other words, the $Projectname can run on any computing platform that comes with a web server, a MySQL-compatible database, and the PHP scripting language.
|
||||
In other words, $Projectname can run on any computing platform that comes with a web server, a MySQL-compatible database, and the PHP scripting language.
|
||||
|
||||
Along the way, Red offers a number of unique goodies:
|
||||
Along the way, $Projectname offers a number of unique goodies:
|
||||
|
||||
[b]Single-click user identification:[/b] meaning you can access sites on the $Projectname simply by clicking on links to remote sites. Authentication just happens automagically behind the scenes. Forget about remembering multiple user names with multiple passwords when accessing different sites online.
|
||||
[b]Single-click user identification:[/b] meaning you can access sites on $Projectname simply by clicking on links to remote sites. Authentication just happens automagically behind the scenes. Forget about remembering multiple user names with multiple passwords when accessing different sites online.
|
||||
|
||||
[b]Cloning:[/b] of online identities. Your online presence no longer has to be tied to a single server, domain name or IP address. You can clone and import your identity (or channel as we call it) to another server (or, a hub as servers are known in the $Projectname). Now, should your primary hub go down, no worries, your contacts, posts[i]*[/i], and messages[i]*[/i] will automagically continue to be available and accessible under your cloned channel. [i](*: only posts and messages as from the moment you cloned your channel)[/i]
|
||||
[b]Cloning:[/b] of online identities. Your online presence no longer has to be tied to a single server, domain name or IP address. You can clone and import your identity (or channel as we call it) to another server (or, a hub as servers are known in $Projectname). Now, should your primary hub go down, no worries, your contacts, posts[i]*[/i], and messages[i]*[/i] will automagically continue to be available and accessible under your cloned channel. [i](*: only posts and messages as from the moment you cloned your channel)[/i]
|
||||
|
||||
[b]Privacy:[/b] Red identities (Zot IDs) can be deleted, backed up/downloaded, and cloned. The user is in full control of their data. Should you decide to delete all your content and erase your Zot ID, all you have to do is click on a link and it's immediately deleted from the hub. No questions, no fuss.
|
||||
[b]Privacy:[/b] $Projectname identities (Zot IDs) can be deleted, backed up/downloaded, and cloned. The user is in full control of their data. Should you decide to delete all your content and erase your Zot ID, all you have to do is click on a link and it's immediately deleted from the hub. No questions, no fuss.
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
|
||||
|
12
doc/admins.bb
Normal file
@@ -0,0 +1,12 @@
|
||||
[h2]Documentation for Hub Administrators[/h2]
|
||||
|
||||
[h3]Administrators[/h3]
|
||||
|
||||
[zrl=[baseurl]/help/install]Install[/zrl]
|
||||
[zrl=[baseurl]/help/red2pi]Installing $Projectname on the Raspberry Pi[/zrl]
|
||||
[zrl=[baseurl]/help/troubleshooting]Troubleshooting Tips[/zrl]
|
||||
[zrl=[baseurl]/help/hidden_configs]Tweaking $Projectname's Hidden Configurations[/zrl]
|
||||
[zrl=[baseurl]/help/faq_admins]FAQ For Admins[/zrl]
|
||||
[zrl=[baseurl]/help/service_classes]Service Classes[/zrl]
|
||||
|
||||
|
45
doc/bugs.bb
Normal file
@@ -0,0 +1,45 @@
|
||||
[h2]Bugs, Issues, and things that go bump in the night...[/h2]
|
||||
[h3]Something went wrong! Who is charge of fixing it?[/h3]
|
||||
|
||||
[b]Hubzilla Community Server[/b]
|
||||
|
||||
Hubzilla Community Server is open source software which is maintained by "the community" - essentially unpaid volunteers.
|
||||
|
||||
[b]Hubzilla Enterprise Server[/b]
|
||||
|
||||
Hubzilla Enterprise Server is commercial software with a variety of support plans depending on the specific license terms.
|
||||
|
||||
|
||||
The first thing you need to do is talk to your hub administrator - the person who runs and manages your site. They are in the unique position of having access to the internal software and database and [b]logfiles[/b] and will need to be involved in fixing your problem. Other people "on the net" can't really help with this. The first thing the hub administrator needs to do is look at their logs and/or try to reproduce the problem. So try to be as helpful and courteous as possible in helping them look into the problem.
|
||||
|
||||
To find your hub administrator (if you don't know who they are) please look at [url=[baseurl]/siteinfo]this page[/url]. If they have not provided any contact info on that page or provided an "Impressum" there, see [url=[baseurl]/siteinfo/json]this site info summary[/url] under the heading "admin:".
|
||||
|
||||
[h3]I'm a hub administrator; what do I do?[/h3]
|
||||
|
||||
The software instructions which provide this server are open source and are available for your inspection. If an error message was reported, often one can do a search on the source files for that error message and find out what triggered it. With this information and the site logfiles it may be possible to figure out the sequence of events leading to the error. There could also be other sites involved, and the problem may not even be on your site but elsewhere in the network. Try to pin down the communication endpoints (hubs or sites) involved in the problem and contact the administrator of that site or those sites. Please try and provide an event time of when things went wrong so it can be found in the logs. Work with the other administrator(s) to try and find the cause of the problem. Logfiles are your friend. When something happens in the software that we didn't expect, it is nearly always logged.
|
||||
|
||||
[h3]The white screen of death[/h3]
|
||||
|
||||
If you get a blank white screen when doing something, this is almost always a code or syntax error. There are instructions in your .htconfig.php file for enabling syntax logging. We recommend all sites use this. With syntax logging enabled repeat the sequence which led to the error and it should log the offending line of code. Hopefully you will be able to fix the problem with this information. When you do, please submit the fix "upstream" so that we can share the fix with the rest of the project members and other communities. This is a key benefit of using open source software - we share with each other and everybody benefits.
|
||||
|
||||
[h3]I'm stumped. I can't figure out what is wrong.[/h3]
|
||||
|
||||
[b]Hubzilla Enterprise Server[/b]
|
||||
|
||||
Please make contact with the vendor - who will have provided you with support contact details. Preferably this contact will be made by the hub administrator so that he/she can assist us in collecting the necessary issue details. We will assign a ticket and notify you of progress.
|
||||
|
||||
|
||||
[b]Hubzilla Community Server[/b]
|
||||
|
||||
At this point it might be worthwhile discussing the issue on one of the online forums. There may be several of these and some may be more suited to your spoken language. As a last resort, try "Channel One", which is in English.
|
||||
|
||||
If the community developers can't help you right away, understand that they are volunteers and may have a lot of other work and demands on their time. At this point you need to file a bug report. You will need an account on github.com to do this. So register, and then visit https://github.com/redmatrix/hubzilla/issues
|
||||
. Create an issue here and provide all the same information that you provided online. Don't leave out anything.
|
||||
|
||||
Then you wait. If it's a high profile issue, it may get fixed quickly. But nobody is in charge of fixing bugs. If it lingers without resolution, please spend some more time investigating the problem. Ask about anything you don't understand related to the behaviour. You will learn more about how the software works and quite possibly figure out why it isn't working now. Ultimately it is somebody in the community who is going to fix this and you are a member of the community; and this is how the open source process works.
|
||||
|
||||
|
||||
[b]In either case[/b]
|
||||
|
||||
Other developers working to fix the problem may need to find out more, so do your homework and document what is happening and everything you've tried. Don't say "I did xyz and it didn't work." That doesn't tell us anything. Tell us precisely what steps you took and what you expected the result to be, and precisely what happened as a result. If there were any error messages, don't say "there was an error message". Tell us exactly what the message said.
|
||||
|
@@ -1,5 +1,9 @@
|
||||
[b]Credits[/b]
|
||||
|
||||
Thanks to all who have helped and contributed to the project and its predecessors over the years. It is possible we missed in your name but this is unintentional. We also thank the community and its members for providing valuable input and without whom this entire effort would be meaningless.
|
||||
|
||||
It is also worth acknowledging the contributions and solutions to problems which arose from discussions amongst members and developers of other somewhat related and competing projects; even if we have had our occasional disagreements.
|
||||
|
||||
Mike Macgirvin
|
||||
Fabio Comuni
|
||||
Simon L'nu
|
||||
@@ -62,6 +66,7 @@ tonnerkiller
|
||||
Antoine G
|
||||
Christian Drechsler
|
||||
Ludovic Grossard
|
||||
RedmatrixCanada
|
||||
Stanislav Lechev [0xAF]
|
||||
aweiher
|
||||
bufalo1973
|
||||
@@ -73,3 +78,5 @@ mycocham
|
||||
ndurchx
|
||||
pafcu
|
||||
Simó Albert i Beltran
|
||||
Manuel Reva
|
||||
Manuel Jiménez Friaza
|
||||
|
@@ -1,8 +1,8 @@
|
||||
[b]Using The Cloud - Dolphin[/b]
|
||||
|
||||
Visit webdavs://example.com/cloud where "example.com" is the URL of your hub.
|
||||
Visit webdavs://example.com/dav where "example.com" is the URL of your hub.
|
||||
|
||||
When prompted for a username and password, enter your username (the first part of your webbie - no @ or domain name) and password for your normal account.
|
||||
When prompted for a username and password, enter your channel name (the first part of your webbie - no @ or domain name) and password for your normal account.
|
||||
|
||||
Note, if you are already logged in to the web interface via Konqueror, you will not be prompted for further authentication.
|
||||
|
||||
|
@@ -25,14 +25,14 @@ Edit /etc/fstab
|
||||
to include your cloud directory by adding
|
||||
|
||||
[code]
|
||||
[baseurl]/cloud/ /mount/point davfs user,noauto,uid=<DesktopUser>,file_mode=600,dir_mode=700 0 1
|
||||
[baseurl]/dav/ /mount/point davfs user,noauto,uid=<DesktopUser>,file_mode=600,dir_mode=700 0 1
|
||||
[/code]
|
||||
|
||||
Where [baseurl] is the URL of your hub, /mount/point is the location you want to mount the cloud, and <DesktopUser> is the user you log in to one your computer. Note that if you are mounting as a normal user (not root) the mount point must be in your home directory.
|
||||
|
||||
For example, if I wanted to mount my cloud to a directory called 'cloud' in my home directory, and my username was bob, my fstab would be
|
||||
|
||||
[code][baseurl]/cloud/ /home/bob/cloud davfs user,noauto,uid=bob,file_mode=600,dir_mode=700 0 1[/code]
|
||||
[code][baseurl]/dav/ /home/bob/cloud davfs user,noauto,uid=bob,file_mode=600,dir_mode=700 0 1[/code]
|
||||
|
||||
Now, create the mount point.
|
||||
|
||||
@@ -49,7 +49,7 @@ Create a file called 'secrets'
|
||||
and add your cloud login credentials
|
||||
|
||||
[code]
|
||||
[baseurl]/cloud <username> <password>
|
||||
[baseurl]/dav <username> <password>
|
||||
[/code]
|
||||
|
||||
Where <username> and <password> are the username and password [i]for your hub[/i].
|
||||
@@ -60,7 +60,7 @@ Don't let this file be writeable by anyone who doesn't need it with
|
||||
|
||||
Finally, mount the drive.
|
||||
|
||||
[code]mount [baseurl]/cloud[/code]
|
||||
[code]mount [baseurl]/dav[/code]
|
||||
|
||||
You can now find your cloud at /home/bob/cloud and use it as though it were part of your local filesystem - even if the applications you are using have no dav support themselves.
|
||||
|
||||
|
@@ -2,8 +2,8 @@
|
||||
|
||||
1. Open a File browsing window (that's Nautilus)
|
||||
2. Select File > Connect to server from the menu
|
||||
3. Type davs://<domain_name>/cloud/<your_username> and click Connect
|
||||
4. You will be prompted for your username (same as above) and password
|
||||
3. Type davs://<domain_name>/dav/<your_channelname> and click Connect
|
||||
4. You will be prompted for your channel name (same as above) and password
|
||||
5. Your personal DAV directory will be shown in the window
|
||||
|
||||
#include doc/macros/cloud_footer.bb;
|
||||
|
@@ -3,16 +3,16 @@
|
||||
For (file browser) Nemo 1.8.2 under Linux Mint 15, Cinnamon 1.8.8. Nemo ist the standard file browser there.
|
||||
|
||||
1st way
|
||||
type "davs://yourusername@friendicared.net/cloud" in the address bar
|
||||
type "davs://<domain_name>/dav/<your_channelname>" in the address bar.
|
||||
|
||||
2nd way
|
||||
Menu > file > connect to server
|
||||
Fill the dialog
|
||||
- Server: friendicared.net
|
||||
- Server: hubzilla_domain_name
|
||||
- Type: Secure WebDAV (https)
|
||||
- Folder: /cloud
|
||||
- Username: yourusername
|
||||
- Passwort: yourpasswort
|
||||
- Folder: /dav
|
||||
- Username: yourchannelname
|
||||
- Password: yourpassword
|
||||
|
||||
Once open you can set a bookmark.
|
||||
|
||||
|
@@ -4,8 +4,8 @@ RedDav using Windows 7 graphical user interface wizard:
|
||||
1. Left-click the Start-button to open the start menu.
|
||||
2. Right-click the My computer icon to access its menu.
|
||||
3. Left-click Map network drive... to open the connection dialog wizard.
|
||||
4. Type #^[url=https://example.net/cloud/your_user_name]https://example.net/cloud/your_user_name[/url] in the textbox and click the Complete button where "example.net" is the URL of your hub.
|
||||
5. Type your Red account's user name. IMPORTANT - NO at-sign or domain name.
|
||||
6. Type your Red password
|
||||
4. Type #^[url=https://example.net/dav/your_channel_name]https://example.net/dav/your_channel_name[/url] in the textbox and click the Complete button where "example.net" is the URL of your hub.
|
||||
5. Type your Hubzilla account's user name. IMPORTANT - NO at-sign or domain name.
|
||||
6. Type your Hubzilla password
|
||||
|
||||
#include doc/macros/cloud_footer.bb;
|
||||
|
34
doc/develop.bb
Normal file
@@ -0,0 +1,34 @@
|
||||
[h2]Documentation for Developers[/h2]
|
||||
|
||||
[h3]Technical Documentation[/h3]
|
||||
[zrl=[baseurl]/help/Zot---A-High-Level-Overview]A high level overview of Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot]An introduction to Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot_structures]Zot Stuctures[/zrl]
|
||||
[zrl=[baseurl]/help/comanche]Comanche Page Descriptions[/zrl]
|
||||
[zrl=[baseurl]/help/Creating-Templates]Creating Comanche Templates[/zrl]
|
||||
[zrl=[baseurl]/help/Widgets]Widgets[/zrl]
|
||||
[zrl=[baseurl]/help/plugins]Plugins[/zrl]
|
||||
[zrl=[baseurl]/help/doco]Contributing Documentation[/zrl]
|
||||
[zrl=[baseurl]/help/DerivedTheme1]Creating Derivative Themes[/zrl]
|
||||
[zrl=[baseurl]/help/schema_development]Schemas[/zrl]
|
||||
[zrl=[baseurl]/help/Translations]Translations[/zrl]
|
||||
[zrl=[baseurl]/help/developers]Developers[/zrl]
|
||||
[zrl=[baseurl]/help/intro_for_developers]Intro for Developers[/zrl]
|
||||
[zrl=[baseurl]/help/database]Database schema documantation[/zrl]
|
||||
[zrl=[baseurl]/help/api_functions]API functions[/zrl]
|
||||
[zrl=[baseurl]/help/api_posting]Posting to the red# using the API[/zrl]
|
||||
[zrl=[baseurl]/help/developer_function_primer]Red Functions 101[/zrl]
|
||||
[zrl=[baseurl]/doc/html/]Code Reference (Doxygen generated - sets cookies)[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_doco]To-Do list for the Red Documentation Project[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_code]To-Do list for Developers[/zrl]
|
||||
[zrl=[baseurl]/help/roadmap]Version 3 roadmap[/zrl]
|
||||
[zrl=[baseurl]/help/git_for_non_developers]Git for Non-Developers[/zrl]
|
||||
[zrl=[baseurl]/help/dev_beginner]Step-for-step manual for beginning developers[/zrl]
|
||||
|
||||
[h3]Frequently Asked Questions For Developers[/h3]
|
||||
[zrl=[baseurl]/help/faq_developers]FAQ For Developers[/zrl]
|
||||
|
||||
[h3]External Resources[/h3]
|
||||
|
||||
[url=https://zothub.com/channel/one]Development Channel[/url]
|
||||
[url=https://federated.social/channel/postgres]Postgres-specific $Projectname Admin Support Channel[/url]
|
@@ -8,14 +8,14 @@ $Projectname provides distributed web publishing and social communications with
|
||||
|
||||
So what exactly are "decentralised permissions"? They give me the ability to share something on my website (photos, media, files, webpages, etc.) with specific people on completely different websites - but not necessarily [i]everybody[/i] on those websites; and they do not need a password on my website and do not need to login to my website to view the things I've shared with them. They have one password on their own website and "magic authentication" between affiliated websites in the network. Also, as it is decentralised, there is no third party which has the ability to bypass permissions and see everything in the network.
|
||||
|
||||
$Projectname combines many features of traditional blogs, social networking and media, content management systems, and personal cloud storage into an easy to use framework. Each node in the matrix can operate standalone or link with other nodes to create a super-network; leaving privacy under the control of the original publisher.
|
||||
$Projectname combines many features of traditional blogs, social networking and media, content management systems, and personal cloud storage into an easy to use framework. Each node in the grid can operate standalone or link with other nodes to create a super-network; leaving privacy under the control of the original publisher.
|
||||
|
||||
$Projectname is an open source webserver application written originally in PHP/MySQL and is easily installable by those with basic website administration skills. It is also easily extended via plugins and themes and other third-party tools.
|
||||
|
||||
[b][size=24]$Projectname Features[/size][/b]
|
||||
|
||||
|
||||
The $Projectname is a general-purpose web publishing and communication network, with several unique features. It is designed to be used by the widest range of people on the web, from non-technical bloggers, to expert PHP programmers and seasoned systems administrators.
|
||||
$Projectname is a general-purpose web publishing and communication network, with several unique features. It is designed to be used by the widest range of people on the web, from non-technical bloggers, to expert PHP programmers and seasoned systems administrators.
|
||||
|
||||
This page lists some of the core features of $Projectname that are bundled with the official release. As with most free and open source software, there may be many other extensions, additions, plugins, themes and configurations that are limited only by the needs and imagination of the members.
|
||||
|
||||
@@ -29,10 +29,14 @@ When adding connnections in $Projectname, members have the option of assigning "
|
||||
|
||||
On the other hand, when adding a friend's channel, they could be placed under the affinity level of "Friends".
|
||||
|
||||
At this point, the $Projectname [i]Affinity Slider[/i] tool, which usually appears at the top of your "Matrix" page, adjusts the content on the page to include those within the desired affinity range. Channels outside that range will not be displayed, unless you adjust the slider to include them.
|
||||
At this point, $Projectname [i]Affinity Slider[/i] tool, which usually appears at the top of your "Matrix" page, adjusts the content on the page to include those within the desired affinity range. Channels outside that range will not be displayed, unless you adjust the slider to include them.
|
||||
|
||||
The Affinity Slider allows instantaneous filtering of large amounts of content, grouped by levels of closeness.
|
||||
|
||||
[b]Connection Filtering[/b]
|
||||
|
||||
You have the ability to control precisely what appears in your stream using the optional "Connection Filter". When enabled, the Connection Editor provides inputs for selecting criteria which needs to be matched in order to include or exclude a specific post from a specific channel. Once a post has been allowed, all comments to that post are allowed regardless of whether they match the selection criteria. You may select words that if present block the post or ensure it is included in your stream. Regular expressions may be used for even finer control, as well as hashtags or even the detected language of the post.
|
||||
|
||||
[b]Access Control Lists[/b]
|
||||
|
||||
When sharing content, members have the option of restricting who sees the content. By clicking on the padlock underneath the sharing box, one may choose desired recipients of the post, by clicking on their names.
|
||||
@@ -43,7 +47,7 @@ Access Control Lists may be applied to content and posts, photos, events, webpag
|
||||
|
||||
[b]Single Sign-on[/b]
|
||||
|
||||
Access Control Lists work for all channels in the matrix due to our unique single sign-on technology. Most internal links provide an identity token which can be verified on other $Projectname sites and used to control access to private resources. You login once to your home hub. After that, authentication to all $Projectname resources is "magic".
|
||||
Access Control Lists work for all channels in the grid due to our unique single sign-on technology. Most internal links provide an identity token which can be verified on other $Projectname sites and used to control access to private resources. You login once to your home hub. After that, authentication to all $Projectname resources is "magic".
|
||||
|
||||
|
||||
[b]WebDAV enabled File Storage[/b]
|
||||
@@ -56,7 +60,7 @@ Store photos in albums. All your photos may be protected by Access Control Lists
|
||||
|
||||
[b]Events Calendar[/b]
|
||||
|
||||
Create and manage events, which may also be protected with Access Control Lists. Events can be exported to other software using the industry standard vcalendar/iCal format and shared in posts with others. Birthday events are automatically added from your friends and converted to your correct timezone so that you will know precisely when the birthday occurs - no matter where you are located in the world in relation to the birthday person. Events are normally created with attendance counters so your friends and connections can RSVP instantly.
|
||||
Create and manage events and tasks, which may also be protected with Access Control Lists. Events can be imported/exported to other software using the industry standard vcalendar/iCal format and shared in posts with others. Birthday events are automatically added from your friends and converted to your correct timezone so that you will know precisely when the birthday occurs - no matter where you are located in the world in relation to the birthday person. Events are normally created with attendance counters so your friends and connections can RSVP instantly.
|
||||
|
||||
[b]Chatrooms[/b]
|
||||
|
||||
@@ -85,7 +89,7 @@ Messages marked [b]private[/b] are encrypted with AES-CBC 256-bit symmetric ciph
|
||||
|
||||
These private messages are also stored in an encrypted form on remote systems.
|
||||
|
||||
Each Red channel has it's own unique set of private and associated public RSA 4096-bit keys, generated when the channels is first created.
|
||||
Each$Projectname channel has it's own unique set of private and associated public RSA 4096-bit keys, generated when the channels is first created.
|
||||
|
||||
Additionally, messages may be created utilising "end-to-end encryption" which cannot be read by $Projectname operators or ISPs or anybody who does not know the passcode.
|
||||
|
||||
@@ -142,9 +146,9 @@ Forums are typically channels which may be open to participation from multiple a
|
||||
|
||||
[b]Account Cloning[/b]
|
||||
|
||||
Accounts in the $Projectname are referred to as [i]nomadic identities[/i], because a member's identity is not bound to the hub where the identity was originally created. For example, when you create a Facebook or Gmail account, it is tied to those services. They cannot function without Facebook.com or Gmail.com.
|
||||
Accounts in $Projectname are referred to as [i]nomadic identities[/i], because a member's identity is not bound to the hub where the identity was originally created. For example, when you create a Facebook or Gmail account, it is tied to those services. They cannot function without Facebook.com or Gmail.com.
|
||||
|
||||
By contrast, say you've created a Red identity called [b]tina@redhub.com[/b]. You can clone it to another Red hub by choosing the same, or a different name: [b]liveForever@Some$ProjectnameHub.info[/b]
|
||||
By contrast, say you've created a$Projectname identity called [b]tina@redhub.com[/b]. You can clone it to another$Projectname hub by choosing the same, or a different name: [b]liveForever@Some$ProjectnameHub.info[/b]
|
||||
|
||||
Both channels are now synchronized, which means all your contacts and preferences will be duplicated on your clone. It doesn't matter whether you send a post from your original hub, or the new hub. Posts will be mirrored on both accounts.
|
||||
|
||||
@@ -152,9 +156,9 @@ This is a rather revolutionary feature, if we consider some scenarios:
|
||||
|
||||
- What happens if the hub where an identity is based suddenly goes offline? Without cloning, a member will not be able to communicate until that hub comes back online (no doubt many of you have seen and cursed the Twitter "Fail Whale"). With cloning, you just log into your cloned account, and life goes on happily ever after.
|
||||
|
||||
- The administrator of your hub can no longer afford to pay for his free and public $Projectname hub. He announces that the hub will be shutting down in two weeks. This gives you ample time to clone your identity(ies) and preserve your Red relationships, friends and content.
|
||||
- The administrator of your hub can no longer afford to pay for his free and public $Projectname hub. He announces that the hub will be shutting down in two weeks. This gives you ample time to clone your identity(ies) and preserve your$Projectname relationships, friends and content.
|
||||
|
||||
- What if your identity is subject to government censorship? Your hub provider may be compelled to delete your account, along with any identities and associated data. With cloning, the $Projectname offers [b]censorship resistance[/b]. You can have hundreds of clones, if you wanted to, all named different, and existing on many different hubs, strewn around the internet.
|
||||
- What if your identity is subject to government censorship? Your hub provider may be compelled to delete your account, along with any identities and associated data. With cloning, $Projectname offers [b]censorship resistance[/b]. You can have hundreds of clones, if you wanted to, all named different, and existing on many different hubs, strewn around the internet.
|
||||
|
||||
Red offers interesting new possibilities for privacy. You can read more at the <<Private Communications Best Practices>> page.
|
||||
|
||||
@@ -172,7 +176,7 @@ Backups can then be used to clone or restore a profile.
|
||||
|
||||
[b]Account Deletion[/b]
|
||||
|
||||
Accounts can be immediately deleted by clicking on a link. That's it. All associated content is then deleted from the matrix (this includes posts and any other content produced by the deleted profile). Depending on the number of connections you have, the process of deleting remote content could take some time but it is scheduled to happen as quickly as is practical.
|
||||
Accounts can be immediately deleted by clicking on a link. That's it. All associated content is then deleted from the grid (this includes posts and any other content produced by the deleted profile). Depending on the number of connections you have, the process of deleting remote content could take some time but it is scheduled to happen as quickly as is practical.
|
||||
|
||||
[b][size=20]Content Creation[/size][/b]
|
||||
|
||||
@@ -183,10 +187,10 @@ Red supports a number of different ways of adding rich-text content. The default
|
||||
When creating "Websites", content may be entered in HTML, Markdown, BBcode, and/or plain text.
|
||||
|
||||
[b]Deletion of content[/b]
|
||||
Any content created in the $Projectname remains under the control of the member (or channel) that originally created it. At any time, a member can delete a message, or a range of messages. The deletion process ensures that the content is deleted, regardless of whether it was posted on a channel's primary (home) hub, or on another hub, where the channel was remotely authenticated via Zot (the $Projectname communication and authentication protocol).
|
||||
Any content created in $Projectname remains under the control of the member (or channel) that originally created it. At any time, a member can delete a message, or a range of messages. The deletion process ensures that the content is deleted, regardless of whether it was posted on a channel's primary (home) hub, or on another hub, where the channel was remotely authenticated via Zot ($Projectname communication and authentication protocol).
|
||||
|
||||
[b]Media[/b]
|
||||
Similar to any other modern blogging system, social network, or a micro-blogging service, Red supports the uploading of files, embedding of videos, linking web pages.
|
||||
Similar to any other modern blogging system, social network, or a micro-blogging service, $Projectname supports the uploading of files, embedding of videos, linking web pages.
|
||||
|
||||
[b]Previewing/Editing[/b]
|
||||
Post can be previewed prior to sending and edited after sending.
|
||||
|
20
doc/general.bb
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
[h2]Project/Site Information[/h2]
|
||||
|
||||
[zrl=[baseurl]/help/Privacy]Privacy Policy[/zrl]
|
||||
|
||||
[zrl=[baseurl]/help/history]$Projectname history[/zrl]
|
||||
|
||||
[h3]External Resources[/h3]
|
||||
[zrl=[baseurl]/help/external-resource-links]External Resource Links[/zrl]
|
||||
|
||||
[url=https://github.com/redmatrix/hubzilla]Main Website[/url]
|
||||
[url=https://github.com/redmatrix/hubzilla-addons]Addon Website[/url]
|
||||
|
||||
[url=[baseurl]/help/credits]$Projectname Credits[/url]
|
||||
|
||||
[h3]About This $Projectname Hub[/h3]
|
||||
[zrl=[baseurl]/help/TermsOfService]Terms of Service For This Hub[/zrl]
|
||||
[zrl=[baseurl]/siteinfo]Hub Information (/siteinfo)[/zrl]
|
||||
[zrl=[baseurl]/siteinfo/json]Detailed Technical Hub Information in JSON format(/siteinfo/json)[/zrl]
|
||||
|
@@ -1,7 +1,7 @@
|
||||
$Projectname History
|
||||
====================
|
||||
Hubzilla History
|
||||
================
|
||||
|
||||
$Projectname is a collaborative effort by the $Projectname community and based on work introduced in Friendica by the Friendica community. The core design, the project mission, and software base itself were created/written primarily by Mike Macgirvin and represent the culmination of over a decade of software design using variations of this platform and an evolving vision of the role of communication software in our lives. Many others have contributed to this work, both conceptually and in terms of actual code (way too many to list individually).
|
||||
Hubzilla is a community developed open source project based on work introduced in Friendica by the Friendica community and which previously was named Redmatrix. The core design, the project mission, and software base itself were created/written primarily by Mike Macgirvin and represent the culmination of over a decade of software design using variations of this platform and an evolving vision of the role of communication software in our lives. Many others have contributed to this work, both conceptually and in terms of actual code (far too many to list individually).
|
||||
|
||||
##Mike Macgirvin -- Biography
|
||||
|
||||
@@ -10,9 +10,9 @@ Mike Macgirvin is an American software engineer now living in Australia. He spen
|
||||
During a layoff round, Mike was let go from America Online in August 2001 and purchased a music store in Mountain View, California later to be known as "Sonica Music Company". Opening a retail store for non-essential goods at the beginning of a prolonged economic downturn was in retrospect probably not the wisest career move. Sonica eventually folded; in late 2006. Mike returned to working on software and systems support full-time and was employed briefly at Symantec before moving to Australia in early 2007. He currently lives on a farm "out in the middle of nowhere" and is employed as a Computer Systems Officer at the University of Wollongong.
|
||||
|
||||
|
||||
##$Projectname - The Early Years
|
||||
##Hubzilla - The Early Years
|
||||
|
||||
The software which went into creating $Projectname has been through three distinct historical phases. It began in 2003 when Mike Macgirvin was looking for a content management system to power the website for his music store and found the available solutions to be lacking in various respects. The project was born as the "PurpleHaze weblog" under the nom de plume "Nerdware Communications". It was a multi-user PHP/MySQL CMS which provided blogs, forums, photo albums, events and more. Initially it provided the basis for a social community and shopping for customers of the store, but was also linked to Mike's personal weblog running on another domain. The distinguishing characteristic of this software was the ability for so-called "normal users" to re-assemble the components and choose different content feeds - and in essence create their own personal "multi-user CMS" as a view. Their custom view was able to communicate with anybody else that used the system, but could be partitioned so that adult sites and motorcycle enthusiast sites would not be visible to each other and not clash (or in this case Mike's personal website and the music store website). This software was developed primarily from 2003 until 2008.
|
||||
The software which went into creating Hubzilla has been through several distinct historical phases. It began in 2003 when Mike Macgirvin was looking for a content management system to power the website for his music store and found the available solutions to be lacking in various respects. The project was born as the "PurpleHaze weblog" under the nom de plume "Nerdware Communications". It was a multi-user PHP/MySQL CMS which provided blogs, forums, photo albums, events and more. Initially it provided the basis for a social community and shopping for customers of the store, but was also linked to Mike's personal weblog running on another domain. The distinguishing characteristic of this software was the ability for so-called "normal users" to re-assemble the components and choose different content feeds - and in essence create their own personal "multi-user CMS" as a view. Their custom view was able to communicate with anybody else that used the system, but could be partitioned so that adult sites and motorcycle enthusiast sites would not be visible to each other and not clash (or in this case Mike's personal website and the music store website). This software was developed primarily from 2003 until 2008.
|
||||
|
||||
In 2006 this software was used as the prototype for Symantec's "safeweb" reputation and community site. It was developed and enhanced until about 2008. A rewrite took place in 2008 named "Reflection" but work stagnated as the community dwindled. The need for content management systems and communications software dropped dramatically during this time as humans flocked to the new social aggregrators - Facebook and Twitter.
|
||||
|
||||
@@ -32,19 +32,25 @@ Mike realised he did not want to be held hostage to the decisions that other pro
|
||||
Mike had been working on this project for some time and there were a number of things which needed re-writing, including the base communication protocol which Friendica used (DFRN or the "Distributed Friends and Relations Network" protocol). These ideas were starting to emerge as a different method of communication he called "zot". Zot began as a way to create a common language for federated websites, but there was no interest in this ability and as mentioned, the federated web was crumbling. The first version was soon scrapped and zot was re-designed and re-ignited as a streamlined communication protocol which was location-independent; e.g. not tied to any website. This would allow people to carry on unaffected if their website operator shut down temporarily or permanently. They wouldn't have to make friends all over again, and permissions of everything on the system wouldn't have to be changed to allow bob@site1 to see something that was private to him, even though he was now bob@site2. This was a serious problem with decentralisation. People moved and their online identities were lost and had to be re-created from scratch and existing relationships destroyed and had to be created all over again.
|
||||
|
||||
|
||||
##$Projectname
|
||||
##Redmatrix
|
||||
|
||||
In July 2012, Mike left the Friendica project and began development of "zot" and a new base project called "red" in his somewhat elusive *spare time*. Red is Spanish for "network". It wasn't really a "social network" and especially not a "federated social network". It was just Red (technically "la red"), or "the network". Work began by removing all the "federation" components and going back to basics - communication and remote authentication. It was a major re-write and took roughly six months before even basic communication was re-established. It was also no longer compatible with Friendica - which had been given to the "Friendica community" and by this time (December 2012) was developing separately on its own track.
|
||||
|
||||
It became clear during this time that the single most compelling feature of the project wasn't the social network at all, but the authentication layer and decentralised access control mechanisms. Combined with zot's location independence it created a new model for software which had never existed previously - decentralised identity-aware web publishing and single sign-on to any compatible provider across the web. These weren't *evolutionary*, they were **revolutionary**. One of the biggest flaws of the modern web is the reliance on different passwords for every service you use, or reliance on a single provider if you were to tie them to - say your Facebook login. Facebook can remove your account at any time. Gone. If you rely on their authentication for all your websites, your entire online identity - now gone. This is also what was missing from Friendica - a compelling software feature which could stand on its own, without requiring a social network and especially without requiring a federated social network with all the mentioned external dependencies.
|
||||
|
||||
An early visitor to the project noted that he had some difficulty finding the project on Google because of the choice of name - "red". Yes, this was a poor decision in retrospect. We were buried on page 23,712 of the search results. The concept that was emerging around this identity-aware publishing was that of "a matrix of inter-connected thought streams", since we didn't have a concept of "people" and "friends". All were just connected "channels" with different ways to connect. So "$Projectname" was chosen to give it a searchable name. It had nothing to do with the Matrix film and red and blue pills, though that is frequently cited (erronously); and in fact isn't a bad analogy.
|
||||
An early visitor to the project noted that he had some difficulty finding the project on Google because of the choice of name - "red". Yes, this was a poor decision in retrospect. We were buried on page 23,712 of the search results. The concept that was emerging around this identity-aware publishing was that of "a matrix of inter-connected thought streams", since we didn't have a concept of "people" and "friends". All were just connected "channels" with different ways to connect. So "Redmatrix" was chosen to give it a searchable name. It had nothing to do with the Matrix film and red and blue pills, though that is frequently cited (erronously); and in fact isn't a bad analogy.
|
||||
|
||||
The concept of identity-aware content was alien to anything that existed previously on the web, so to make it useful we had to provide the ability to use it for content. It needed content publishing tools. This brought back concepts from the old "Content Management System" on which the software was originally based. To get it up and running quickly we created a markup language for webpages called "Comanche" which let you describe a page in high-level terms based on bbcode tags. We also added WebDAV so you could put decentralised access control on files and drag/drop from your operating system. So now you could have private photos, webpages, files, events, conversations, chatrooms - and they are visible to those you choose - no matter what site they use. All they need is zot. And your viewers could move to another site or just pop up at a different site any time they want and we don't care. And it **also** had a built-in social network; with lots of additional privacy and encryption features which were added even before the Snowden revelations gave them added urgency.
|
||||
|
||||
Over time a few federation components re-emerged. The ability to view RSS feeds was important to many people. Diaspora never really managed to re-write their protocol, so that was re-implemented and allowed $Projectname to connect with Diaspora and Friendica again (Friendica still had their Diaspora protocol intact, so this was the most common language now remaining on the free web - despite its faults). Diaspora communications aren't able to make use of the advanced identity features, but they work for basic communications.
|
||||
Over time a few federation components re-emerged. The ability to view RSS feeds was important to many people. Diaspora never really managed to re-write their protocol, so that was re-implemented and allowed Redmatrix to connect with Diaspora and Friendica again (Friendica still had their Diaspora protocol intact, so this was the most common language now remaining on the free web - despite its faults). Diaspora communications aren't able to make use of the advanced identity features, but they work for basic communications.
|
||||
|
||||
|
||||
Mike resigned from the project as an active coordinator in early 2015.
|
||||
##Hubzilla
|
||||
|
||||
The Redmatrix project reached a point of stagnation in early 2015 as network growth leveled and active interest in the project declined. Mike met with several external high tech developers and innovators in a round of discussions that were called "Zotopia" in early 2015 to perform an independent review of the project and try to identify what had gone wrong and plan a route forward. The basic consensus is that the project suffered from bad marketing decisions which were compounded by mixed messages about the project goals and target audience. A "rival" project (Diaspora) was marketing itself as a Facebook competitor, but after some long discussions it was determined that Redmatrix wasn't a Facebook competitor at all, and too much emphasis was being placed on the "social network" and "anti-Facebook" features. It was a novel decentralisation platform with distributed identity and permissions, and as was pointed out, the "end user" was the wrong target market. These marketing mistakes were now identified with the project name and random sampling of various "customers" showed that none of them really had a clue about the software goals or target market segment. The mixed messages were associated with the brand identity and this was a problem.
|
||||
|
||||
The Redmatrix community held a vote and the project was renamed "Hubzilla", with a renewed identity and focus - to provide software for creating and ultimately linking together unrelated community websites or "hubs" into a global community. This is in fact what we were building all along, but didn't fully recognise it. The target audience for this software as it turns out is not the members or end users, but software integrators and digital community architects and builders. These in turn will be responsible for marketing their own product (their respective online communities) to end-users or members. The software solves a real world need of linking isolated and "walled garden" community sites together into a larger cooperative. The transition from Redmatrix to Hubzilla was complex and has taken several months as we consolidated the marketing and media assets to deliver a consistent message. It is still ongoing at this time, and should be completed in Q4 2015.
|
||||
|
||||
Mike stepped down as active coordinator for the project in early 2015 and turned management over to the community. He remains active as a Hubzilla developer.
|
||||
|
||||
#include doc/macros/main_footer.bb;
|
||||
|
81
doc/main.bb
@@ -1,86 +1,13 @@
|
||||
|
||||
[zrl=[baseurl]/help/about][b]What is the $Projectname?[/b][/zrl]
|
||||
[zrl=[baseurl]/help/about][b]What is $Projectname?[/b][/zrl]
|
||||
$Projectname is a decentralized communication and publishing platform that enables you to keep in control of your communication needs by automatic encryption and finely grained access control. It's you, and only you who decides who is allowed to see your stuff.
|
||||
|
||||
[zrl=[baseurl]/help/features][b]$Projectname Features[/b][/zrl]
|
||||
|
||||
The $Projectname is already running as a global distributed network and proves its versatility and scalability from standalone to huge sites on a daily basis.
|
||||
Think of standalone family communication platforms, distributed online communities, support forums, blogs and homepages. Or professional content providers with commercial premium channels and targeted content acces. Whatever you want, the $Projectname is there to cater to your creativity.
|
||||
$Projectname is already running as a global distributed network and proves its versatility and scalability from standalone to huge sites on a daily basis.
|
||||
Think of standalone family communication platforms, distributed online communities, support forums, blogs and homepages. Or professional content providers with commercial premium channels and targeted content acces. Whatever you want, $Projectname is there to cater to your creativity.
|
||||
|
||||
[zrl=[baseurl]/help/what_is_zot][b]Got Zot? Well, you should.[/b][/zrl]
|
||||
Zot is the great new communicaton protocol invented especially for the $Projectname. As a member you are no longer bound to a single site or hub thanks to "Nomadic Identities". Migrate easily to another server and keep your contacts intact, or clone it and run the same channel on several servers. Just in case one of them might shut down, you don't lose out. Plus once you are inside the $Projectname there is no need for you to authenticate twice, even when accessing another $Projectname site. Zot is what sets the $Projectname apart.
|
||||
Zot is the great new communicaton protocol invented especially for $Projectname. As a member you are no longer bound to a single site or hub thanks to "Nomadic Identities". Migrate easily to another server and keep your contacts intact, or clone it and run the same channel on several servers. Just in case one of them might shut down, you don't lose out. Plus once you are inside $Projectname there is no need for you to authenticate twice, even when accessing another $Projectname site. Zot is what sets $Projectname apart.
|
||||
|
||||
[h3]Getting Started[/h3]
|
||||
[zrl=[baseurl]/help/Privacy]Privacy Policy[/zrl]
|
||||
[zrl=[baseurl]/help/registration]Account Registration[/zrl]
|
||||
[zrl=[baseurl]/help/accounts_profiles_channels_basics]You at the $Projectname: accounts, profiles and channels in short[/zrl]
|
||||
[zrl=[baseurl]/help/profiles]Profiles[/zrl]
|
||||
[zrl=[baseurl]/help/channels]Channels[/zrl]
|
||||
[zrl=[baseurl]/help/roles]Permission roles and Channel types[/zrl]
|
||||
[zrl=[baseurl]/help/first-post]Your first posting[/zrl]
|
||||
[zrl=[baseurl]/help/connecting_to_channels]Connecting To Other Channels[/zrl]
|
||||
[zrl=[baseurl]/help/permissions]Permissions And Encryption: You Are In Control[/zrl]
|
||||
[zrl=[baseurl]/help/cloud]Cloud Storage[/zrl]
|
||||
[zrl=[baseurl]/help/remove_account]Remove Channel or Account[/zrl]
|
||||
|
||||
[h3]Members Help[/h3]
|
||||
[zrl=[baseurl]/help/tags_and_mentions]Tags and Mentions[/zrl]
|
||||
[zrl=[baseurl]/help/webpages]Web Pages[/zrl]
|
||||
[zrl=[baseurl]/help/bbcode]BBcode reference for posts and comments[/zrl]
|
||||
[zrl=[baseurl]/help/checking_account_quota_usage]Checking Account Quota Usage[/zrl]
|
||||
[zrl=[baseurl]/help/cloud_desktop_clients]Cloud Desktop Clients[/zrl]
|
||||
[zrl=[baseurl]/help/AdvancedSearch]Advanced Directory Search[/zrl]
|
||||
[zrl=[baseurl]/help/addons]Help With Addons[/zrl]
|
||||
[zrl=[baseurl]/help/diaspora_compat]Diaspora Communications Compatibility (Diaspora and Friendica)[/zrl]
|
||||
[zrl=[baseurl]/help/faq_members]FAQ For Members[/zrl]
|
||||
|
||||
[h3]Administrators Help[/h3]
|
||||
[zrl=[baseurl]/help/install]Install[/zrl]
|
||||
[zrl=[baseurl]/help/red2pi]Installing Red on the Raspberry Pi[/zrl]
|
||||
[zrl=[baseurl]/help/troubleshooting]Troubleshooting Tips[/zrl]
|
||||
[zrl=[baseurl]/help/hidden_configs]Tweaking $Projectname's Hidden Configurations[/zrl]
|
||||
[zrl=[baseurl]/help/faq_admins]FAQ For Admins[/zrl]
|
||||
[zrl=[baseurl]/help/service_classes]Service Classes[/zrl]
|
||||
|
||||
[h3]Technical Documentation[/h3]
|
||||
[zrl=[baseurl]/help/history]$Projectname history[/zrl]
|
||||
[zrl=[baseurl]/help/Zot---A-High-Level-Overview]A high level overview of Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot]An introduction to Zot[/zrl]
|
||||
[zrl=[baseurl]/help/zot_structures]Zot Stuctures[/zrl]
|
||||
[zrl=[baseurl]/help/comanche]Comanche Page Descriptions[/zrl]
|
||||
[zrl=[baseurl]/help/Creating-Templates]Creating Comanche Templates[/zrl]
|
||||
[zrl=[baseurl]/help/Widgets]Widgets[/zrl]
|
||||
[zrl=[baseurl]/help/plugins]Plugins[/zrl]
|
||||
[zrl=[baseurl]/help/doco]Contributing Documentation[/zrl]
|
||||
[zrl=[baseurl]/help/DerivedTheme1]Creating Derivative Themes[/zrl]
|
||||
[zrl=[baseurl]/help/schema_development]Schemas[/zrl]
|
||||
[zrl=[baseurl]/help/Translations]Translations[/zrl]
|
||||
[zrl=[baseurl]/help/developers]Developers[/zrl]
|
||||
[zrl=[baseurl]/help/intro_for_developers]Intro for Developers[/zrl]
|
||||
[zrl=[baseurl]/help/database]Database schema documantation[/zrl]
|
||||
[zrl=[baseurl]/help/api_functions]API functions[/zrl]
|
||||
[zrl=[baseurl]/help/api_posting]Posting to the red# using the API[/zrl]
|
||||
[zrl=[baseurl]/help/developer_function_primer]Red Functions 101[/zrl]
|
||||
[zrl=[baseurl]/doc/html/]Code Reference (Doxygen generated - sets cookies)[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_doco]To-Do list for the Red Documentation Project[/zrl]
|
||||
[zrl=[baseurl]/help/to_do_code]To-Do list for Developers[/zrl]
|
||||
[zrl=[baseurl]/help/roadmap]Version 3 roadmap[/zrl]
|
||||
[zrl=[baseurl]/help/git_for_non_developers]Git for Non-Developers[/zrl]
|
||||
[zrl=[baseurl]/help/dev_beginner]Step-for-step manual for beginning developers[/zrl]
|
||||
|
||||
[h3]Frequently Asked Questions For Developers[/h3]
|
||||
[zrl=[baseurl]/help/faq_developers]FAQ For Developers[/zrl]
|
||||
|
||||
[h3]External Resources[/h3]
|
||||
[zrl=[baseurl]/help/external-resource-links]External Resource Links[/zrl]
|
||||
[url=https://github.com/redmatrix/hubzilla]Main Website[/url]
|
||||
[url=https://github.com/redmatrix/hubzilla-addons]Addon Website[/url]
|
||||
[url=https://zothub.com/channel/one]Development Channel[/url]
|
||||
[url=https://federated.social/channel/postgres]Postgres-specific $Projectname Admin Support Channel[/url]
|
||||
|
||||
[url=[baseurl]/help/credits]$Projectname Credits[/url]
|
||||
|
||||
[h3]About This $Projectname Hub[/h3]
|
||||
[zrl=[baseurl]/help/TermsOfService]Terms of Service For This Hub[/zrl]
|
||||
[zrl=[baseurl]/siteinfo]Hub Information (/siteinfo)[/zrl]
|
||||
[zrl=[baseurl]/siteinfo/json]Detailed Technical Hub Information in JSON format(/siteinfo/json)[/zrl]
|
||||
|
25
doc/members.bb
Normal file
@@ -0,0 +1,25 @@
|
||||
[h2]Documentation for Hub Members[/h2]
|
||||
|
||||
[h3]Getting Started[/h3]
|
||||
[zrl=[baseurl]/help/registration]Account Registration[/zrl]
|
||||
[zrl=[baseurl]/help/accounts_profiles_channels_basics]You at $Projectname: accounts, profiles and channels in short[/zrl]
|
||||
[zrl=[baseurl]/help/profiles]Profiles[/zrl]
|
||||
[zrl=[baseurl]/help/channels]Channels[/zrl]
|
||||
[zrl=[baseurl]/help/roles]Permission roles and Channel types[/zrl]
|
||||
[zrl=[baseurl]/help/first-post]Your first posting[/zrl]
|
||||
[zrl=[baseurl]/help/connecting_to_channels]Connecting To Other Channels[/zrl]
|
||||
[zrl=[baseurl]/help/permissions]Permissions And Encryption: You Are In Control[/zrl]
|
||||
[zrl=[baseurl]/help/cloud]Cloud Storage[/zrl]
|
||||
[zrl=[baseurl]/help/remove_account]Remove Channel or Account[/zrl]
|
||||
|
||||
[h3]Members Help[/h3]
|
||||
[zrl=[baseurl]/help/tags_and_mentions]Tags and Mentions[/zrl]
|
||||
[zrl=[baseurl]/help/webpages]Web Pages[/zrl]
|
||||
[zrl=[baseurl]/help/bbcode]BBcode reference for posts and comments[/zrl]
|
||||
[zrl=[baseurl]/help/checking_account_quota_usage]Checking Account Quota Usage[/zrl]
|
||||
[zrl=[baseurl]/help/cloud_desktop_clients]Cloud Desktop Clients[/zrl]
|
||||
[zrl=[baseurl]/help/AdvancedSearch]Advanced Directory Search[/zrl]
|
||||
[zrl=[baseurl]/help/addons]Help With Addons[/zrl]
|
||||
[zrl=[baseurl]/help/diaspora_compat]Diaspora Communications Compatibility (Diaspora and Friendica)[/zrl]
|
||||
[zrl=[baseurl]/help/faq_members]FAQ For Members[/zrl]
|
||||
[zrl=[baseurl]/help/bugs]Bugs, Issues, and things that go bump in the night...[/zrl]
|
@@ -4,15 +4,20 @@ We need much more than this, but here are areas where developers can help. Pleas
|
||||
|
||||
[li]Documentation - see Red Documentation Project To-Do List[/li]
|
||||
[li]Include TOS link in registration/verification email[/li]
|
||||
[li]forum widget with unread counts (requires the DB schema changes from v3/hubzilla to be viable)[/li]
|
||||
[li]Auto preview posts/comments (configurable timer kicks in the preview if not 0)[/li]
|
||||
[li]Create bug tracker module[/li]
|
||||
[li]delivery tracking/reporting[/li]
|
||||
[li]Filing posts - provide a dropdown menu integrated with the 'post actions menu'[/li]
|
||||
[li]integrate Mozilla Persona (possibly via plugin) https://github.com/mozilla/id-specs/blob/prod/browserid/index.md and become an idP[/li]
|
||||
[li]translation plugins - moses or apertium[/li]
|
||||
[li]plugins - provide 'disable' which is softer than 'uninstall' for those plugins which create additional DB tables[/li]
|
||||
[li]Infinite scroll improvements (i.e. embedded page links) see http://scrollsample.appspot.com/items [/li]
|
||||
[li]Finish the anti-spam bayesian engine[/li]
|
||||
[li]implement an email permission denied bounce message from the sys channel[/li]
|
||||
[li]provide a way for xchans with a certain network type to upgrade (unknown to rss, rss to statusnet, friendica-over-diaspora to friendica, for instance) based on new knowledge and/or redmatrix ability[/li]
|
||||
[li](done - HZ) If DAV folders exist, add an option to the Settings page to set a default folder for attachment uploads.[/li]
|
||||
[li]Integrate the "open site" list with the register page[/li]
|
||||
[li]Support comments and member notes on documentation pages (to achieve an effect similar to php.net)[/li]
|
||||
[li]implement oembed provider interface[/li]
|
||||
[li]refactor the oembed client interface so that we can safely sandbox remote content[/li]
|
||||
[li]Many modern social apps now have both a profile photo and a "cover photo". Add support for this. [/li]
|
||||
@@ -26,7 +31,7 @@ We need much more than this, but here are areas where developers can help. Pleas
|
||||
[li]External post connectors, add popular services[/li]
|
||||
[li](in progress Habeas Codice) service classes - provide a pluggable subscription payment gateway for premium accounts[/li]
|
||||
[li](in progress Habeas Codice) service classes - account overview page showing resources consumed by channel. With special consideration this page can also be accessed at a meta level by the site admin to drill down on problematic accounts/channels.[/li]
|
||||
[li]Events module - fix permissions on events, and provide JS translation support for the calendar overview (done); integrate with calDAV[/li]
|
||||
[li]implement CalDAV/CardDAV sync[/li]
|
||||
[li]Uploads - integrate #^[url=https://github.com/blueimp/jQuery-File-Upload]https://github.com/blueimp/jQuery-File-Upload[/url][/li]
|
||||
[li]Import/export - include events, things, etc.[/li]
|
||||
[li]API extensions, for Twitter API - search, friending, threading. For Red API, lots of stuff[/li]
|
||||
@@ -43,7 +48,7 @@ We need much more than this, but here are areas where developers can help. Pleas
|
||||
[li]Create mobile clients for the top platforms - which involves extending the API so that we can do stuff far beyond the current crop of Twitter/Statusnet clients. Ditto for mobile themes. We can probably use something like the Friendica Android app as a base to start from.[/li]
|
||||
[li](in progress Habeas Codice) Implement owned and exchangeable "things".[/li]
|
||||
[li]Family Account creation - using service classes (an account holder can create a certain number of sub-accounts which are all tied to their subscription - if the subscription lapses they all go away).[/li]
|
||||
[li]Put mod_admin under Comanche[/li]
|
||||
|
||||
|
||||
In many cases some of the work has already been started and code exists so that you needn't start from scratch. Please contact one of the developer channels like Channel One (one@zothub.com) before embarking and we can tell you what we already have and provide some insights on how we envision these features fitting together.
|
||||
|
||||
|
@@ -1,23 +0,0 @@
|
||||
[b]Documentation To-Do List[/b]
|
||||
|
||||
[b]Documentation we need to write[/b]
|
||||
|
||||
Database schema detailed descriptions
|
||||
|
||||
Complete plugin hook documentation
|
||||
|
||||
API documentation
|
||||
|
||||
Function and code documentation (doxygen)
|
||||
|
||||
New Member guide
|
||||
|
||||
"Extra Feature" reference, description of each
|
||||
|
||||
Detailed Personal Settings Documentation
|
||||
|
||||
Administration Guide (post-install)
|
||||
|
||||
Administration Guide (pre-install)
|
||||
|
||||
Return to the [url=[baseurl]/help/main]Main documentation page[/url]
|
@@ -1,6 +1,6 @@
|
||||
[b]What is Zot?[/b]
|
||||
|
||||
Zot is the protocol that powers the $Projectname, providing three core capabilities: Communications, Identity, and Access Control.
|
||||
Zot is the protocol that powers $Projectname, providing three core capabilities: Communications, Identity, and Access Control.
|
||||
|
||||
The functionality it provides can also be described as follows:
|
||||
|
||||
@@ -9,43 +9,43 @@ The functionality it provides can also be described as follows:
|
||||
|
||||
[b][size=20]Communications[/size][/b]
|
||||
|
||||
Zot is a revolutionary protocol which provides [i]decentralised communications[/i] and [i]identity management[/i] across the matrix. The resulting platform can provide web services comparable to those offered by large corporate providers, but without the large corporate provider and their associated privacy issues, insatiable profit drive, and walled-garden mentality.
|
||||
Zot is a revolutionary protocol which provides [i]decentralised communications[/i] and [i]identity management[/i] across the grid. The resulting platform can provide web services comparable to those offered by large corporate providers, but without the large corporate provider and their associated privacy issues, insatiable profit drive, and walled-garden mentality.
|
||||
|
||||
Communications and social networking are an integral part of the matrix. Any channel (and any services provided by that channel) can make full use of feature-rich social communications on a global scale. These communications may be public or private - and private communications comprise not only fully encrypted transport, but also encrypted storage to help protect against accidental snooping and disclosure by rogue system administrators and internet service providers.
|
||||
Communications and social networking are an integral part of the grid. Any channel (and any services provided by that channel) can make full use of feature-rich social communications on a global scale. These communications may be public or private - and private communications comprise not only fully encrypted transport, but also encrypted storage to help protect against accidental snooping and disclosure by rogue system administrators and internet service providers.
|
||||
|
||||
Zot allows a wide array of background services in the matrix, from offering friend suggestions, to directory services. You can also perform other things which would typically only be possibly on a centralized provider - such as "Wall to Wall" posts. Priivate/multiple profiles can be easily created, and web content can be tailored to the viewer via the [i]Affinity Slider[/i].
|
||||
Zot allows a wide array of background services in the grid, from offering friend suggestions, to directory services. You can also perform other things which would typically only be possibly on a centralized provider - such as "Wall to Wall" posts. Private/multiple profiles can be easily created, and web content can be tailored to the viewer via the [i]Affinity Slider[/i].
|
||||
|
||||
You won't find these features at all on other decentralized communication services. In addition to providing hub (server) decentralization, perhaps the most innovative and interesting Zot feature is its provision of [i]decentralized identity[/i] services.
|
||||
|
||||
[b][size=20]Identity[/size][/b]
|
||||
|
||||
Zot's identity layer is unique. It provides [i]invisible single sign-on[/i] across all sites in the matrix.
|
||||
Zot's identity layer is unique. It provides [i]invisible single sign-on[/i] across all sites in the grid.
|
||||
|
||||
It also provides [i]nomadic identity[/i], so that your communications with friends, family, and or anyone else you're communicating with won't be affected by the loss of your primary communication node - either temporarily or permanently.
|
||||
|
||||
The important bits of your identity and relationships can be backed up to a thumb drive, or your laptop, and may appear at any node in the matrix at any time - with all your friends and preferences intact.
|
||||
The important bits of your identity and relationships can be backed up to a thumb drive, or your laptop, and may appear at any node in the grid at any time - with all your friends and preferences intact.
|
||||
|
||||
Crucially, these nomadic instances are kept in sync so any instance can take over if another one is compromised or damaged. This protects you against not only major system failure, but also temporary site overloads and governmental manipulation or censorship.
|
||||
|
||||
Nomadic identity, single sign-on, and Red's decentralization of hubs, we believe, introduce a high degree of degree of [i]resiliency[/i] and [i]persistence[/i] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship.
|
||||
Nomadic identity, single sign-on, and $Projectname's decentralization of hubs, we believe, introduce a high degree of degree of [i]resiliency[/i] and [i]persistence[/i] in internet communications, that are sorely needed amidst global trends towards corporate centralization, as well as mass and indiscriminate government surveillance and censorship.
|
||||
|
||||
As you browse the matrix, viewing channels and their unique content, you are seamlessly authenticated as you go, even across completely different server hubs. No passwords to enter. Nothing to type. You're just greeted by name on every new site you visit.
|
||||
As you browse the grid, viewing channels and their unique content, you are seamlessly authenticated as you go, even across completely different server hubs. No passwords to enter. Nothing to type. You're just greeted by name on every new site you visit.
|
||||
|
||||
How does Zot do that? We call it [i]magic-auth[/i], because Red hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the matrix. This is one of the design goals of Red: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and user names for every different sight that someone might visit online.
|
||||
How does Zot do that? We call it [i]magic-auth[/i], because $Projectname hides the details of the complexities that go into single sign-on logins, and nomadic identities, from the experience of browsing on the grid. This is one of the design goals of $Projectname: to increase privacy, and freedom on the web, while reducing the complexity and tedium brought by the need to enter new passwords and user names for every different sight that someone might visit online.
|
||||
|
||||
You login only once on your home hub (or any nomadic backup hub you have chosen). This allows you to access any authenticated services provided anywhere in the matrix - such as shopping, blogs, forums, and access to private information. This is just like the services offered by large corporate providers with huge user databases; however you can be a member of this community, as well as a server on this network using a $35 Rasberry Pi. Your password isn't stored on a thousand different sites, or even worse, only on a few sites like Google and Facebook, beyond your direct control.
|
||||
You login only once on your home hub (or any nomadic backup hub you have chosen). This allows you to access any authenticated services provided anywhere in the grid - such as shopping, blogs, forums, and access to private information. This is just like the services offered by large corporate providers with huge user databases; however you can be a member of this community, as well as a server on this network using a $35 Rasberry Pi. Your password isn't stored on a thousand different sites, or even worse, only on a few sites like Google and Facebook, beyond your direct control.
|
||||
|
||||
You cannot be silenced. You cannot be removed from the matrix, unless you yourself choose to exit it.
|
||||
You cannot be silenced. You cannot be removed from the grid, unless you yourself choose to exit it.
|
||||
|
||||
[b][size=20]Access Control[/size][/b]
|
||||
|
||||
Zot's identity layer allows you to provide fine-grained permissions to any content you wish to publish - and these permissions extend across the $Projectname. This is like having one super huge website made up of an army of small individual websites - and where each channel in the matrix can completely control their privacy and sharing preferences for any web resources they create.
|
||||
Zot's identity layer allows you to provide fine-grained permissions to any content you wish to publish - and these permissions extend across $Projectname. This is like having one super huge website made up of an army of small individual websites - and where each channel in the grid can completely control their privacy and sharing preferences for any web resources they create.
|
||||
|
||||
Currently, the matrix supports communications, photo albums, events, and files. This will be extended in the future to provide content management services (web pages) and cloud storage facilities, such as WebDAV and multi-media libraries. Every object and how it is shared and with whom is completely under your control.
|
||||
Currently, the grid supports communications, photo albums, events, and files. This will be extended in the future to provide content management services (web pages) and cloud storage facilities, such as WebDAV and multi-media libraries. Every object and how it is shared and with whom is completely under your control.
|
||||
|
||||
This type of control is available on large corporate providers such as Facebook and Google, because they own the user database. Within the matrix, there is no need for a huge user databaseon your machine - because the matrix [i]is[/i] your user database. It has what is essentially infinite capacity (limited by the total number of hubs online across the internet), and is spread amongst hundreds, and potentially millions of computers.
|
||||
This type of control is available on large corporate providers such as Facebook and Google, because they own the user database. Within the grid, there is no need for a huge user databaseon your machine - because the grid [i]is[/i] your user database. It has what is essentially infinite capacity (limited by the total number of hubs online across the internet), and is spread amongst hundreds, and potentially millions of computers.
|
||||
|
||||
Access can be granted or denied for any resource, to any channel, or any group of channels; anywhere within the matrix. Others can access your content if you permit them to do so, and they do not even need to have an account on your hub. Your private photos cannot be viewed, because permission really work; they are not an addon that was added as an afterthought. If you aren't on the list of allowed viewers for a particular photo, you aren't going to look at it.
|
||||
Access can be granted or denied for any resource, to any channel, or any group of channels; anywhere within the grid. Others can access your content if you permit them to do so, and they do not even need to have an account on your hub. Your private photos cannot be viewed, because permission really work; they are not an addon that was added as an afterthought. If you aren't on the list of allowed viewers for a particular photo, you aren't going to look at it.
|
||||
|
||||
[b][size=18]Additional Resources and Links[/size][/b]
|
||||
|
||||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 524 B |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 9.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 910 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 906 B |
BIN
images/default_profile_photos/hubzilla_avatar/300.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
images/default_profile_photos/hubzilla_avatar/48.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
images/default_profile_photos/hubzilla_avatar/80.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 99 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 114 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 7.7 KiB |
BIN
images/hubzilla_house_arrows.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
images/hubzilla_logo_1.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
images/hubzilla_logo_2.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
images/hubzilla_logo_3.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
BIN
images/hubzilla_logo_4.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
images/hubzilla_logo_5.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
images/hubzilla_logo_6.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
images/hz-16.png
Normal file
After Width: | Height: | Size: 559 B |
BIN
images/hz-32.png
Normal file
After Width: | Height: | Size: 992 B |
BIN
images/hz-64.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
148
include/AccessList.php
Normal file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
|
||||
class AccessList {
|
||||
|
||||
private $allow_cid;
|
||||
private $allow_gid;
|
||||
private $deny_cid;
|
||||
private $deny_gid;
|
||||
|
||||
/* indicates if we are using the default constructor values or values that have been set explicitly. */
|
||||
|
||||
private $explicit;
|
||||
|
||||
function __construct($channel) {
|
||||
|
||||
if($channel) {
|
||||
$this->allow_cid = $channel['channel_allow_cid'];
|
||||
$this->allow_gid = $channel['channel_allow_gid'];
|
||||
$this->deny_cid = $channel['channel_deny_cid'];
|
||||
$this->deny_gid = $channel['channel_deny_gid'];
|
||||
}
|
||||
else {
|
||||
$this->allow_cid = '';
|
||||
$this->allow_gid = '';
|
||||
$this->deny_cid = '';
|
||||
$this->deny_gid = '';
|
||||
}
|
||||
|
||||
$this->explicit = false;
|
||||
}
|
||||
|
||||
function get_explicit() {
|
||||
return $this->explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from strings such as those in already
|
||||
* existing stored data items
|
||||
*/
|
||||
|
||||
function set($arr,$explicit = true) {
|
||||
$this->allow_cid = $arr['allow_cid'];
|
||||
$this->allow_gid = $arr['allow_gid'];
|
||||
$this->deny_cid = $arr['deny_cid'];
|
||||
$this->deny_gid = $arr['deny_gid'];
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
/**
|
||||
* return an array consisting of the current
|
||||
* access list components where the elements
|
||||
* are directly storable.
|
||||
*/
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'allow_cid' => $this->allow_cid,
|
||||
'allow_gid' => $this->allow_gid,
|
||||
'deny_cid' => $this->deny_cid,
|
||||
'deny_gid' => $this->deny_gid,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set AccessList from arrays, such as those provided by
|
||||
* acl_selector(). For convenience, a string (or non-array) input is
|
||||
* assumed to be a comma-separated list and auto-converted into an array.
|
||||
*/
|
||||
|
||||
function set_from_array($arr,$explicit = true) {
|
||||
$this->allow_cid = perms2str((is_array($arr['contact_allow']))
|
||||
? $arr['contact_allow'] : explode(',',$arr['contact_allow']));
|
||||
$this->allow_gid = perms2str((is_array($arr['group_allow']))
|
||||
? $arr['group_allow'] : explode(',',$arr['group_allow']));
|
||||
$this->deny_cid = perms2str((is_array($arr['contact_deny']))
|
||||
? $arr['contact_deny'] : explode(',',$arr['contact_deny']));
|
||||
$this->deny_gid = perms2str((is_array($arr['group_deny']))
|
||||
? $arr['group_deny'] : explode(',',$arr['group_deny']));
|
||||
|
||||
$this->explicit = $explicit;
|
||||
}
|
||||
|
||||
function is_private() {
|
||||
return (($this->allow_cid || $this->allow_gid || $this->deny_cid || $this->deny_gid) ? true : false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Used to wrap ACL elements in angle brackets for storage.
|
||||
*
|
||||
* @param[in,out] array &$item
|
||||
*/
|
||||
function sanitise_acl(&$item) {
|
||||
if (strlen($item))
|
||||
$item = '<' . notags(trim($item)) . '>';
|
||||
else
|
||||
unset($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert an ACL array to a storable string.
|
||||
*
|
||||
* @param array $p
|
||||
* @return array
|
||||
*/
|
||||
function perms2str($p) {
|
||||
$ret = '';
|
||||
|
||||
if (is_array($p))
|
||||
$tmp = $p;
|
||||
else
|
||||
$tmp = explode(',', $p);
|
||||
|
||||
if (is_array($tmp)) {
|
||||
array_walk($tmp, 'sanitise_acl');
|
||||
$ret = implode('', $tmp);
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Turn user/group ACLs stored as angle bracketed text into arrays.
|
||||
*
|
||||
* turn string array of angle-bracketed elements into string array
|
||||
* e.g. "<123xyz><246qyo><sxo33e>" => array(123xyz,246qyo,sxo33e);
|
||||
*
|
||||
* @param string $s
|
||||
* @return array
|
||||
*/
|
||||
function expand_acl($s) {
|
||||
$ret = array();
|
||||
|
||||
if(strlen($s)) {
|
||||
$t = str_replace('<','',$s);
|
||||
$a = explode('>',$t);
|
||||
foreach($a as $aa) {
|
||||
if($aa)
|
||||
$ret[] = $aa;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
@@ -174,9 +174,6 @@ function abook_toggle_flag($abook,$flag) {
|
||||
);
|
||||
}
|
||||
|
||||
$a = get_app();
|
||||
if($a->data['abook'])
|
||||
$a->data['abook']['abook_flags'] = $a->data['abook']['abook_flags'] ^ $flag;
|
||||
return $r;
|
||||
|
||||
}
|
||||
@@ -322,6 +319,8 @@ function channel_remove($channel_id, $local = true, $unset_session=true) {
|
||||
q("DELETE FROM `pconfig` WHERE `uid` = %d", intval($channel_id));
|
||||
q("DELETE FROM `spam` WHERE `uid` = %d", intval($channel_id));
|
||||
|
||||
// @FIXME At this stage we need to remove the file resources located under /store/$nickname
|
||||
|
||||
|
||||
q("delete from abook where abook_xchan = '%s' and abook_self = 1 ",
|
||||
dbesc($channel['channel_hash'])
|
||||
|
55
include/DReport.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
class DReport {
|
||||
|
||||
private $location;
|
||||
private $sender;
|
||||
private $recipient;
|
||||
private $message_id;
|
||||
private $status;
|
||||
private $date;
|
||||
|
||||
function __construct($location,$sender,$recipient,$message_id,$status = 'deliver') {
|
||||
$this->location = $location;
|
||||
$this->sender = $sender;
|
||||
$this->recipient = $recipient;
|
||||
$this->message_id = $message_id;
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function update($status) {
|
||||
$this->status = $status;
|
||||
$this->date = datetime_convert();
|
||||
}
|
||||
|
||||
function addto_recipient($name) {
|
||||
$this->recipient = $this->recipient . ' ' . $name;
|
||||
}
|
||||
|
||||
function addto_update($status) {
|
||||
$this->status = $this->status . ' ' . $status;
|
||||
}
|
||||
|
||||
|
||||
function set($arr) {
|
||||
$this->location = $arr['location'];
|
||||
$this->sender = $arr['sender'];
|
||||
$this->recipient = $arr['recipient'];
|
||||
$this->message_id = $arr['message_id'];
|
||||
$this->status = $arr['status'];
|
||||
$this->date = $arr['date'];
|
||||
}
|
||||
|
||||
function get() {
|
||||
return array(
|
||||
'location' => $this->location,
|
||||
'sender' => $this->sender,
|
||||
'recipient' => $this->recipient,
|
||||
'message_id' => $this->message_id,
|
||||
'status' => $this->status,
|
||||
'date' => $this->date
|
||||
);
|
||||
}
|
||||
}
|
@@ -57,6 +57,10 @@ function import_diaspora($data) {
|
||||
|
||||
$channel_id = $c['channel']['channel_id'];
|
||||
|
||||
// Hubzilla only: Turn on the Diaspora protocol so that follow requests will be sent.
|
||||
|
||||
set_pconfig($channel_id,'system','diaspora_allowed','1');
|
||||
|
||||
// todo - add auto follow settings, (and strip exif in hubzilla)
|
||||
|
||||
$location = escape_tags($data['user']['profile']['location']);
|
||||
@@ -70,7 +74,6 @@ function import_diaspora($data) {
|
||||
);
|
||||
|
||||
if($data['user']['profile']['nsfw']) {
|
||||
// fixme for hubzilla which doesn't use pageflags any more
|
||||
q("update channel set channel_pageflags = (channel_pageflags | %d) where channel_id = %d",
|
||||
intval(PAGE_ADULT),
|
||||
intval($channel_id)
|
||||
|
@@ -286,6 +286,7 @@ class Item extends BaseObject {
|
||||
'body' => $body,
|
||||
'text' => strip_tags($body),
|
||||
'id' => $this->get_id(),
|
||||
'mid' => $item['mid'],
|
||||
'isevent' => $isevent,
|
||||
'attend' => $attend,
|
||||
'consensus' => $consensus,
|
||||
@@ -301,6 +302,7 @@ class Item extends BaseObject {
|
||||
'vwall' => t('via Wall-To-Wall:'),
|
||||
'profile_url' => $profile_link,
|
||||
'item_photo_menu' => item_photo_menu($item),
|
||||
'dreport' => t('Delivery Report'),
|
||||
'name' => $profile_name,
|
||||
'thumb' => $profile_avatar,
|
||||
'osparkle' => $osparkle,
|
||||
|
@@ -217,6 +217,8 @@ function create_account($arr) {
|
||||
$result['email'] = $email;
|
||||
$result['password'] = $password;
|
||||
|
||||
call_hooks('register_account',$result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
190
include/api.php
@@ -631,6 +631,47 @@ require_once('include/items.php');
|
||||
}
|
||||
api_register_func('api/red/photos','api_photos', true);
|
||||
|
||||
function api_photo_detail(&$a,$type) {
|
||||
if (api_user()===false) return false;
|
||||
if(! $_REQUEST['photo_id']) return false;
|
||||
$scale = ((array_key_exists('scale',$_REQUEST)) ? intval($_REQUEST['scale']) : 0);
|
||||
$r = q("select * from photo where uid = %d and resource_id = '%s' and scale = %d limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc($_REQUEST['photo_id']),
|
||||
intval($scale)
|
||||
);
|
||||
if($r) {
|
||||
$data = dbunescbin($r[0]['data']);
|
||||
if(array_key_exists('os_storage',$r[0]) && intval($r[0]['os_storage']))
|
||||
$data = file_get_contents($data);
|
||||
$r[0]['data'] = base64_encode($data);
|
||||
$ret = array('photo' => $r[0]);
|
||||
$i = q("select id from item where uid = %d and resource_type = 'photo' and resource_id = '%s' limit 1",
|
||||
intval(local_channel()),
|
||||
dbesc($_REQUEST['photo_id'])
|
||||
);
|
||||
if($i) {
|
||||
$ii = q("select * from item where parent = %d order by id",
|
||||
intval($i[0]['id'])
|
||||
);
|
||||
if($ii) {
|
||||
xchan_query($ii,true,0);
|
||||
$ii = fetch_post_tags($ii,true);
|
||||
if($ii) {
|
||||
$ret['item'] = array();
|
||||
foreach($ii as $iii)
|
||||
$ret['item'][] = encode_item($iii,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
killme();
|
||||
}
|
||||
|
||||
api_register_func('api/red/photo', 'api_photo_detail', true);
|
||||
|
||||
|
||||
function api_group_members(&$a,$type) {
|
||||
if(api_user() === false)
|
||||
@@ -686,7 +727,7 @@ require_once('include/items.php');
|
||||
api_register_func('api/red/xchan','api_red_xchan',true);
|
||||
|
||||
|
||||
function api_statuses_mediap(&$a, $type) {
|
||||
function api_statuses_mediap(&$a, $type) {
|
||||
if (api_user() === false) {
|
||||
logger('api_statuses_update: no user');
|
||||
return false;
|
||||
@@ -696,7 +737,7 @@ require_once('include/items.php');
|
||||
$_REQUEST['type'] = 'wall';
|
||||
$_REQUEST['profile_uid'] = api_user();
|
||||
$_REQUEST['api_source'] = true;
|
||||
|
||||
|
||||
$txt = requestdata('status');
|
||||
|
||||
require_once('library/HTMLPurifier.auto.php');
|
||||
@@ -711,13 +752,13 @@ require_once('include/items.php');
|
||||
}
|
||||
$txt = html2bbcode($txt);
|
||||
|
||||
$a->argv[1] = $user_info['screen_name'];
|
||||
$a->argv[1] = $user_info['screen_name'];
|
||||
|
||||
$_REQUEST['silent']='1'; //tell wall_upload function to return img info instead of echo
|
||||
$_FILES['userfile'] = $_FILES['media'];
|
||||
require_once('mod/wall_attach.php');
|
||||
$posted = wall_attach_post($a);
|
||||
|
||||
|
||||
//now that we have the img url in bbcode we can add it to the status and insert the wall item.
|
||||
$_REQUEST['body']=$txt."\n\n".$posted;
|
||||
require_once('mod/item.php');
|
||||
@@ -855,6 +896,55 @@ require_once('include/items.php');
|
||||
api_register_func('api/red/item/new','red_item_new', true);
|
||||
|
||||
|
||||
function red_item(&$a, $type) {
|
||||
|
||||
if (api_user() === false) {
|
||||
logger('api_red_item_new: no user');
|
||||
return false;
|
||||
}
|
||||
|
||||
if($_REQUEST['mid']) {
|
||||
$arr = array('mid' => $_REQUEST['mid']);
|
||||
}
|
||||
elseif($_REQUEST['item_id']) {
|
||||
$arr = array('item_id' => $_REQUEST['item_id']);
|
||||
}
|
||||
else
|
||||
json_return_and_die(array());
|
||||
|
||||
$arr['start'] = 0;
|
||||
$arr['records'] = 999999;
|
||||
$arr['item_type'] = '*';
|
||||
|
||||
$i = items_fetch($arr,$a->get_channel(),get_observer_hash());
|
||||
|
||||
if(! $i)
|
||||
json_return_and_die(array());
|
||||
|
||||
$ret = array();
|
||||
$tmp = array();
|
||||
$str = '';
|
||||
foreach($i as $ii) {
|
||||
$tmp[] = encode_item($ii,true);
|
||||
if($str)
|
||||
$str .= ',';
|
||||
$str .= $ii['id'];
|
||||
}
|
||||
$ret['item'] = $tmp;
|
||||
if($str) {
|
||||
$r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item.id in ( $str ) ");
|
||||
|
||||
if($r)
|
||||
$ret['item_id'] = $r;
|
||||
}
|
||||
|
||||
json_return_and_die($ret);
|
||||
}
|
||||
|
||||
api_register_func('api/red/item/full','red_item', true);
|
||||
|
||||
|
||||
|
||||
function api_get_status($xchan_hash) {
|
||||
require_once('include/security.php');
|
||||
|
||||
@@ -1178,7 +1268,7 @@ require_once('include/items.php');
|
||||
and uid = " . $sys['channel_id'] . "
|
||||
$sql_extra
|
||||
AND id > %d group by mid
|
||||
order by received desc LIMIT %d OFFSET %d ",
|
||||
order by received desc LIMIT %d OFFSET %d ",
|
||||
intval($since_id),
|
||||
intval($count),
|
||||
intval($start)
|
||||
@@ -1392,17 +1482,17 @@ require_once('include/items.php');
|
||||
$diasp_url = str_replace('/channel/','/u/',$myurl);
|
||||
|
||||
if (get_config('system','use_fulltext_engine'))
|
||||
$sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where (MATCH(`author-link`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(`tag`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(tag) AGAINST ('".'"%s"'."' in boolean mode))) ",
|
||||
dbesc(protect_sprintf($myurl)),
|
||||
dbesc(protect_sprintf($myurl)),
|
||||
dbesc(protect_sprintf($diasp_url))
|
||||
);
|
||||
else
|
||||
$sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where ( `author-link` like '%s' or `tag` like '%s' or tag like '%s' )) ",
|
||||
dbesc(protect_sprintf('%' . $myurl)),
|
||||
dbesc(protect_sprintf('%' . $myurl . ']%')),
|
||||
dbesc(protect_sprintf('%' . $diasp_url . ']%'))
|
||||
);
|
||||
$sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where (MATCH(`author-link`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(`tag`) AGAINST ('".'"%s"'."' in boolean mode) or MATCH(tag) AGAINST ('".'"%s"'."' in boolean mode))) ",
|
||||
dbesc(protect_sprintf($myurl)),
|
||||
dbesc(protect_sprintf($myurl)),
|
||||
dbesc(protect_sprintf($diasp_url))
|
||||
);
|
||||
else
|
||||
$sql_extra .= sprintf(" AND `item`.`parent` IN (SELECT distinct(`parent`) from item where ( `author-link` like '%s' or `tag` like '%s' or tag like '%s' )) ",
|
||||
dbesc(protect_sprintf('%' . $myurl)),
|
||||
dbesc(protect_sprintf('%' . $myurl . ']%')),
|
||||
dbesc(protect_sprintf('%' . $diasp_url . ']%'))
|
||||
);
|
||||
|
||||
if ($max_id > 0)
|
||||
$sql_extra .= ' AND `item`.`id` <= '.intval($max_id);
|
||||
@@ -1496,10 +1586,10 @@ require_once('include/items.php');
|
||||
// );
|
||||
|
||||
$arr = array(
|
||||
'uid' => api_user(),
|
||||
'since_id' => $since_id,
|
||||
'start' => $start,
|
||||
'records' => $count);
|
||||
'uid' => api_user(),
|
||||
'since_id' => $since_id,
|
||||
'start' => $start,
|
||||
'records' => $count);
|
||||
|
||||
if ($user_info['self']==1)
|
||||
$arr['wall'] = 1;
|
||||
@@ -1508,7 +1598,7 @@ require_once('include/items.php');
|
||||
|
||||
|
||||
$r = items_fetch($arr,get_app()->get_channel(),get_observer_hash());
|
||||
|
||||
|
||||
$ret = api_format_items($r,$user_info);
|
||||
|
||||
|
||||
@@ -1526,32 +1616,32 @@ require_once('include/items.php');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Star/unstar an item
|
||||
* param: id : id of the item
|
||||
*
|
||||
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
|
||||
*/
|
||||
function api_favorites_create_destroy(&$a, $type){
|
||||
/**
|
||||
* Star/unstar an item
|
||||
* param: id : id of the item
|
||||
*
|
||||
* api v1 : https://web.archive.org/web/20131019055350/https://dev.twitter.com/docs/api/1/post/favorites/create/%3Aid
|
||||
*/
|
||||
function api_favorites_create_destroy(&$a, $type){
|
||||
|
||||
logger('favorites_create_destroy');
|
||||
|
||||
if (api_user()===false)
|
||||
if (api_user()===false)
|
||||
return false;
|
||||
|
||||
$action = str_replace(".".$type,"",argv(2));
|
||||
if (argc() > 3) {
|
||||
$itemid = intval(argv(3));
|
||||
} else {
|
||||
$itemid = intval($_REQUEST['id']);
|
||||
}
|
||||
$action = str_replace(".".$type,"",argv(2));
|
||||
if (argc() > 3) {
|
||||
$itemid = intval(argv(3));
|
||||
} else {
|
||||
$itemid = intval($_REQUEST['id']);
|
||||
}
|
||||
|
||||
$item = q("SELECT * FROM item WHERE id = %d AND uid = %d",
|
||||
intval($itemid),
|
||||
intval(api_user())
|
||||
);
|
||||
|
||||
if (! $item)
|
||||
if (! $item)
|
||||
return false;
|
||||
|
||||
switch($action){
|
||||
@@ -1581,22 +1671,22 @@ require_once('include/items.php');
|
||||
xchan_query($item,true);
|
||||
|
||||
|
||||
$user_info = api_get_user($a);
|
||||
$rets = api_format_items($item,$user_info);
|
||||
$ret = $rets[0];
|
||||
$user_info = api_get_user($a);
|
||||
$rets = api_format_items($item,$user_info);
|
||||
$ret = $rets[0];
|
||||
|
||||
$data = array('$status' => $ret);
|
||||
switch($type){
|
||||
case "atom":
|
||||
case "rss":
|
||||
$data = api_rss_extra($a, $data, $user_info);
|
||||
}
|
||||
$data = array('$status' => $ret);
|
||||
switch($type){
|
||||
case "atom":
|
||||
case "rss":
|
||||
$data = api_rss_extra($a, $data, $user_info);
|
||||
}
|
||||
|
||||
return api_apply_template("status", $type, $data);
|
||||
}
|
||||
return api_apply_template("status", $type, $data);
|
||||
}
|
||||
|
||||
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true);
|
||||
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true);
|
||||
api_register_func('api/favorites/create', 'api_favorites_create_destroy', true);
|
||||
api_register_func('api/favorites/destroy', 'api_favorites_create_destroy', true);
|
||||
|
||||
|
||||
|
||||
@@ -1607,7 +1697,7 @@ require_once('include/items.php');
|
||||
$user_info = api_get_user($a);
|
||||
|
||||
// params
|
||||
$count = (x($_REQUEST,'count')?$_REQUEST['count']:20);
|
||||
$count = (x($_REQUEST,'count')?$_REQUEST['count']:20);
|
||||
$page = (x($_REQUEST,'page')?$_REQUEST['page']-1:0);
|
||||
if($page < 0)
|
||||
$page = 0;
|
||||
|
@@ -264,18 +264,37 @@ function app_install($uid,$app) {
|
||||
else
|
||||
$x = app_store($app);
|
||||
|
||||
if($x['success'])
|
||||
return $x['app_id'];
|
||||
if($x['success']) {
|
||||
$r = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($x['app_id']),
|
||||
intval($uid)
|
||||
);
|
||||
if($r)
|
||||
build_sync_packet($uid,array('app' => $r[0]));
|
||||
|
||||
return $x['app_id'];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function app_destroy($uid,$app) {
|
||||
|
||||
|
||||
if($uid && $app['guid']) {
|
||||
|
||||
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
$x[0]['app_deleted'] = 1;
|
||||
|
||||
|
||||
$r = q("delete from app where app_id = '%s' and app_channel = %d",
|
||||
dbesc($app['guid']),
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
build_sync_packet($uid,array('app' => $x));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +344,7 @@ function app_store($arr) {
|
||||
return $ret;
|
||||
|
||||
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
|
||||
$x = import_profile_photo($arr['photo'],get_observer_hash(),true);
|
||||
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
|
||||
$arr['photo'] = $x[1];
|
||||
}
|
||||
|
||||
@@ -342,7 +361,9 @@ function app_store($arr) {
|
||||
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
|
||||
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
|
||||
|
||||
$r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s' )",
|
||||
$created = datetime_convert();
|
||||
|
||||
$r = q("insert into app ( app_id, app_sig, app_author, app_name, app_desc, app_url, app_photo, app_version, app_channel, app_addr, app_price, app_page, app_requires, app_created, app_edited ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s' )",
|
||||
dbesc($darray['app_id']),
|
||||
dbesc($darray['app_sig']),
|
||||
dbesc($darray['app_author']),
|
||||
@@ -355,7 +376,9 @@ function app_store($arr) {
|
||||
dbesc($darray['app_addr']),
|
||||
dbesc($darray['app_price']),
|
||||
dbesc($darray['app_page']),
|
||||
dbesc($darray['app_requires'])
|
||||
dbesc($darray['app_requires']),
|
||||
dbesc($created),
|
||||
dbesc($created)
|
||||
);
|
||||
if($r) {
|
||||
$ret['success'] = true;
|
||||
@@ -378,7 +401,7 @@ function app_update($arr) {
|
||||
return $ret;
|
||||
|
||||
if($arr['photo'] && ! strstr($arr['photo'],z_root())) {
|
||||
$x = import_profile_photo($arr['photo'],get_observer_hash(),true);
|
||||
$x = import_xchan_photo($arr['photo'],get_observer_hash(),true);
|
||||
$arr['photo'] = $x[1];
|
||||
}
|
||||
|
||||
@@ -393,7 +416,9 @@ function app_update($arr) {
|
||||
$darray['app_page'] = ((x($arr,'page')) ? escape_tags($arr['page']) : '');
|
||||
$darray['app_requires'] = ((x($arr,'requires')) ? escape_tags($arr['requires']) : '');
|
||||
|
||||
$r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s' where app_id = '%s' and app_channel = %d",
|
||||
$edited = datetime_convert();
|
||||
|
||||
$r = q("update app set app_sig = '%s', app_author = '%s', app_name = '%s', app_desc = '%s', app_url = '%s', app_photo = '%s', app_version = '%s', app_addr = '%s', app_price = '%s', app_page = '%s', app_requires = '%s', app_edited = '%s' where app_id = '%s' and app_channel = %d",
|
||||
dbesc($darray['app_sig']),
|
||||
dbesc($darray['app_author']),
|
||||
dbesc($darray['app_name']),
|
||||
@@ -405,6 +430,7 @@ function app_update($arr) {
|
||||
dbesc($darray['app_price']),
|
||||
dbesc($darray['app_page']),
|
||||
dbesc($darray['app_requires']),
|
||||
dbesc($edited),
|
||||
dbesc($darray['app_id']),
|
||||
intval($darray['app_channel'])
|
||||
);
|
||||
|
@@ -378,10 +378,36 @@ function attach_by_hash_nodata($hash, $rev = 0) {
|
||||
* @param string $options (optional) one of update, replace, revision
|
||||
* @param array $arr (optional) associative array
|
||||
*/
|
||||
|
||||
/**
|
||||
* A lot going on in this function, and some of it is old cruft and some is new cruft
|
||||
* and the entire thing probably needs to be refactored. It started out just storing
|
||||
* files, before we had DAV. It was made extensible to do extra stuff like edit an
|
||||
* existing file or optionally store a separate revision using $options to choose between different
|
||||
* storage models. Along the way we moved from
|
||||
* DB data storage to file system storage.
|
||||
* Then DAV came along and used different upload methods depending on whether the
|
||||
* file was stored as a DAV directory object or updated as a file object. One of these
|
||||
* is essentially an update and the other is basically an upload, but doesn't use the traditional PHP
|
||||
* upload workflow.
|
||||
* Then came hubzilla and we tried to merge photo functionality with the file storage. Most of
|
||||
* that integration occurs within this function.
|
||||
* This required overlap with the old photo_upload stuff and photo albums were
|
||||
* completely different concepts from directories which needed to be reconciled somehow.
|
||||
* The old revision stuff is kind of orphaned currently. There's new revision stuff for photos
|
||||
* which attaches (2) etc. onto the name, but doesn't integrate with the attach table revisioning.
|
||||
* That's where it sits currently. I repeat it needs to be refactored, and this note is here
|
||||
* for future explorers and those who may be doing that work to understand where it came
|
||||
* from and got to be the monstrosity of tangled unrelated code that it currently is.
|
||||
*/
|
||||
|
||||
function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
require_once('include/photos.php');
|
||||
|
||||
|
||||
call_hooks('photo_upload_begin',$arr);
|
||||
|
||||
$ret = array('success' => false);
|
||||
$channel_id = $channel['channel_id'];
|
||||
$sql_options = '';
|
||||
@@ -391,9 +417,19 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$hash = (($arr && $arr['hash']) ? $arr['hash'] : null);
|
||||
$upload_path = (($arr && $arr['directory']) ? $arr['directory'] : '');
|
||||
|
||||
logger('arr: ' . print_r($arr,true));
|
||||
$observer = array();
|
||||
|
||||
if(! perm_is_allowed($channel_id,get_observer_hash(), 'write_storage')) {
|
||||
if($observer_hash) {
|
||||
$x = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
dbesc($observer_hash)
|
||||
);
|
||||
if($x)
|
||||
$observer = $x[0];
|
||||
}
|
||||
|
||||
logger('arr: ' . print_r($arr,true));
|
||||
|
||||
if(! perm_is_allowed($channel_id,$observer_hash, 'write_storage')) {
|
||||
$ret['message'] = t('Permission denied.');
|
||||
return $ret;
|
||||
}
|
||||
@@ -411,16 +447,35 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
// revise or update must provide $arr['hash'] of the thing to revise/update
|
||||
|
||||
if($options !== 'update') {
|
||||
if(! x($_FILES,'userfile')) {
|
||||
$ret['message'] = t('No source file.');
|
||||
return $ret;
|
||||
if($options === 'import') {
|
||||
$src = $arr['src'];
|
||||
$filename = $arr['filename'];
|
||||
$filesize = @filesize($src);
|
||||
$hash = $arr['resource_id'];
|
||||
}
|
||||
elseif($options !== 'update') {
|
||||
$f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
|
||||
|
||||
call_hooks('photo_upload_file',$f);
|
||||
call_hooks('attach_upload_file',$f);
|
||||
|
||||
if (x($f,'src') && x($f,'filesize')) {
|
||||
$src = $f['src'];
|
||||
$filename = $f['filename'];
|
||||
$filesize = $f['filesize'];
|
||||
$type = $f['type'];
|
||||
|
||||
} else {
|
||||
|
||||
if(! x($_FILES,'userfile')) {
|
||||
$ret['message'] = t('No source file.');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
$filename = basename($_FILES['userfile']['name']);
|
||||
$filesize = intval($_FILES['userfile']['size']);
|
||||
}
|
||||
|
||||
$src = $_FILES['userfile']['tmp_name'];
|
||||
$filename = basename($_FILES['userfile']['name']);
|
||||
$filesize = intval($_FILES['userfile']['size']);
|
||||
|
||||
}
|
||||
|
||||
$existing_size = 0;
|
||||
@@ -457,12 +512,19 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
|
||||
|
||||
|
||||
$def_extension = '';
|
||||
$is_photo = 0;
|
||||
$gis = @getimagesize($src);
|
||||
logger('getimagesize: ' . print_r($gis,true), LOGGER_DATA);
|
||||
if(($gis) && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
|
||||
$is_photo = 1;
|
||||
if($gis[2] === IMAGETYPE_GIF)
|
||||
$def_extension = '.gif';
|
||||
if($gis[2] === IMAGETYPE_JPEG)
|
||||
$def_extension = '.jpg';
|
||||
if($gis[2] === IMAGETYPE_PNG)
|
||||
$def_extension = '.png';
|
||||
|
||||
}
|
||||
|
||||
$pathname = '';
|
||||
@@ -504,7 +566,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$folder_hash = '';
|
||||
}
|
||||
|
||||
if(! $options) {
|
||||
if((! $options) || ($options === 'import')) {
|
||||
|
||||
// A freshly uploaded file. Check for duplicate and resolve with the channel's overwrite settings.
|
||||
|
||||
@@ -521,9 +583,18 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$hash = $x[0]['hash'];
|
||||
}
|
||||
else {
|
||||
if(strpos($filename,'.') !== false) {
|
||||
$basename = substr($filename,0,strrpos($filename,'.'));
|
||||
$ext = substr($filename,strrpos($filename,'.'));
|
||||
}
|
||||
else {
|
||||
$basename = $filename;
|
||||
$ext = $def_extension;
|
||||
}
|
||||
|
||||
$r = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ",
|
||||
dbesc($filename),
|
||||
dbesc($filename . '(%)'),
|
||||
dbesc($basename . $ext),
|
||||
dbesc($basename . '(%)' . $ext),
|
||||
dbesc($folder_hash)
|
||||
);
|
||||
|
||||
@@ -533,7 +604,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
do {
|
||||
$found = false;
|
||||
foreach($r as $rr) {
|
||||
if($rr['filename'] === $filename . '(' . $x . ')') {
|
||||
if($rr['filename'] === $basename . '(' . $x . ')' . $ext) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
@@ -542,8 +613,10 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$x++;
|
||||
}
|
||||
while($found);
|
||||
$filename = $filename . '(' . $x . ')';
|
||||
$filename = $basename . '(' . $x . ')' . $ext;
|
||||
}
|
||||
else
|
||||
$filename = $basename . $ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -558,6 +631,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
if(($maxfilesize) && ($filesize > $maxfilesize)) {
|
||||
$ret['message'] = sprintf( t('File exceeds size limit of %d'), $maxfilesize);
|
||||
@unlink($src);
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -570,10 +644,11 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
if(($r) && (($r[0]['total'] + $filesize) > ($limit - $existing_size))) {
|
||||
$ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1$.0f Mbytes attachment storage."), $limit / 1024000);
|
||||
@unlink($src);
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
$mimetype = z_mime_content_type($filename);
|
||||
$mimetype = ((isset($type) && $type) ? $type : z_mime_content_type($filename));
|
||||
}
|
||||
|
||||
$os_basepath = 'store/' . $channel['channel_address'] . '/' ;
|
||||
@@ -591,7 +666,15 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
if($src)
|
||||
@file_put_contents($os_basepath . $os_relpath,@file_get_contents($src));
|
||||
|
||||
$created = datetime_convert();
|
||||
if(array_key_exists('created', $arr))
|
||||
$created = $arr['created'];
|
||||
else
|
||||
$created = datetime_convert();
|
||||
|
||||
if(array_key_exists('edited', $arr))
|
||||
$edited = $arr['edited'];
|
||||
else
|
||||
$edited = $created;
|
||||
|
||||
if($options === 'replace') {
|
||||
$r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, data = '%s', edited = '%s' where id = %d and uid = %d",
|
||||
@@ -648,6 +731,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
||||
$r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
|
||||
intval($channel['channel_account_id']),
|
||||
@@ -672,6 +756,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
}
|
||||
|
||||
if($is_photo) {
|
||||
|
||||
$args = array( 'source' => $source, 'visible' => 0, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct);
|
||||
if($arr['contact_allow'])
|
||||
$args['contact_allow'] = $arr['contact_allow'];
|
||||
@@ -681,7 +766,21 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
$args['contact_deny'] = $arr['contact_deny'];
|
||||
if($arr['group_deny'])
|
||||
$args['group_deny'] = $arr['group_deny'];
|
||||
$p = photo_upload($channel,get_app()->get_observer(),$args);
|
||||
if(array_key_exists('allow_cid',$arr))
|
||||
$args['allow_cid'] = $arr['allow_cid'];
|
||||
if(array_key_exists('allow_gid',$arr))
|
||||
$args['allow_gid'] = $arr['allow_gid'];
|
||||
if(array_key_exists('deny_cid',$arr))
|
||||
$args['deny_cid'] = $arr['deny_cid'];
|
||||
if(array_key_exists('deny_gid',$arr))
|
||||
$args['deny_gid'] = $arr['deny_gid'];
|
||||
|
||||
$args['created'] = $created;
|
||||
$args['edited'] = $edited;
|
||||
if($arr['item'])
|
||||
$args['item'] = $arr['item'];
|
||||
|
||||
$p = photo_upload($channel,$observer,$args);
|
||||
if($p['success']) {
|
||||
$ret['body'] = $p['body'];
|
||||
}
|
||||
@@ -692,6 +791,7 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
if(! $r) {
|
||||
$ret['message'] = t('File upload failed. Possible system limit or action terminated.');
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -704,13 +804,17 @@ function attach_store($channel, $observer_hash, $options = '', $arr = null) {
|
||||
|
||||
if(! $r) {
|
||||
$ret['message'] = t('Stored file could not be verified. Upload failed.');
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
$ret['success'] = true;
|
||||
$ret['data'] = $r[0];
|
||||
|
||||
if(! $is_photo) {
|
||||
// This would've been called already with a success result in photos_upload() if it was a photo.
|
||||
call_hooks('photo_upload_end',$ret);
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -1028,7 +1132,7 @@ function attach_mkdirp($channel, $observer_hash, $arr = null) {
|
||||
*/
|
||||
function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gid, $deny_cid, $deny_gid, $recurse = false) {
|
||||
|
||||
$r = q("select hash, flags, is_dir from attach where hash = '%s' and uid = %d limit 1",
|
||||
$r = q("select hash, flags, is_dir, is_photo from attach where hash = '%s' and uid = %d limit 1",
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
);
|
||||
@@ -1058,6 +1162,16 @@ function attach_change_permissions($channel_id, $resource, $allow_cid, $allow_gi
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r[0]['is_photo']) {
|
||||
$x = q("update photo set allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s' where resource_id = '%s' and uid = %d",
|
||||
dbesc($allow_cid),
|
||||
dbesc($allow_gid),
|
||||
dbesc($deny_cid),
|
||||
dbesc($deny_gid),
|
||||
dbesc($resource),
|
||||
intval($channel_id)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -437,7 +437,7 @@ function bb_observer($Text) {
|
||||
|
||||
|
||||
// BBcode 2 HTML was written by WAY2WEB.net
|
||||
// extended to work with Mistpark/Friendica/Red - Mike Macgirvin
|
||||
// extended to work with Mistpark/Friendica/Redmatrix/Hubzilla - Mike Macgirvin
|
||||
|
||||
function bbcode($Text, $preserve_nl = false, $tryoembed = true, $cache = false) {
|
||||
|
||||
|
@@ -91,6 +91,8 @@ function chatroom_destroy($channel,$arr) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
build_sync_packet($channel['channel_id'],array('chatroom' => $r));
|
||||
|
||||
q("delete from chatroom where cr_id = %d",
|
||||
intval($r[0]['cr_id'])
|
||||
);
|
||||
|
62
include/checksites.php
Normal file
@@ -0,0 +1,62 @@
|
||||
<?php /** @file */
|
||||
|
||||
require_once('boot.php');
|
||||
require_once('include/cli_startup.php');
|
||||
require_once('include/zot.php');
|
||||
require_once('include/hubloc.php');
|
||||
|
||||
|
||||
|
||||
function checksites_run($argv, $argc){
|
||||
|
||||
|
||||
cli_startup();
|
||||
$a = get_app();
|
||||
|
||||
logger('checksites: start');
|
||||
|
||||
if(($argc > 1) && ($argv[1]))
|
||||
$site_id = $argv[1];
|
||||
|
||||
if($site_id)
|
||||
$sql_options = " and site_url = '" . dbesc($argv[1]) . "' ";
|
||||
|
||||
$days = intval(get_config('system','sitecheckdays'));
|
||||
if($days < 1)
|
||||
$days = 30;
|
||||
|
||||
$r = q("select * from site where site_dead = 0 and site_update < %s - INTERVAL %s and site_type = %d $sql_options ",
|
||||
db_utcnow(), db_quoteinterval($days . ' DAY'),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
|
||||
if(! $r)
|
||||
return;
|
||||
|
||||
foreach($r as $rr) {
|
||||
if(! strcasecmp($rr['site_url'],z_root()))
|
||||
continue;
|
||||
|
||||
$x = ping_site($rr['site_url']);
|
||||
if($x['success']) {
|
||||
logger('checksites: ' . $rr['site_url']);
|
||||
q("update site set site_update = '%s' where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
}
|
||||
else {
|
||||
logger('marking dead site: ' . $x['message']);
|
||||
q("update site set site_dead = 1 where site_url = '%s' ",
|
||||
dbesc($rr['site_url'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (array_search(__file__,get_included_files())===0){
|
||||
checksites_run($argv,$argc);
|
||||
killme();
|
||||
}
|
@@ -395,7 +395,9 @@ function count_descendants($item) {
|
||||
* @brief Check if the activity of the item is visible.
|
||||
*
|
||||
* likes (etc.) can apply to other things besides posts. Check if they are post
|
||||
* children, in which case we handle them specially.
|
||||
* children, in which case we handle them specially. Activities which are unrecognised
|
||||
* as having special meaning and hidden will be treated as posts or comments and visible
|
||||
* in the stream.
|
||||
*
|
||||
* @param array $item
|
||||
* @return boolean
|
||||
@@ -403,12 +405,21 @@ function count_descendants($item) {
|
||||
function visible_activity($item) {
|
||||
$hidden_activities = array(ACTIVITY_LIKE, ACTIVITY_DISLIKE, ACTIVITY_AGREE, ACTIVITY_DISAGREE, ACTIVITY_ABSTAIN, ACTIVITY_ATTEND, ACTIVITY_ATTENDNO, ACTIVITY_ATTENDMAYBE);
|
||||
|
||||
$post_types = array(ACTIVITY_OBJ_NOTE,ACTIVITY_OBJ_COMMENT,basename(ACTIVITY_OBJ_NOTE),basename(ACTIVITY_OBJ_COMMENT));
|
||||
|
||||
foreach ($hidden_activities as $act) {
|
||||
if ((activity_match($item['verb'], $act)) && ($item['mid'] != $item['parent_mid'])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// In order to share edits with networks which have no concept of editing, we'll create
|
||||
// separate activities to indicate the edit. Our network will not require them, since our
|
||||
// edits are automatically applied and the activity indicated.
|
||||
|
||||
if(($item['verb'] === ACTIVITY_UPDATE) && (in_array($item['obj_type'],$post_types)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -932,9 +943,9 @@ function item_photo_menu($item){
|
||||
t("View Status") => $status_link,
|
||||
t("View Profile") => $profile_link,
|
||||
t("View Photos") => $photos_link,
|
||||
t("Matrix Activity") => $posts_link,
|
||||
t("Activity/Posts") => $posts_link,
|
||||
t("Connect") => $follow_url,
|
||||
t("Edit Contact") => $contact_url,
|
||||
t("Edit Connection") => $contact_url,
|
||||
t("Send PM") => $pm_url,
|
||||
t("Poke") => $poke_link
|
||||
);
|
||||
@@ -1126,6 +1137,7 @@ function status_editor($a, $x, $popup = false) {
|
||||
'$newpost' => 'true',
|
||||
'$baseurl' => $a->get_baseurl(true),
|
||||
'$editselect' => (($plaintext) ? 'none' : '/(profile-jot-text|prvmail-text)/'),
|
||||
'$pretext' => ((x($x,'pretext')) ? $x['pretext'] : ''),
|
||||
'$geotag' => $geotag,
|
||||
'$nickname' => $x['nickname'],
|
||||
'$ispublic' => t('Visible to <strong>everybody</strong>'),
|
||||
|
@@ -15,7 +15,10 @@ function deliver_run($argv, $argc) {
|
||||
|
||||
logger('deliver: invoked: ' . print_r($argv,true), LOGGER_DATA);
|
||||
|
||||
|
||||
for($x = 1; $x < $argc; $x ++) {
|
||||
|
||||
$dresult = null;
|
||||
$r = q("select * from outq where outq_hash = '%s' limit 1",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
@@ -26,6 +29,8 @@ function deliver_run($argv, $argc) {
|
||||
* If not, reduce the outq_priority.
|
||||
*/
|
||||
|
||||
$base = '';
|
||||
|
||||
$h = parse_url($r[0]['outq_posturl']);
|
||||
if($h) {
|
||||
$base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||
@@ -50,18 +55,45 @@ function deliver_run($argv, $argc) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// zot sites should all have a site record, unless they've been dead for as long as
|
||||
// your site has existed. Since we don't know for sure what these sites are,
|
||||
// call them unknown
|
||||
|
||||
q("insert into site (site_url, site_update, site_dead, site_type) values ('%s','%s',0,%d) ",
|
||||
dbesc($base),
|
||||
dbesc(datetime_convert()),
|
||||
intval(($r[0]['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
|
||||
|
||||
if($r[0]['outq_driver'] === 'post') {
|
||||
|
||||
|
||||
$result = z_post_url($r[0]['outq_posturl'],$r[0]['outq_msg']);
|
||||
if($result['success'] && $result['return_code'] < 300) {
|
||||
logger('deliver: queue post success to ' . $r[0]['outq_posturl'], LOGGER_DEBUG);
|
||||
if($base) {
|
||||
q("update site set site_update = '%s', site_dead = 0 where site_url = '%s' ",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($base)
|
||||
);
|
||||
}
|
||||
q("update dreport set dreport_result = '%s', dreport_time = '%s' where dreport_queue = '%s' limit 1",
|
||||
dbesc('accepted for delivery'),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
$y = q("delete from outq where outq_hash = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
|
||||
}
|
||||
else {
|
||||
logger('deliver: queue post returned ' . $result['return_code'] . ' from ' . $r[0]['outq_posturl'],LOGGER_DEBUG);
|
||||
@@ -92,17 +124,35 @@ function deliver_run($argv, $argc) {
|
||||
$m = json_decode($r[0]['outq_msg'],true);
|
||||
if(array_key_exists('message_list',$m)) {
|
||||
foreach($m['message_list'] as $mm) {
|
||||
$msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $mm)))));
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $mm)))));
|
||||
zot_import($msg,z_root());
|
||||
}
|
||||
}
|
||||
else {
|
||||
$msg = array('body' => json_encode(array('pickup' => array(array('notify' => $notify,'message' => $m)))));
|
||||
zot_import($msg,z_root());
|
||||
$msg = array('body' => json_encode(array('success' => true, 'pickup' => array(array('notify' => $notify,'message' => $m)))));
|
||||
$dresult = zot_import($msg,z_root());
|
||||
}
|
||||
$r = q("delete from outq where outq_hash = '%s'",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
if($dresult && is_array($dresult)) {
|
||||
foreach($dresult as $xx) {
|
||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
|
||||
dbesc($xx['message_id']),
|
||||
dbesc($xx['location']),
|
||||
dbesc($xx['recipient']),
|
||||
dbesc($xx['status']),
|
||||
dbesc(datetime_convert($xx['date'])),
|
||||
dbesc($xx['sender'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
q("delete from dreport where dreport_queue = '%s' limit 1",
|
||||
dbesc($argv[$x])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
29
include/deliver_hooks.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
|
||||
require_once('include/cli_startup.php');
|
||||
require_once('include/zot.php');
|
||||
|
||||
|
||||
function deliver_hooks_run($argv, $argc) {
|
||||
|
||||
cli_startup();
|
||||
|
||||
$a = get_app();
|
||||
|
||||
if($argc < 2)
|
||||
return;
|
||||
|
||||
|
||||
$r = q("select * from item where id = '%d'",
|
||||
intval($argv[1])
|
||||
);
|
||||
if($r)
|
||||
call_hooks('notifier_normal',$r[0]);
|
||||
|
||||
}
|
||||
|
||||
if (array_search(__file__,get_included_files())===0){
|
||||
deliver_hooks_run($argv,$argc);
|
||||
killme();
|
||||
}
|
@@ -151,16 +151,18 @@ function sync_directories($dirmode) {
|
||||
|
||||
$realm = get_directory_realm();
|
||||
if ($realm == DIRECTORY_REALM) {
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and ( site_realm = '%s' or site_realm = '') ",
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d and ( site_realm = '%s' or site_realm = '') ",
|
||||
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root()),
|
||||
intval(SITE_TYPE_ZOT),
|
||||
dbesc($realm)
|
||||
);
|
||||
} else {
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' ",
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_realm like '%s' and site_type = %d ",
|
||||
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root()),
|
||||
dbesc(protect_sprintf('%' . $realm . '%'))
|
||||
dbesc(protect_sprintf('%' . $realm . '%')),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -187,9 +189,10 @@ function sync_directories($dirmode) {
|
||||
intval($r[0]['site_valid'])
|
||||
);
|
||||
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s'",
|
||||
$r = q("select * from site where (site_flags & %d) > 0 and site_url != '%s' and site_type = %d ",
|
||||
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||
dbesc(z_root())
|
||||
dbesc(z_root()),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
}
|
||||
if (! $r)
|
||||
|
@@ -315,9 +315,12 @@ function notification($params) {
|
||||
'epreamble' => $epreamble,
|
||||
'body' => $body,
|
||||
'sitelink' => $sitelink,
|
||||
'sitename' => $sitename,
|
||||
'tsitelink' => $tsitelink,
|
||||
'hsitelink' => $hsitelink,
|
||||
'itemlink' => $itemlink
|
||||
'itemlink' => $itemlink,
|
||||
'sender' => $sender,
|
||||
'recipient' => $recip
|
||||
);
|
||||
|
||||
call_hooks('enotify', $h);
|
||||
|
@@ -63,9 +63,9 @@ function ical_wrapper($ev) {
|
||||
return '';
|
||||
|
||||
$o .= "BEGIN:VCALENDAR";
|
||||
$o .= "\nVERSION:2.0";
|
||||
$o .= "\nMETHOD:PUBLISH";
|
||||
$o .= "\nPRODID:-//" . get_config('system','sitename') . "//" . PLATFORM_NAME . "//" . strtoupper(get_app()->language). "\n";
|
||||
$o .= "\r\nVERSION:2.0";
|
||||
$o .= "\r\nMETHOD:PUBLISH";
|
||||
$o .= "\r\nPRODID:-//" . get_config('system','sitename') . "//" . PLATFORM_NAME . "//" . strtoupper(get_app()->language). "\r\n";
|
||||
if(array_key_exists('start', $ev))
|
||||
$o .= format_event_ical($ev);
|
||||
else {
|
||||
@@ -73,38 +73,84 @@ function ical_wrapper($ev) {
|
||||
$o .= format_event_ical($e);
|
||||
}
|
||||
}
|
||||
$o .= "\nEND:VCALENDAR\n";
|
||||
$o .= "\r\nEND:VCALENDAR\r\n";
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
function format_event_ical($ev) {
|
||||
|
||||
if($ev['type'] === 'task')
|
||||
return format_todo_ical($ev);
|
||||
|
||||
$o = '';
|
||||
|
||||
$o .= "\nBEGIN:VEVENT";
|
||||
$o .= "\r\nBEGIN:VEVENT";
|
||||
|
||||
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
|
||||
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
|
||||
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
|
||||
if($ev['start'])
|
||||
$o .= "\nDTSTART:" . datetime_convert('UTC','UTC', $ev['start'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['start'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
if($ev['finish'] && ! $ev['nofinish'])
|
||||
$o .= "\nDTEND:" . datetime_convert('UTC','UTC', $ev['finish'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
$o .= "\r\nDTEND:" . datetime_convert('UTC','UTC', $ev['finish'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
if($ev['summary'])
|
||||
$o .= "\nSUMMARY:" . format_ical_text($ev['summary']);
|
||||
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
|
||||
if($ev['location'])
|
||||
$o .= "\nLOCATION:" . format_ical_text($ev['location']);
|
||||
$o .= "\r\nLOCATION:" . format_ical_text($ev['location']);
|
||||
if($ev['description'])
|
||||
$o .= "\nDESCRIPTION:" . format_ical_text($ev['description']);
|
||||
$o .= "\nUID:" . $ev['event_hash'] ;
|
||||
$o .= "\nEND:VEVENT\n";
|
||||
$o .= "\r\nDESCRIPTION:" . format_ical_text($ev['description']);
|
||||
if($ev['event_priority'])
|
||||
$o .= "\r\nPRIORITY:" . intval($ev['event_priority']);
|
||||
$o .= "\r\nUID:" . $ev['event_hash'] ;
|
||||
$o .= "\r\nEND:VEVENT\r\n";
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
function format_todo_ical($ev) {
|
||||
|
||||
$o = '';
|
||||
|
||||
$o .= "\r\nBEGIN:VTODO";
|
||||
$o .= "\r\nCREATED:" . datetime_convert('UTC','UTC', $ev['created'],'Ymd\\THis\\Z');
|
||||
$o .= "\r\nLAST-MODIFIED:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
|
||||
$o .= "\r\nDTSTAMP:" . datetime_convert('UTC','UTC', $ev['edited'],'Ymd\\THis\\Z');
|
||||
if($ev['start'])
|
||||
$o .= "\r\nDTSTART:" . datetime_convert('UTC','UTC', $ev['start'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
if($ev['finish'] && ! $ev['nofinish'])
|
||||
$o .= "\r\nDUE:" . datetime_convert('UTC','UTC', $ev['finish'],'Ymd\\THis' . (($ev['adjust']) ? '\\Z' : ''));
|
||||
if($ev['summary'])
|
||||
$o .= "\r\nSUMMARY:" . format_ical_text($ev['summary']);
|
||||
if($ev['event_status']) {
|
||||
$o .= "\r\nSTATUS:" . $ev['event_status'];
|
||||
if($ev['event_status'] === 'COMPLETED')
|
||||
$o .= "\r\nCOMPLETED:" . datetime_convert('UTC','UTC', $ev['event_status_date'],'Ymd\\THis\\Z');
|
||||
}
|
||||
if(intval($ev['event_percent']))
|
||||
$o .= "\r\nPERCENT-COMPLETE:" . $ev['event_percent'];
|
||||
if(intval($ev['event_sequence']))
|
||||
$o .= "\r\nSEQUENCE:" . $ev['event_sequence'];
|
||||
if($ev['location'])
|
||||
$o .= "\r\nLOCATION:" . format_ical_text($ev['location']);
|
||||
if($ev['description'])
|
||||
$o .= "\r\nDESCRIPTION:" . format_ical_text($ev['description']);
|
||||
$o .= "\r\nUID:" . $ev['event_hash'] ;
|
||||
if($ev['event_priority'])
|
||||
$o .= "\r\nPRIORITY:" . intval($ev['event_priority']);
|
||||
$o .= "\r\nEND:VTODO\r\n";
|
||||
|
||||
return $o;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function format_ical_text($s) {
|
||||
require_once('include/bbcode.php');
|
||||
require_once('include/html2plain.php');
|
||||
|
||||
return(wordwrap(str_replace(',','\\,',html2plain(bbcode($s))),72,"\n ",true));
|
||||
return(wordwrap(str_replace(array(',',';','\\'),array('\\,','\\;','\\\\'),html2plain(bbcode($s))),72,"\r\n ",true));
|
||||
}
|
||||
|
||||
|
||||
@@ -218,12 +264,18 @@ function ev_compare($a, $b) {
|
||||
|
||||
function event_store_event($arr) {
|
||||
|
||||
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
|
||||
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
|
||||
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
|
||||
$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : '');
|
||||
$arr['created'] = (($arr['created']) ? $arr['created'] : datetime_convert());
|
||||
$arr['edited'] = (($arr['edited']) ? $arr['edited'] : datetime_convert());
|
||||
$arr['type'] = (($arr['type']) ? $arr['type'] : 'event' );
|
||||
$arr['event_xchan'] = (($arr['event_xchan']) ? $arr['event_xchan'] : '');
|
||||
$arr['event_priority'] = (($arr['event_priority']) ? $arr['event_priority'] : 0);
|
||||
|
||||
|
||||
if(array_key_exists('event_status_date',$arr))
|
||||
$arr['event_status_date'] = datetime_convert('UTC','UTC', $arr['event_status_date']);
|
||||
else
|
||||
$arr['event_status_date'] = NULL_DATE;
|
||||
|
||||
// Existing event being modified
|
||||
|
||||
if($arr['id'] || $arr['event_hash']) {
|
||||
@@ -265,6 +317,12 @@ function event_store_event($arr) {
|
||||
`type` = '%s',
|
||||
`adjust` = %d,
|
||||
`nofinish` = %d,
|
||||
`event_status` = '%s',
|
||||
`event_status_date` = '%s',
|
||||
`event_percent` = %d,
|
||||
`event_repeat` = '%s',
|
||||
`event_sequence` = %d,
|
||||
`event_priority` = %d,
|
||||
`allow_cid` = '%s',
|
||||
`allow_gid` = '%s',
|
||||
`deny_cid` = '%s',
|
||||
@@ -280,6 +338,12 @@ function event_store_event($arr) {
|
||||
dbesc($arr['type']),
|
||||
intval($arr['adjust']),
|
||||
intval($arr['nofinish']),
|
||||
dbesc($arr['event_status']),
|
||||
dbesc($arr['event_status_date']),
|
||||
intval($arr['event_percent']),
|
||||
dbesc($arr['event_repeat']),
|
||||
intval($arr['event_sequence']),
|
||||
intval($arr['event_priority']),
|
||||
dbesc($arr['allow_cid']),
|
||||
dbesc($arr['allow_gid']),
|
||||
dbesc($arr['deny_cid']),
|
||||
@@ -298,8 +362,8 @@ function event_store_event($arr) {
|
||||
$hash = random_string() . '@' . get_app()->get_hostname();
|
||||
|
||||
$r = q("INSERT INTO event ( uid,aid,event_xchan,event_hash,created,edited,start,finish,summary,description,location,type,
|
||||
adjust,nofinish,allow_cid,allow_gid,deny_cid,deny_gid)
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s' ) ",
|
||||
adjust,nofinish, event_status, event_status_date, event_percent, event_repeat, event_sequence, event_priority, allow_cid,allow_gid,deny_cid,deny_gid)
|
||||
VALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, '%s', %d, %d, '%s', '%s', '%s', '%s' ) ",
|
||||
intval($arr['uid']),
|
||||
intval($arr['account']),
|
||||
dbesc($arr['event_xchan']),
|
||||
@@ -314,6 +378,12 @@ function event_store_event($arr) {
|
||||
dbesc($arr['type']),
|
||||
intval($arr['adjust']),
|
||||
intval($arr['nofinish']),
|
||||
dbesc($arr['event_status']),
|
||||
dbesc($arr['event_status_date']),
|
||||
intval($arr['event_percent']),
|
||||
dbesc($arr['event_repeat']),
|
||||
intval($arr['event_sequence']),
|
||||
intval($arr['event_priority']),
|
||||
dbesc($arr['allow_cid']),
|
||||
dbesc($arr['allow_gid']),
|
||||
dbesc($arr['deny_cid']),
|
||||
@@ -376,6 +446,20 @@ function event_addtocal($item_id, $uid) {
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
|
||||
$item['resource_id'] = $event['event_hash'];
|
||||
$item['resource_type'] = 'event';
|
||||
|
||||
$i = array($item);
|
||||
xchan_query($i);
|
||||
$sync_item = fetch_post_tags($i);
|
||||
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
|
||||
dbesc($event['event_hash']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($z) {
|
||||
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -399,9 +483,15 @@ require_once('vendor/autoload.php');
|
||||
$ical = VObject\Reader::read($s);
|
||||
|
||||
if($ical) {
|
||||
foreach($ical->VEVENT as $event) {
|
||||
event_import_ical($event,$uid);
|
||||
|
||||
if($ical->VEVENT) {
|
||||
foreach($ical->VEVENT as $event) {
|
||||
event_import_ical($event,$uid);
|
||||
}
|
||||
}
|
||||
if($ical->VTODO) {
|
||||
foreach($ical->VTODO as $event) {
|
||||
event_import_ical_task($event,$uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -436,13 +526,17 @@ function event_import_ical($ical, $uid) {
|
||||
|
||||
// logger('dtstart: ' . var_export($dtstart,true));
|
||||
|
||||
if(($dtstart->timezone_type == 2) || (($dtstart->timezone_type == 3) && ($dtstart->timezone === 'UTC'))) {
|
||||
$ev['adjust'] = 1;
|
||||
|
||||
switch($dtstart->timezone_type) {
|
||||
case VObject\Property\DateTime::UTC :
|
||||
$ev['adjust'] = 0;
|
||||
break;
|
||||
case VObject\Property\DateTime::LOCALTZ :
|
||||
default:
|
||||
$ev['adjust'] = 1;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
$ev['adjust'] = 0;
|
||||
}
|
||||
|
||||
|
||||
$ev['start'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
|
||||
$dtstart->format(\DateTime::W3C));
|
||||
|
||||
@@ -475,6 +569,8 @@ function event_import_ical($ical, $uid) {
|
||||
$ev['description'] = (string) $ical->DESCRIPTION;
|
||||
if(isset($ical->SUMMARY))
|
||||
$ev['summary'] = (string) $ical->SUMMARY;
|
||||
if(isset($ical->PRIORITY))
|
||||
$ev['event_priority'] = intval((string) $ical->PRIORITY);
|
||||
|
||||
if(isset($ical->UID)) {
|
||||
$evuid = (string) $ical->UID;
|
||||
@@ -507,6 +603,138 @@ function event_import_ical($ical, $uid) {
|
||||
|
||||
}
|
||||
|
||||
function event_import_ical_task($ical, $uid) {
|
||||
|
||||
$c = q("select * from channel where channel_id = %d limit 1",
|
||||
intval($uid)
|
||||
);
|
||||
|
||||
if(! $c)
|
||||
return false;
|
||||
|
||||
$channel = $c[0];
|
||||
$ev = array();
|
||||
|
||||
|
||||
if(! isset($ical->DTSTART)) {
|
||||
logger('no event start');
|
||||
return false;
|
||||
}
|
||||
|
||||
$dtstart = $ical->DTSTART->getDateTime();
|
||||
|
||||
// logger('dtstart: ' . var_export($dtstart,true));
|
||||
|
||||
if(($dtstart->timezone_type == 2) || (($dtstart->timezone_type == 3) && ($dtstart->timezone === 'UTC'))) {
|
||||
$ev['adjust'] = 1;
|
||||
}
|
||||
else {
|
||||
$ev['adjust'] = 0;
|
||||
}
|
||||
|
||||
$ev['start'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
|
||||
$dtstart->format(\DateTime::W3C));
|
||||
|
||||
|
||||
if(isset($ical->DUE)) {
|
||||
$dtend = $ical->DUE->getDateTime();
|
||||
$ev['finish'] = datetime_convert((($ev['adjust']) ? 'UTC' : date_default_timezone_get()),'UTC',
|
||||
$dtend->format(\DateTime::W3C));
|
||||
}
|
||||
else
|
||||
$ev['nofinish'] = 1;
|
||||
|
||||
|
||||
if($ev['start'] === $ev['finish'])
|
||||
$ev['nofinish'] = 1;
|
||||
|
||||
if(isset($ical->CREATED)) {
|
||||
$created = $ical->CREATED->getDateTime();
|
||||
$ev['created'] = datetime_convert('UTC','UTC',$created->format(\DateTime::W3C));
|
||||
}
|
||||
|
||||
if(isset($ical->{'DTSTAMP'})) {
|
||||
$edited = $ical->{'DTSTAMP'}->getDateTime();
|
||||
$ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C));
|
||||
}
|
||||
|
||||
if(isset($ical->{'LAST-MODIFIED'})) {
|
||||
$edited = $ical->{'LAST-MODIFIED'}->getDateTime();
|
||||
$ev['edited'] = datetime_convert('UTC','UTC',$edited->format(\DateTime::W3C));
|
||||
}
|
||||
|
||||
if(isset($ical->LOCATION))
|
||||
$ev['location'] = (string) $ical->LOCATION;
|
||||
if(isset($ical->DESCRIPTION))
|
||||
$ev['description'] = (string) $ical->DESCRIPTION;
|
||||
if(isset($ical->SUMMARY))
|
||||
$ev['summary'] = (string) $ical->SUMMARY;
|
||||
if(isset($ical->PRIORITY))
|
||||
$ev['event_priority'] = intval((string) $ical->PRIORITY);
|
||||
|
||||
$stored_event = null;
|
||||
|
||||
if(isset($ical->UID)) {
|
||||
$evuid = (string) $ical->UID;
|
||||
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||
dbesc($evuid),
|
||||
intval($uid)
|
||||
);
|
||||
if($r) {
|
||||
$ev['event_hash'] = $evuid;
|
||||
$stored_event = $r[0];
|
||||
}
|
||||
else {
|
||||
$ev['external_id'] = $evuid;
|
||||
}
|
||||
}
|
||||
|
||||
if(isset($ical->SEQUENCE)) {
|
||||
$ev['event_sequence'] = (string) $ical->SEQUENCE;
|
||||
// see if our stored event is more current than the one we're importing
|
||||
if((intval($ev['event_sequence']) <= intval($stored_event['event_sequence']))
|
||||
&& ($ev['edited'] <= $stored_event['edited']))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isset($ical->STATUS)) {
|
||||
$ev['event_status'] = (string) $ical->STATUS;
|
||||
}
|
||||
|
||||
if(isset($ical->{'COMPLETED'})) {
|
||||
$completed = $ical->{'COMPLETED'}->getDateTime();
|
||||
$ev['event_status_date'] = datetime_convert('UTC','UTC',$completed->format(\DateTime::W3C));
|
||||
}
|
||||
|
||||
if(isset($ical->{'PERCENT-COMPLETE'})) {
|
||||
$ev['event_percent'] = (string) $ical->{'PERCENT-COMPLETE'} ;
|
||||
}
|
||||
|
||||
$ev['type'] = 'task';
|
||||
|
||||
if($ev['summary'] && $ev['start']) {
|
||||
$ev['event_xchan'] = $channel['channel_hash'];
|
||||
$ev['uid'] = $channel['channel_id'];
|
||||
$ev['account'] = $channel['channel_account_id'];
|
||||
$ev['private'] = 1;
|
||||
$ev['allow_cid'] = '<' . $channel['channel_hash'] . '>';
|
||||
|
||||
logger('storing event: ' . print_r($ev,true), LOGGER_ALL);
|
||||
$event = event_store_event($ev);
|
||||
if($event) {
|
||||
$item_id = event_store_item($ev,$event);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function event_store_item($arr, $event) {
|
||||
|
||||
@@ -527,12 +755,15 @@ function event_store_item($arr, $event) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
$item_arr = array();
|
||||
$prefix = '';
|
||||
// $birthday = false;
|
||||
|
||||
if($event['type'] === 'birthday') {
|
||||
$prefix = t('This event has been added to your calendar.');
|
||||
if(! is_sys_channel($arr['uid']))
|
||||
$prefix = t('This event has been added to your calendar.');
|
||||
// $birthday = true;
|
||||
|
||||
// The event is created on your own site by the system, but appears to belong
|
||||
@@ -568,7 +799,12 @@ function event_store_item($arr, $event) {
|
||||
|
||||
$private = (($arr['allow_cid'] || $arr['allow_gid'] || $arr['deny_cid'] || $arr['deny_gid']) ? 1 : 0);
|
||||
|
||||
q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
|
||||
// @FIXME can only update sig if we have the author's channel on this site
|
||||
// Until fixed, set it to nothing so it won't give us signature errors
|
||||
|
||||
$sig = '';
|
||||
|
||||
q("UPDATE item SET title = '%s', body = '%s', object = '%s', allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', edited = '%s', sig = '%s', item_flags = %d, item_private = %d, obj_type = '%s' WHERE id = %d AND uid = %d",
|
||||
dbesc($arr['summary']),
|
||||
dbesc($prefix . format_event_bbcode($arr)),
|
||||
dbesc($object),
|
||||
@@ -577,6 +813,7 @@ function event_store_item($arr, $event) {
|
||||
dbesc($arr['deny_cid']),
|
||||
dbesc($arr['deny_gid']),
|
||||
dbesc($arr['edited']),
|
||||
dbesc($sig),
|
||||
intval($r[0]['item_flags']),
|
||||
intval($private),
|
||||
dbesc(ACTIVITY_OBJ_EVENT),
|
||||
@@ -652,6 +889,17 @@ function event_store_item($arr, $event) {
|
||||
$item_arr['item_origin'] = $item_origin;
|
||||
$item_arr['item_thread_top'] = $item_thread_top;;
|
||||
|
||||
$attach = array(array(
|
||||
'href' => z_root() . '/events/ical/' . urlencode($event['event_hash']),
|
||||
'length' => 0,
|
||||
'type' => 'text/calendar',
|
||||
'title' => t('event') . '-' . $event['event_hash'],
|
||||
'revision' => ''
|
||||
));
|
||||
|
||||
$item_arr['attach'] = $attach;
|
||||
|
||||
|
||||
if(array_key_exists('term', $arr))
|
||||
$item_arr['term'] = $arr['term'];
|
||||
|
||||
@@ -698,3 +946,38 @@ function event_store_item($arr, $event) {
|
||||
return $item_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function todo_stat() {
|
||||
return array(
|
||||
'' => t('Not specified'),
|
||||
'NEEDS-ACTION' => t('Needs Action'),
|
||||
'COMPLETED' => t('Completed'),
|
||||
'IN-PROCESS' => t('In Process'),
|
||||
'CANCELLED' => t('Cancelled')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function tasks_fetch($arr) {
|
||||
|
||||
if(! local_channel())
|
||||
return;
|
||||
|
||||
$ret = array();
|
||||
$sql_extra = " and event_status != 'COMPLETED' ";
|
||||
if($arr && $arr['all'] == 1)
|
||||
$sql_extra = '';
|
||||
|
||||
$r = q("select * from event where type = 'task' and uid = %d $sql_extra order by created desc",
|
||||
intval(local_channel())
|
||||
);
|
||||
|
||||
$ret['success'] = (($r) ? true : false);
|
||||
if($r) {
|
||||
$ret['tasks'] = $r;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
|
||||
}
|
||||
|
@@ -28,9 +28,10 @@ function externals_run($argv, $argc){
|
||||
}
|
||||
else {
|
||||
$randfunc = db_getfunc('RAND');
|
||||
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d order by $randfunc limit 1",
|
||||
$r = q("select site_url, site_pull from site where site_url != '%s' and site_flags != %d and site_type = %d order by $randfunc limit 1",
|
||||
dbesc(z_root()),
|
||||
intval(DIRECTORY_MODE_STANDALONE)
|
||||
intval(DIRECTORY_MODE_STANDALONE),
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
if($r)
|
||||
$url = $r[0]['site_url'];
|
||||
|
@@ -14,6 +14,9 @@ function gprobe_run($argv, $argc){
|
||||
|
||||
$url = hex2bin($argv[1]);
|
||||
|
||||
if(! strpos($url,'@'))
|
||||
return;
|
||||
|
||||
$r = q("select * from xchan where xchan_addr = '%s' limit 1",
|
||||
dbesc($url)
|
||||
);
|
||||
|
@@ -229,7 +229,7 @@ function mini_group_select($uid,$group = '') {
|
||||
logger('mini_group_select: ' . print_r($grps,true), LOGGER_DATA);
|
||||
|
||||
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||
'$label' => t('Default privacy group for new contacts'),
|
||||
'$label' => t('Add new connections to this collection (privacy group)'),
|
||||
'$groups' => $grps
|
||||
));
|
||||
return $o;
|
||||
|
@@ -16,7 +16,9 @@ function is_matrix_url($url) {
|
||||
|
||||
function prune_hub_reinstalls() {
|
||||
|
||||
$r = q("select site_url from site where true");
|
||||
$r = q("select site_url from site where site_type = %d",
|
||||
intval(SITE_TYPE_ZOT)
|
||||
);
|
||||
if($r) {
|
||||
foreach($r as $rr) {
|
||||
$x = q("select count(*) as t, hubloc_sitekey, max(hubloc_connected) as c from hubloc where hubloc_url = '%s' group by hubloc_sitekey order by c",
|
||||
@@ -230,7 +232,7 @@ function xchan_store($arr) {
|
||||
if(! $r)
|
||||
return $r;
|
||||
|
||||
$photos = import_profile_photo($arr['photo'],$arr['hash']);
|
||||
$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]),
|
||||
@@ -275,4 +277,34 @@ function xchan_fetch($arr) {
|
||||
$ret[str_replace('xchan_','',$k)] = $v;
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function ping_site($url) {
|
||||
|
||||
$ret = array('success' => false);
|
||||
|
||||
$sys = get_sys_channel();
|
||||
|
||||
$m = zot_build_packet($sys,'ping');
|
||||
$r = zot_zot($url . '/post',$m);
|
||||
if(! $r['success']) {
|
||||
$ret['message'] = 'no answer from ' . $url;
|
||||
return $ret;
|
||||
}
|
||||
$packet_result = json_decode($r['body'],true);
|
||||
if(! $packet_result['success']) {
|
||||
$ret['message'] = 'packet failure from ' . $url;
|
||||
return $ret;
|
||||
}
|
||||
|
||||
if($packet_result['success']) {
|
||||
$ret['success'] = true;
|
||||
}
|
||||
else {
|
||||
$ret['message'] = 'unknown error from ' . $url;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
require_once('include/zot.php');
|
||||
require_once('include/crypto.php');
|
||||
|
||||
require_once('include/menu.php');
|
||||
|
||||
/**
|
||||
* @brief Called when creating a new channel.
|
||||
@@ -427,7 +427,7 @@ function create_identity($arr) {
|
||||
}
|
||||
}
|
||||
|
||||
call_hooks('register_account', $newuid);
|
||||
call_hooks('create_identity', $newuid);
|
||||
|
||||
proc_run('php','include/directory.php', $ret['channel']['channel_id']);
|
||||
}
|
||||
@@ -555,17 +555,76 @@ function identity_basic_export($channel_id, $items = false) {
|
||||
if($r)
|
||||
$ret['term'] = $r;
|
||||
|
||||
$r = q("select * from obj where obj_channel = %d",
|
||||
|
||||
// add psuedo-column obj_baseurl to aid in relocations
|
||||
|
||||
$r = q("select obj.*, '%s' as obj_baseurl from obj where obj_channel = %d",
|
||||
dbesc(z_root()),
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
if($r)
|
||||
$ret['obj'] = $r;
|
||||
|
||||
$r = q("select * from app where app_channel = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r)
|
||||
$ret['app'] = $r;
|
||||
|
||||
$r = q("select * from chatroom where cr_uid = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r)
|
||||
$ret['chatroom'] = $r;
|
||||
|
||||
|
||||
$r = q("select * from event where uid = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r)
|
||||
$ret['event'] = $r;
|
||||
|
||||
$r = q("select * from item where resource_type = 'event' and uid = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
if($r) {
|
||||
$ret['event_item'] = array();
|
||||
xchan_query($r);
|
||||
$r = fetch_post_tags($r,true);
|
||||
foreach($r as $rr)
|
||||
$ret['event_item'][] = encode_item($rr,true);
|
||||
}
|
||||
|
||||
$x = menu_list($channel_id);
|
||||
if($x) {
|
||||
$ret['menu'] = array();
|
||||
for($y = 0; $y < count($x); $y ++) {
|
||||
$m = menu_fetch($x[$y]['menu_name'],$channel_id,$ret['channel']['channel_hash']);
|
||||
if($m)
|
||||
$ret['menu'][] = menu_element($m);
|
||||
}
|
||||
}
|
||||
|
||||
$x = menu_list($channel_id);
|
||||
if($x) {
|
||||
$ret['menu'] = array();
|
||||
for($y = 0; $y < count($x); $y ++) {
|
||||
$m = menu_fetch($x[$y]['menu_name'],$channel_id,$ret['channel']['channel_hash']);
|
||||
if($m)
|
||||
$ret['menu'][] = menu_element($m);
|
||||
}
|
||||
}
|
||||
|
||||
$addon = array('channel_id' => $channel_id,'data' => $ret);
|
||||
call_hooks('identity_basic_export',$addon);
|
||||
$ret = $addon['data'];
|
||||
|
||||
|
||||
if(! $items)
|
||||
return $ret;
|
||||
|
||||
$r = q("select likes.*, item.mid from likes left join item on likes.iid = item.id where likes.channel_id = %d",
|
||||
$r = q("select * from likes where channel_id = %d",
|
||||
intval($channel_id)
|
||||
);
|
||||
|
||||
@@ -583,14 +642,17 @@ function identity_basic_export($channel_id, $items = false) {
|
||||
|
||||
/** @warning this may run into memory limits on smaller systems */
|
||||
|
||||
/** export one year of posts. If you want to export and import all posts you have to start with
|
||||
|
||||
/** export three months of posts. If you want to export and import all posts you have to start with
|
||||
* the first year and export/import them in ascending order.
|
||||
*
|
||||
* Don't export linked resource items. we'll have to pull those out separately.
|
||||
*/
|
||||
|
||||
$r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created > %s - INTERVAL %s",
|
||||
$r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created > %s - INTERVAL %s and resource_type = '' order by created",
|
||||
intval($channel_id),
|
||||
db_utcnow(),
|
||||
db_quoteinterval('1 YEAR')
|
||||
db_quoteinterval('3 MONTH')
|
||||
);
|
||||
if($r) {
|
||||
$ret['item'] = array();
|
||||
@@ -604,15 +666,27 @@ function identity_basic_export($channel_id, $items = false) {
|
||||
}
|
||||
|
||||
|
||||
function identity_export_year($channel_id,$year) {
|
||||
function identity_export_year($channel_id,$year,$month = 0) {
|
||||
|
||||
if(! $year)
|
||||
return array();
|
||||
|
||||
if($month && $month <= 12) {
|
||||
$target_month = sprintf('%02d',$month);
|
||||
$target_month_plus = sprintf('%02d',$month+1);
|
||||
}
|
||||
else
|
||||
$target_month = '01';
|
||||
|
||||
$ret = array();
|
||||
$mindate = datetime_convert('UTC','UTC',$year . '-01-01 00:00:00');
|
||||
$maxdate = datetime_convert('UTC','UTC',$year+1 . '-01-01 00:00:00');
|
||||
$r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' ",
|
||||
|
||||
$mindate = datetime_convert('UTC','UTC',$year . '-' . $target_month . '-01 00:00:00');
|
||||
if($month && $month < 12)
|
||||
$maxdate = datetime_convert('UTC','UTC',$year . '-' . $target_month_plus . '-01 00:00:00');
|
||||
else
|
||||
$maxdate = datetime_convert('UTC','UTC',$year+1 . '-01-01 00:00:00');
|
||||
|
||||
$r = q("select * from item where item_wall = 1 and item_deleted = 0 and uid = %d and created >= '%s' and created < '%s' and resource_type = '' order by created",
|
||||
intval($channel_id),
|
||||
dbesc($mindate),
|
||||
dbesc($maxdate)
|
||||
@@ -626,6 +700,17 @@ function identity_export_year($channel_id,$year) {
|
||||
$ret['item'][] = encode_item($rr,true);
|
||||
}
|
||||
|
||||
$r = q("select item_id.*, item.mid from item_id left join item on item_id.iid = item.id where item_id.uid = %d
|
||||
and item.created >= '%s' and item.created < '%s' order by created ",
|
||||
intval($channel_id),
|
||||
dbesc($mindate),
|
||||
dbesc($maxdate)
|
||||
);
|
||||
|
||||
if($r)
|
||||
$ret['item_id'] = $r;
|
||||
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
@@ -649,7 +734,7 @@ function identity_export_year($channel_id,$year) {
|
||||
*/
|
||||
function profile_load(&$a, $nickname, $profile = '') {
|
||||
|
||||
logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : ''));
|
||||
// logger('profile_load: ' . $nickname . (($profile) ? ' profile: ' . $profile : ''));
|
||||
|
||||
$user = q("select channel_id from channel where channel_address = '%s' and channel_removed = 0 limit 1",
|
||||
dbesc($nickname)
|
||||
@@ -912,7 +997,8 @@ function profile_sidebar($profile, $block = 0, $show_connect = true) {
|
||||
$marital = ((x($profile,'marital') == 1) ? t('Status:') : False);
|
||||
$homepage = ((x($profile,'homepage') == 1) ? t('Homepage:') : False);
|
||||
$profile['online'] = (($profile['online_status'] === 'online') ? t('Online Now') : False);
|
||||
logger('online: ' . $profile['online']);
|
||||
|
||||
// logger('online: ' . $profile['online']);
|
||||
|
||||
if(! perm_is_allowed($profile['uid'],((is_array($observer)) ? $observer['xchan_hash'] : ''),'view_profile')) {
|
||||
$block = true;
|
||||
|
806
include/import.php
Normal file
@@ -0,0 +1,806 @@
|
||||
<?php
|
||||
|
||||
require_once('include/menu.php');
|
||||
|
||||
function import_channel($channel) {
|
||||
|
||||
if(! array_key_exists('channel_system',$channel)) {
|
||||
$channel['channel_system'] = (($channel['channel_pageflags'] & 0x1000) ? 1 : 0);
|
||||
$channel['channel_removed'] = (($channel['channel_pageflags'] & 0x8000) ? 1 : 0);
|
||||
}
|
||||
|
||||
$r = q("select * from channel where (channel_guid = '%s' or channel_hash = '%s' or channel_address = '%s' ) limit 1",
|
||||
dbesc($channel['channel_guid']),
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($channel['channel_address'])
|
||||
);
|
||||
|
||||
// We should probably also verify the hash
|
||||
|
||||
if($r) {
|
||||
if($r[0]['channel_guid'] === $channel['channel_guid'] || $r[0]['channel_hash'] === $channel['channel_hash']) {
|
||||
logger('mod_import: duplicate channel. ', print_r($channel,true));
|
||||
notice( t('Cannot create a duplicate channel identifier on this system. Import failed.') . EOL);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// try at most ten times to generate a unique address.
|
||||
$x = 0;
|
||||
$found_unique = false;
|
||||
do {
|
||||
$tmp = $channel['channel_address'] . mt_rand(1000,9999);
|
||||
$r = q("select * from channel where channel_address = '%s' limit 1",
|
||||
dbesc($tmp)
|
||||
);
|
||||
if(! $r) {
|
||||
$channel['channel_address'] = $tmp;
|
||||
$found_unique = true;
|
||||
break;
|
||||
}
|
||||
$x ++;
|
||||
} while ($x < 10);
|
||||
if(! $found_unique) {
|
||||
logger('mod_import: duplicate channel. randomisation failed.', print_r($channel,true));
|
||||
notice( t('Unable to create a unique channel address. Import failed.') . EOL);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unset($channel['channel_id']);
|
||||
$channel['channel_account_id'] = get_account_id();
|
||||
$channel['channel_primary'] = (($seize) ? 1 : 0);
|
||||
|
||||
if($channel['channel_pageflags'] & PAGE_ALLOWCODE) {
|
||||
if(! is_site_admin())
|
||||
$channel['channel_pageflags'] = $channel['channel_pageflags'] ^ PAGE_ALLOWCODE;
|
||||
}
|
||||
|
||||
dbesc_array($channel);
|
||||
|
||||
$r = dbq("INSERT INTO channel (`"
|
||||
. implode("`, `", array_keys($channel))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($channel))
|
||||
. "')"
|
||||
);
|
||||
|
||||
if(! $r) {
|
||||
logger('mod_import: channel clone failed. ', print_r($channel,true));
|
||||
notice( t('Channel clone failed. Import failed.') . EOL);
|
||||
return false;
|
||||
}
|
||||
|
||||
$r = q("select * from channel where channel_account_id = %d and channel_guid = '%s' limit 1",
|
||||
intval(get_account_id()),
|
||||
$channel['channel_guid'] // Already dbesc'd
|
||||
);
|
||||
if(! $r) {
|
||||
logger('mod_import: channel not found. ', print_r($channel,true));
|
||||
notice( t('Cloned channel not found. Import failed.') . EOL);
|
||||
return false;
|
||||
}
|
||||
// reset
|
||||
$channel = $r[0];
|
||||
|
||||
set_default_login_identity(get_account_id(),$channel['channel_id'],false);
|
||||
logger('import step 1');
|
||||
$_SESSION['import_step'] = 1;
|
||||
ref_session_write(session_id(), serialize($_SESSION));
|
||||
return $channel;
|
||||
|
||||
}
|
||||
|
||||
function import_config($channel,$configs) {
|
||||
|
||||
if($channel && $configs) {
|
||||
foreach($configs as $config) {
|
||||
unset($config['id']);
|
||||
$config['uid'] = $channel['channel_id'];
|
||||
dbesc_array($config);
|
||||
$r = dbq("INSERT INTO pconfig (`"
|
||||
. implode("`, `", array_keys($config))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($config))
|
||||
. "')" );
|
||||
}
|
||||
load_pconfig($channel['channel_id']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function import_profiles($channel,$profiles) {
|
||||
|
||||
if($channel && $profiles) {
|
||||
foreach($profiles as $profile) {
|
||||
unset($profile['id']);
|
||||
$profile['aid'] = get_account_id();
|
||||
$profile['uid'] = $channel['channel_id'];
|
||||
|
||||
// we are going to reset all profile photos to the original
|
||||
// somebody will have to fix this later and put all the applicable photos into the export
|
||||
|
||||
$profile['photo'] = z_root() . '/photo/profile/l/' . $channel['channel_id'];
|
||||
$profile['thumb'] = z_root() . '/photo/profile/m/' . $channel['channel_id'];
|
||||
|
||||
dbesc_array($profile);
|
||||
$r = dbq("INSERT INTO profile (`"
|
||||
. implode("`, `", array_keys($profile))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($profile))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function import_hublocs($channel,$hublocs,$seize) {
|
||||
|
||||
if($channel && $hublocs) {
|
||||
foreach($hublocs as $hubloc) {
|
||||
|
||||
$hash = make_xchan_hash($hubloc['hubloc_guid'],$hubloc['hubloc_guid_sig']);
|
||||
if($hubloc['hubloc_network'] === 'zot' && $hash !== $hubloc['hubloc_hash']) {
|
||||
logger('forged hubloc: ' . print_r($hubloc,true));
|
||||
continue;
|
||||
}
|
||||
|
||||
if(! array_key_exists('hubloc_primary',$hubloc)) {
|
||||
$hubloc['hubloc_primary'] = (($hubloc['hubloc_flags'] & 0x0001) ? 1 : 0);
|
||||
$hubloc['hubloc_orphancheck'] = (($hubloc['hubloc_flags'] & 0x0004) ? 1 : 0);
|
||||
$hubloc['hubloc_error'] = (($hubloc['hubloc_status'] & 0x0003) ? 1 : 0);
|
||||
$hubloc['hubloc_deleted'] = (($hubloc['hubloc_flags'] & 0x1000) ? 1 : 0);
|
||||
}
|
||||
|
||||
$arr = array(
|
||||
'guid' => $hubloc['hubloc_guid'],
|
||||
'guid_sig' => $hubloc['hubloc_guid_sig'],
|
||||
'url' => $hubloc['hubloc_url'],
|
||||
'url_sig' => $hubloc['hubloc_url_sig']
|
||||
);
|
||||
if(($hubloc['hubloc_hash'] === $channel['channel_hash']) && intval($hubloc['hubloc_primary']) && ($seize))
|
||||
$hubloc['hubloc_primary'] = 0;
|
||||
|
||||
if(! zot_gethub($arr)) {
|
||||
unset($hubloc['hubloc_id']);
|
||||
dbesc_array($hubloc);
|
||||
|
||||
$r = dbq("INSERT INTO hubloc (`"
|
||||
. implode("`, `", array_keys($hubloc))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($hubloc))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function import_objs($channel,$objs) {
|
||||
|
||||
if($channel && $objs) {
|
||||
foreach($objs as $obj) {
|
||||
|
||||
// if it's the old term format - too hard to support
|
||||
if(! $obj['obj_created'])
|
||||
continue;
|
||||
|
||||
$baseurl = $obj['obj_baseurl'];
|
||||
unset($obj['obj_id']);
|
||||
unset($obj['obj_baseurl']);
|
||||
|
||||
$obj['obj_channel'] = $channel['channel_id'];
|
||||
|
||||
if($baseurl && (strpos($obj['obj_url'],$baseurl . '/thing/') !== false)) {
|
||||
$obj['obj_url'] = str_replace($baseurl,z_root(),$obj['obj_url']);
|
||||
}
|
||||
|
||||
if($obj['obj_imgurl']) {
|
||||
$x = import_xchan_photo($obj['obj_imgurl'],$channel['channel_hash'],true);
|
||||
$obj['obj_imgurl'] = $x[0];
|
||||
}
|
||||
|
||||
dbesc_array($obj);
|
||||
|
||||
$r = dbq("INSERT INTO obj (`"
|
||||
. implode("`, `", array_keys($obj))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($obj))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sync_objs($channel,$objs) {
|
||||
|
||||
if($channel && $objs) {
|
||||
foreach($objs as $obj) {
|
||||
|
||||
if(array_key_exists('obj_deleted',$obj) && $obj['obj_deleted'] && $obj['obj_obj']) {
|
||||
q("delete from obj where obj_obj = '%s' and obj_channel = %d limit 1",
|
||||
dbesc($obj['obj_obj']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it's the old term format - too hard to support
|
||||
if(! $obj['obj_created'])
|
||||
continue;
|
||||
|
||||
$baseurl = $obj['obj_baseurl'];
|
||||
unset($obj['obj_id']);
|
||||
unset($obj['obj_baseurl']);
|
||||
|
||||
$obj['obj_channel'] = $channel['channel_id'];
|
||||
|
||||
if($baseurl && (strpos($obj['obj_url'],$baseurl . '/thing/') !== false)) {
|
||||
$obj['obj_url'] = str_replace($baseurl,z_root(),$obj['obj_url']);
|
||||
}
|
||||
|
||||
$exists = false;
|
||||
|
||||
$x = q("select * from obj where obj_obj = '%s' and obj_channel = %d limit 1",
|
||||
dbesc($obj['obj_obj']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['obj_edited'] >= $obj['obj_edited'])
|
||||
continue;
|
||||
|
||||
$exists = true;
|
||||
}
|
||||
|
||||
if($obj['obj_imgurl']) {
|
||||
$x = import_xchan_photo($obj['obj_imgurl'],$channel['channel_hash'],true);
|
||||
$obj['obj_imgurl'] = $x[0];
|
||||
}
|
||||
|
||||
$hash = $obj['obj_obj'];
|
||||
|
||||
if($exists) {
|
||||
unset($obj['obj_obj']);
|
||||
foreach($obj as $k => $v) {
|
||||
$r = q("UPDATE obj SET `%s` = '%s' WHERE obj_obj = '%s' AND obj_channel = %d",
|
||||
dbesc($k),
|
||||
dbesc($v),
|
||||
dbesc($hash),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
dbesc_array($obj);
|
||||
|
||||
$r = dbq("INSERT INTO obj (`"
|
||||
. implode("`, `", array_keys($obj))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($obj))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function import_apps($channel,$apps) {
|
||||
|
||||
if($channel && $apps) {
|
||||
foreach($apps as $app) {
|
||||
|
||||
unset($app['id']);
|
||||
unset($app['app_channel']);
|
||||
|
||||
$app['app_channel'] = $channel['channel_id'];
|
||||
|
||||
if($app['app_photo']) {
|
||||
$x = import_xchan_photo($app['app_photo'],$channel['channel_hash'],true);
|
||||
$app['app_photo'] = $x[0];
|
||||
}
|
||||
|
||||
dbesc_array($app);
|
||||
$r = dbq("INSERT INTO app (`"
|
||||
. implode("`, `", array_keys($app))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($app))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sync_apps($channel,$apps) {
|
||||
|
||||
if($channel && $apps) {
|
||||
foreach($apps as $app) {
|
||||
|
||||
if(array_key_exists('app_deleted',$app) && $app['app_deleted'] && $app['app_id']) {
|
||||
q("delete from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['app_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($app['id']);
|
||||
unset($app['app_channel']);
|
||||
|
||||
if(! $app['app_created'] || $app['app_created'] === NULL_DATE)
|
||||
$app['app_created'] = datetime_convert();
|
||||
if(! $app['app_edited'] || $app['app_edited'] === NULL_DATE)
|
||||
$app['app_edited'] = datetime_convert();
|
||||
|
||||
$app['app_channel'] = $channel['channel_id'];
|
||||
|
||||
if($app['app_photo']) {
|
||||
$x = import_xchan_photo($app['app_photo'],$channel['channel_hash'],true);
|
||||
$app['app_photo'] = $x[0];
|
||||
}
|
||||
|
||||
$exists = false;
|
||||
|
||||
$x = q("select * from app where app_id = '%s' and app_channel = %d limit 1",
|
||||
dbesc($app['app_id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['app_edited'] >= $app['app_edited'])
|
||||
continue;
|
||||
$exists = true;
|
||||
}
|
||||
$hash = $app['app_id'];
|
||||
|
||||
if($exists) {
|
||||
unset($app['app_id']);
|
||||
foreach($app as $k => $v) {
|
||||
$r = q("UPDATE app SET `%s` = '%s' WHERE app_id = '%s' AND app_channel = %d",
|
||||
dbesc($k),
|
||||
dbesc($v),
|
||||
dbesc($hash),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dbesc_array($app);
|
||||
$r = dbq("INSERT INTO app (`"
|
||||
. implode("`, `", array_keys($app))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($app))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function import_chatrooms($channel,$chatrooms) {
|
||||
|
||||
if($channel && $chatrooms) {
|
||||
foreach($chatrooms as $chatroom) {
|
||||
|
||||
if(! $chatroom['cr_name'])
|
||||
continue;
|
||||
|
||||
unset($chatroom['cr_id']);
|
||||
unset($chatroom['cr_aid']);
|
||||
unset($chatroom['cr_uid']);
|
||||
|
||||
$chatroom['cr_aid'] = $channel['channel_account_id'];
|
||||
$chatroom['cr_uid'] = $channel['channel_id'];
|
||||
|
||||
dbesc_array($chatroom);
|
||||
$r = dbq("INSERT INTO chatroom (`"
|
||||
. implode("`, `", array_keys($chatroom))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($chatroom))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function sync_chatrooms($channel,$chatrooms) {
|
||||
|
||||
if($channel && $chatrooms) {
|
||||
foreach($chatrooms as $chatroom) {
|
||||
|
||||
if(! $chatroom['cr_name'])
|
||||
continue;
|
||||
|
||||
if(array_key_exists('cr_deleted',$chatroom) && $chatroom['cr_deleted']) {
|
||||
q("delete from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
|
||||
dbesc($chatroom['cr_name']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
unset($chatroom['cr_id']);
|
||||
unset($chatroom['cr_aid']);
|
||||
unset($chatroom['cr_uid']);
|
||||
|
||||
if(! $chatroom['cr_created'] || $chatroom['cr_created'] === NULL_DATE)
|
||||
$chatroom['cr_created'] = datetime_convert();
|
||||
if(! $chatroom['cr_edited'] || $chatroom['cr_edited'] === NULL_DATE)
|
||||
$chatroom['cr_edited'] = datetime_convert();
|
||||
|
||||
$chatroom['cr_aid'] = $channel['channel_account_id'];
|
||||
$chatroom['cr_uid'] = $channel['channel_id'];
|
||||
|
||||
$exists = false;
|
||||
|
||||
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
|
||||
dbesc($chatroom['cr_name']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['cr_edited'] >= $chatroom['cr_edited'])
|
||||
continue;
|
||||
$exists = true;
|
||||
}
|
||||
$name = $chatroom['cr_name'];
|
||||
|
||||
if($exists) {
|
||||
foreach($chatroom as $k => $v) {
|
||||
$r = q("UPDATE chatroom SET `%s` = '%s' WHERE cr_name = '%s' AND cr_uid = %d",
|
||||
dbesc($k),
|
||||
dbesc($v),
|
||||
dbesc($name),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dbesc_array($chatroom);
|
||||
$r = dbq("INSERT INTO chatroom (`"
|
||||
. implode("`, `", array_keys($chatroom))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($chatroom))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function import_items($channel,$items) {
|
||||
|
||||
if($channel && $items) {
|
||||
$allow_code = false;
|
||||
$r = q("select account_id, account_roles, channel_pageflags from account left join channel on channel_account_id = account_id
|
||||
where channel_id = %d limit 1",
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if(($r[0]['account_roles'] & ACCOUNT_ROLE_ALLOWCODE) || ($r[0]['channel_pageflags'] & PAGE_ALLOWCODE)) {
|
||||
$allow_code = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach($items as $i) {
|
||||
$item = get_item_elements($i,$allow_code);
|
||||
if(! $item)
|
||||
continue;
|
||||
|
||||
$r = q("select id, edited from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($item['mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if($item['edited'] > $r[0]['edited']) {
|
||||
$item['id'] = $r[0]['id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
item_store_update($item);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$item['aid'] = $channel['channel_account_id'];
|
||||
$item['uid'] = $channel['channel_id'];
|
||||
$item_result = item_store($item);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sync_items($channel,$items) {
|
||||
import_items($channel,$items);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function import_item_ids($channel,$itemids) {
|
||||
if($channel && $itemids) {
|
||||
foreach($itemids as $i) {
|
||||
$r = q("select id from item where mid = '%s' and uid = %d limit 1",
|
||||
dbesc($i['mid']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $r)
|
||||
continue;
|
||||
$z = q("select * from item_id where service = '%s' and sid = '%s' and iid = %d and uid = %d limit 1",
|
||||
dbesc($i['service']),
|
||||
dbesc($i['sid']),
|
||||
intval($r[0]['id']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if(! $z) {
|
||||
q("insert into item_id (iid,uid,sid,service) values(%d,%d,'%s','%s')",
|
||||
intval($r[0]['id']),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($i['sid']),
|
||||
dbesc($i['service'])
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function import_events($channel,$events) {
|
||||
|
||||
if($channel && $events) {
|
||||
foreach($events as $event) {
|
||||
unset($event['id']);
|
||||
$event['aid'] = $channel['channel_account_id'];
|
||||
$event['uid'] = $channel['channel_id'];
|
||||
|
||||
dbesc_array($event);
|
||||
$r = dbq("INSERT INTO event (`"
|
||||
. implode("`, `", array_keys($event))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($event))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sync_events($channel,$events) {
|
||||
|
||||
if($channel && $events) {
|
||||
foreach($events as $event) {
|
||||
|
||||
if((! $event['event_hash']) || (! $event['start']))
|
||||
continue;
|
||||
|
||||
if($event['event_deleted']) {
|
||||
$r = q("delete from event where event_hash = '%s' and uid = %d limit 1",
|
||||
dbesc($event['event_hash']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($event['id']);
|
||||
$event['aid'] = $channel['channel_account_id'];
|
||||
$event['uid'] = $channel['channel_id'];
|
||||
|
||||
$exists = false;
|
||||
|
||||
$x = q("select * from event where event_hash = '%s' and uid = %d limit 1",
|
||||
dbesc($event['event_hash']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($x) {
|
||||
if($x[0]['edited'] >= $event['edited'])
|
||||
continue;
|
||||
$exists = true;
|
||||
}
|
||||
|
||||
if($exists) {
|
||||
foreach($event as $k => $v) {
|
||||
$r = q("UPDATE event SET `%s` = '%s' WHERE event_hash = '%s' AND uid = %d",
|
||||
dbesc($k),
|
||||
dbesc($v),
|
||||
dbesc($event['event_hash']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
dbesc_array($event);
|
||||
$r = dbq("INSERT INTO event (`"
|
||||
. implode("`, `", array_keys($event))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($event))
|
||||
. "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function import_menus($channel,$menus) {
|
||||
|
||||
if($channel && $menus) {
|
||||
foreach($menus as $menu) {
|
||||
$m = array();
|
||||
$m['menu_channel_id'] = $channel['channel_id'];
|
||||
$m['menu_name'] = $menu['pagetitle'];
|
||||
$m['menu_desc'] = $menu['desc'];
|
||||
if($menu['created'])
|
||||
$m['menu_created'] = datetime_convert($menu['created']);
|
||||
if($menu['edited'])
|
||||
$m['menu_edited'] = datetime_convert($menu['edited']);
|
||||
|
||||
$m['menu_flags'] = 0;
|
||||
if($menu['flags']) {
|
||||
if(in_array('bookmark',$menu['flags']))
|
||||
$m['menu_flags'] |= MENU_BOOKMARK;
|
||||
if(in_array('system',$menu['flags']))
|
||||
$m['menu_flags'] |= MENU_SYSTEM;
|
||||
|
||||
}
|
||||
|
||||
$menu_id = menu_create($m);
|
||||
|
||||
if($menu_id) {
|
||||
if(is_array($menu['items'])) {
|
||||
foreach($menu['items'] as $it) {
|
||||
$mitem = array();
|
||||
|
||||
$mitem['mitem_link'] = str_replace('[baseurl]',z_root(),$it['link']);
|
||||
$mitem['mitem_desc'] = escape_tags($it['desc']);
|
||||
$mitem['mitem_order'] = intval($it['order']);
|
||||
if(is_array($it['flags'])) {
|
||||
$mitem['mitem_flags'] = 0;
|
||||
if(in_array('zid',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_ZID;
|
||||
if(in_array('new-window',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_NEWWIN;
|
||||
if(in_array('chatroom',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_CHATROOM;
|
||||
}
|
||||
menu_add_item($menu_id,$channel['channel_id'],$mitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function sync_menus($channel,$menus) {
|
||||
|
||||
if($channel && $menus) {
|
||||
foreach($menus as $menu) {
|
||||
$m = array();
|
||||
$m['menu_channel_id'] = $channel['channel_id'];
|
||||
$m['menu_name'] = $menu['pagetitle'];
|
||||
$m['menu_desc'] = $menu['desc'];
|
||||
if($menu['created'])
|
||||
$m['menu_created'] = datetime_convert($menu['created']);
|
||||
if($menu['edited'])
|
||||
$m['menu_edited'] = datetime_convert($menu['edited']);
|
||||
|
||||
$m['menu_flags'] = 0;
|
||||
if($menu['flags']) {
|
||||
if(in_array('bookmark',$menu['flags']))
|
||||
$m['menu_flags'] |= MENU_BOOKMARK;
|
||||
if(in_array('system',$menu['flags']))
|
||||
$m['menu_flags'] |= MENU_SYSTEM;
|
||||
|
||||
}
|
||||
|
||||
$editing = false;
|
||||
|
||||
$r = q("select * from menu where menu_name = '%s' and menu_channel_id = %d limit 1",
|
||||
dbesc($m['menu_name']),
|
||||
intval($channel['channel_id'])
|
||||
);
|
||||
if($r) {
|
||||
if($r[0]['menu_edited'] >= $m['menu_edited'])
|
||||
continue;
|
||||
if($menu['menu_deleted']) {
|
||||
menu_delete_id($r[0]['menu_id'],$channel['channel_id']);
|
||||
continue;
|
||||
}
|
||||
$menu_id = $r[0]['menu_id'];
|
||||
$m['menu_id'] = $r[0]['menu_id'];
|
||||
$x = menu_edit($m);
|
||||
if(! $x)
|
||||
continue;
|
||||
$editing = true;
|
||||
}
|
||||
if(! $editing) {
|
||||
$menu_id = menu_create($m);
|
||||
}
|
||||
if($menu_id) {
|
||||
if($editing) {
|
||||
// don't try syncing - just delete all the entries and start over
|
||||
q("delete from menu_item where mitem_menu_id = %d",
|
||||
intval($menu_id)
|
||||
);
|
||||
}
|
||||
|
||||
if(is_array($menu['items'])) {
|
||||
foreach($menu['items'] as $it) {
|
||||
$mitem = array();
|
||||
|
||||
$mitem['mitem_link'] = str_replace('[baseurl]',z_root(),$it['link']);
|
||||
$mitem['mitem_desc'] = escape_tags($it['desc']);
|
||||
$mitem['mitem_order'] = intval($it['order']);
|
||||
if(is_array($it['flags'])) {
|
||||
$mitem['mitem_flags'] = 0;
|
||||
if(in_array('zid',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_ZID;
|
||||
if(in_array('new-window',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_NEWWIN;
|
||||
if(in_array('chatroom',$it['flags']))
|
||||
$mitem['mitem_flags'] |= MENU_ITEM_CHATROOM;
|
||||
}
|
||||
menu_add_item($menu_id,$channel['channel_id'],$mitem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function import_likes($channel,$likes) {
|
||||
if($channel && $likes) {
|
||||
foreach($likes as $like) {
|
||||
if($like['deleted']) {
|
||||
q("delete from likes where liker = '%s' and likee = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s'",
|
||||
dbesc($like['liker']),
|
||||
dbesc($like['likee']),
|
||||
dbesc($like['verb']),
|
||||
dbesc($like['target_type']),
|
||||
dbesc($like['target_id'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($like['id']);
|
||||
unset($like['iid']);
|
||||
$like['channel_id'] = $channel['channel_id'];
|
||||
$r = q("select * from likes where liker = '%s' and likee = '%s' and verb = '%s' and target_type = '%s' and target_id = '%s' and i_mid = '%s'",
|
||||
dbesc($like['liker']),
|
||||
dbesc($like['likee']),
|
||||
dbesc($like['verb']),
|
||||
dbesc($like['target_type']),
|
||||
dbesc($like['target_id']),
|
||||
dbesc($like['i_mid'])
|
||||
);
|
||||
if($r)
|
||||
continue;
|
||||
|
||||
dbesc_array($config);
|
||||
$r = dbq("INSERT INTO likes (`"
|
||||
. implode("`, `", array_keys($like))
|
||||
. "`) VALUES ('"
|
||||
. implode("', '", array_values($like))
|
||||
. "')" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
41
include/importdoc.php
Executable file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
|
||||
|
||||
require_once('include/cli_startup.php');
|
||||
|
||||
|
||||
function importdoc_run($argv, $argc){
|
||||
|
||||
cli_startup();
|
||||
|
||||
require_once('mod/help.php');
|
||||
|
||||
|
||||
update_docs_dir('doc/*');
|
||||
|
||||
}
|
||||
if (array_search(__file__,get_included_files())===0){
|
||||
importdoc_run($argv,$argc);
|
||||
killme();
|
||||
}
|
||||
|
||||
function update_docs_dir($s) {
|
||||
$f = basename($s);
|
||||
$d = dirname($s);
|
||||
if($s === 'doc/html')
|
||||
return;
|
||||
$files = glob("$d/$f");
|
||||
if($files) {
|
||||
foreach($files as $fi) {
|
||||
if($fi === 'doc/html')
|
||||
continue;
|
||||
if(is_dir($fi))
|
||||
update_docs_dir("$fi/*");
|
||||
else
|
||||
store_doc_file($fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -272,6 +272,8 @@ function can_comment_on_post($observer_xchan, $item) {
|
||||
}
|
||||
if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'red'))
|
||||
return true;
|
||||
if(strstr($item['comment_policy'],'network:') && strstr($item['comment_policy'],'diaspora'))
|
||||
return true;
|
||||
if(strstr($item['comment_policy'],'site:') && strstr($item['comment_policy'],get_app()->get_hostname()))
|
||||
return true;
|
||||
|
||||
@@ -495,6 +497,32 @@ function post_activity_item($arr) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
function validate_item_elements($message,$arr) {
|
||||
|
||||
$result = array('success' => false);
|
||||
|
||||
if(! array_key_exists('created',$arr))
|
||||
$result['message'] = 'missing created, possible author/owner lookup failure';
|
||||
|
||||
if((! $arr['mid']) || (! $arr['parent_mid']))
|
||||
$result['message'] = 'missing message-id or parent message-id';
|
||||
|
||||
if(array_key_exists('flags',$message) && in_array('relay',$message['flags']) && $arr['mid'] === $arr['parent_mid'])
|
||||
$result['message'] = 'relay set on top level post';
|
||||
|
||||
if(! $result['message'])
|
||||
$result['success'] = true;
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Generate an Atom feed.
|
||||
*
|
||||
@@ -805,10 +833,14 @@ function title_is_body($title, $body) {
|
||||
}
|
||||
|
||||
|
||||
function get_item_elements($x) {
|
||||
function get_item_elements($x,$allow_code = false) {
|
||||
|
||||
$arr = array();
|
||||
$arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
if($allow_code)
|
||||
$arr['body'] = $x['body'];
|
||||
else
|
||||
$arr['body'] = (($x['body']) ? htmlspecialchars($x['body'],ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
$key = get_config('system','pubkey');
|
||||
|
||||
@@ -866,7 +898,11 @@ function get_item_elements($x) {
|
||||
|
||||
$arr['sig'] = (($x['signature']) ? htmlspecialchars($x['signature'], ENT_COMPAT,'UTF-8',false) : '');
|
||||
|
||||
if(array_key_exists('diaspora_signature',$x) && is_array($x['diaspora_signature']))
|
||||
$x['diaspora_signature'] = json_encode($x['diaspora_signature']);
|
||||
|
||||
$arr['diaspora_meta'] = (($x['diaspora_signature']) ? $x['diaspora_signature'] : '');
|
||||
|
||||
$arr['object'] = activity_sanitise($x['object']);
|
||||
$arr['target'] = activity_sanitise($x['target']);
|
||||
|
||||
@@ -1095,7 +1131,7 @@ function import_author_rss($x) {
|
||||
|
||||
if($r && $x['photo']) {
|
||||
|
||||
$photos = import_profile_photo($x['photo']['src'],$x['url']);
|
||||
$photos = import_xchan_photo($x['photo']['src'],$x['url']);
|
||||
|
||||
if($photos) {
|
||||
/** @bug $arr is undefined in this SQL query */
|
||||
@@ -1140,7 +1176,7 @@ function import_author_unknown($x) {
|
||||
);
|
||||
if($r && $x['photo']) {
|
||||
|
||||
$photos = import_profile_photo($x['photo']['src'],$x['url']);
|
||||
$photos = import_xchan_photo($x['photo']['src'],$x['url']);
|
||||
|
||||
if($photos) {
|
||||
/** @bug $arr is undefined in this SQL query */
|
||||
@@ -1277,7 +1313,7 @@ function encode_item($item,$mirror = false) {
|
||||
$x['comment_scope'] = $c_scope;
|
||||
|
||||
if($item['term'])
|
||||
$x['tags'] = encode_item_terms($item['term']);
|
||||
$x['tags'] = encode_item_terms($item['term'],$mirror);
|
||||
|
||||
if($item['diaspora_meta']) {
|
||||
$z = json_decode($item['diaspora_meta'],true);
|
||||
@@ -1369,11 +1405,16 @@ function encode_item_xchan($xchan) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function encode_item_terms($terms) {
|
||||
function encode_item_terms($terms,$mirror = false) {
|
||||
$ret = array();
|
||||
|
||||
$allowed_export_terms = array( TERM_UNKNOWN, TERM_HASHTAG, TERM_MENTION, TERM_CATEGORY, TERM_BOOKMARK );
|
||||
|
||||
if($mirror) {
|
||||
$allowed_export_terms[] = TERM_PCATEGORY;
|
||||
$allowed_export_terms[] = TERM_FILE;
|
||||
}
|
||||
|
||||
if($terms) {
|
||||
foreach($terms as $term) {
|
||||
if(in_array($term['type'],$allowed_export_terms))
|
||||
@@ -1581,12 +1622,10 @@ function get_mail_elements($x) {
|
||||
$arr['mail_obscured'] = 1;
|
||||
if($arr['body']) {
|
||||
$arr['body'] = str_rot47(base64url_encode($arr['body']));
|
||||
$arr['body'] = htmlspecialchars($arr['body'],ENT_COMPAT,'UTF-8',false);
|
||||
}
|
||||
|
||||
if($arr['title']) {
|
||||
$arr['title'] = str_rot47(base64url_encode($arr['title']));
|
||||
$arr['title'] = htmlspecialchars($arr['title'],ENT_COMPAT,'UTF-8',false);
|
||||
}
|
||||
if($arr['created'] > datetime_convert())
|
||||
$arr['created'] = datetime_convert();
|
||||
@@ -3292,7 +3331,7 @@ function start_delivery_chain($channel, $item, $item_id, $parent) {
|
||||
dbesc($title),
|
||||
dbesc($body),
|
||||
intval($item_wall),
|
||||
$intval($item_origin),
|
||||
intval($item_origin),
|
||||
intval($item_id)
|
||||
);
|
||||
|
||||
@@ -3403,6 +3442,8 @@ function post_is_importable($item,$abook) {
|
||||
if($exclude) {
|
||||
foreach($exclude as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
@@ -3422,6 +3463,8 @@ function post_is_importable($item,$abook) {
|
||||
if($include) {
|
||||
foreach($include as $word) {
|
||||
$word = trim($word);
|
||||
if(! $word)
|
||||
continue;
|
||||
if(substr($word,0,1) === '#' && $tags) {
|
||||
foreach($tags as $t)
|
||||
if(($t['type'] == TERM_HASHTAG) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||
@@ -3450,8 +3493,10 @@ function mail_store($arr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
|
||||
$arr['body'] = escape_tags($arr['body']);
|
||||
if(! $arr['mail_obscured']) {
|
||||
if((strpos($arr['body'],'<') !== false) || (strpos($arr['body'],'>') !== false))
|
||||
$arr['body'] = escape_tags($arr['body']);
|
||||
}
|
||||
|
||||
if(array_key_exists('attach',$arr) && is_array($arr['attach']))
|
||||
$arr['attach'] = json_encode($arr['attach']);
|
||||
@@ -3462,7 +3507,7 @@ function mail_store($arr) {
|
||||
$arr['to_xchan'] = ((x($arr,'to_xchan')) ? notags(trim($arr['to_xchan'])) : '');
|
||||
$arr['created'] = ((x($arr,'created') !== false) ? datetime_convert('UTC','UTC',$arr['created']) : datetime_convert());
|
||||
$arr['expires'] = ((x($arr,'expires') !== false) ? datetime_convert('UTC','UTC',$arr['expires']) : NULL_DATE);
|
||||
$arr['title'] = ((x($arr,'title')) ? notags(trim($arr['title'])) : '');
|
||||
$arr['title'] = ((x($arr,'title')) ? trim($arr['title']) : '');
|
||||
$arr['parent_mid'] = ((x($arr,'parent_mid')) ? notags(trim($arr['parent_mid'])) : '');
|
||||
$arr['body'] = ((x($arr,'body')) ? trim($arr['body']) : '');
|
||||
|
||||
@@ -3477,11 +3522,17 @@ function mail_store($arr) {
|
||||
dbesc($arr['mid']),
|
||||
intval($arr['channel_id'])
|
||||
);
|
||||
|
||||
if($r) {
|
||||
logger('mail_store: duplicate item ignored. ' . print_r($arr,true));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(! $r && $arr['mail_recalled'] == 1) {
|
||||
logger('mail_store: recalled item not found. ' . print_r($arr,true));
|
||||
return 0;
|
||||
}
|
||||
|
||||
call_hooks('post_mail',$arr);
|
||||
|
||||
if(x($arr,'cancel')) {
|
||||
@@ -4336,7 +4387,7 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
|
||||
);
|
||||
}
|
||||
else {
|
||||
$r = q("UPDATE item set item_deleted = 1, changed = '%s', edited = '%s' where if = %d",
|
||||
$r = q("UPDATE item set item_deleted = 1, changed = '%s', edited = '%s' where id = %d",
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
intval($item['id'])
|
||||
@@ -4373,6 +4424,18 @@ function delete_item_lowlevel($item, $stage = DROPITEM_NORMAL, $force = false) {
|
||||
intval($item['uid'])
|
||||
);
|
||||
|
||||
// remove delivery reports
|
||||
|
||||
$c = q("select channel_hash from channel where channel_id = %d limit 1",
|
||||
intval($item['uid'])
|
||||
);
|
||||
if($c) {
|
||||
q("delete from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
|
||||
dbesc($c[0]['channel_hash']),
|
||||
dbesc($item['mid'])
|
||||
);
|
||||
}
|
||||
|
||||
// network deletion request. Keep the message structure so that we can deliver delete notifications.
|
||||
// Come back after several days (or perhaps a month) to do the lowlevel delete (DROPITEM_PHASE2).
|
||||
|
||||
@@ -4600,10 +4663,12 @@ function zot_feed($uid,$observer_hash,$arr) {
|
||||
|
||||
$items = array();
|
||||
|
||||
/** @FIXME fix this part for PostgreSQL */
|
||||
/** @FIXME re-unite these SQL statements. There is no need for them to be separate. The mySQL is convoluted with misuse of group by. As it stands, there is a slight difference where the postgres version doesn't remove the duplicate parents up to 100. In practice this doesn't matter. It could be made to match behavior by adding "distinct on (parent) " to the front of the selection list, at a not-worth-it performance penalty (page temp results to disk). duplicates are still ignored in the in() clause, you just get less than 100 parents if there are many children. */
|
||||
|
||||
if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) {
|
||||
return array();
|
||||
$groupby = '';
|
||||
} else {
|
||||
$groupby = 'GROUP BY parent';
|
||||
}
|
||||
|
||||
$item_normal = item_normal();
|
||||
@@ -4613,7 +4678,7 @@ function zot_feed($uid,$observer_hash,$arr) {
|
||||
WHERE uid != %d
|
||||
$item_normal
|
||||
AND item_wall = 1
|
||||
and item_private = 0 $sql_extra GROUP BY parent ORDER BY created ASC $limit",
|
||||
and item_private = 0 $sql_extra $groupby ORDER BY created ASC $limit",
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
@@ -4621,7 +4686,7 @@ function zot_feed($uid,$observer_hash,$arr) {
|
||||
$r = q("SELECT parent, created, postopts from item
|
||||
WHERE uid = %d $item_normal
|
||||
AND item_wall = 1
|
||||
$sql_extra GROUP BY parent ORDER BY created ASC $limit",
|
||||
$sql_extra $groupby ORDER BY created ASC $limit",
|
||||
intval($uid)
|
||||
);
|
||||
}
|
||||
@@ -4692,6 +4757,12 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
|
||||
|
||||
if($arr['wall'])
|
||||
$sql_options .= " and item_wall = 1 ";
|
||||
|
||||
if($arr['item_id'])
|
||||
$sql_options .= " and parent = " . intval($arr['item_id']) . " ";
|
||||
|
||||
if($arr['mid'])
|
||||
$sql_options .= " and parent_mid = '" . dbesc($arr['mid']) . "' ";
|
||||
|
||||
$sql_extra = " AND item.parent IN ( SELECT parent FROM item WHERE item_thread_top = 1 $sql_options ) ";
|
||||
|
||||
@@ -4818,11 +4889,15 @@ function items_fetch($arr,$channel = null,$observer_hash = null,$client_mode = C
|
||||
require_once('include/security.php');
|
||||
$sql_extra .= item_permissions_sql($channel['channel_id'],$observer_hash);
|
||||
|
||||
|
||||
if($arr['pages'])
|
||||
$item_restrict = " AND item_type = " . ITEM_TYPE_WEBPAGE . " ";
|
||||
else
|
||||
$item_restrict = " AND item_type = 0 ";
|
||||
|
||||
if($arr['item_type'] === '*')
|
||||
$item_restrict = '';
|
||||
|
||||
if ($arr['nouveau'] && ($client_mode & CLIENT_MODE_LOAD) && $channel) {
|
||||
// "New Item View" - show all items unthreaded in reverse created date order
|
||||
|
||||
|
@@ -120,7 +120,11 @@ function load_translation_table($lang, $install = false) {
|
||||
global $a;
|
||||
|
||||
$a->strings = array();
|
||||
if(file_exists("view/$lang/strings.php")) {
|
||||
|
||||
if(file_exists("view/$lang/hstrings.php")) {
|
||||
include("view/$lang/hstrings.php");
|
||||
}
|
||||
elseif(file_exists("view/$lang/strings.php")) {
|
||||
include("view/$lang/strings.php");
|
||||
}
|
||||
|
||||
@@ -129,7 +133,10 @@ function load_translation_table($lang, $install = false) {
|
||||
if ($plugins !== false) {
|
||||
foreach($plugins as $p) {
|
||||
$name = $p['name'];
|
||||
if(file_exists("addon/$name/lang/$lang/strings.php")) {
|
||||
if(file_exists("addon/$name/lang/$lang/hstrings.php")) {
|
||||
include("addon/$name/lang/$lang/hstrings.php");
|
||||
}
|
||||
elseif(file_exists("addon/$name/lang/$lang/strings.php")) {
|
||||
include("addon/$name/lang/$lang/strings.php");
|
||||
}
|
||||
}
|
||||
@@ -139,7 +146,10 @@ function load_translation_table($lang, $install = false) {
|
||||
// Allow individual strings to be over-ridden on this site
|
||||
// Either for the default language or for all languages
|
||||
|
||||
if(file_exists("view/local-$lang/strings.php")) {
|
||||
if(file_exists("view/local-$lang/hstrings.php")) {
|
||||
include("view/local-$lang/hstrings.php");
|
||||
}
|
||||
elseif(file_exists("view/local-$lang/strings.php")) {
|
||||
include("view/local-$lang/strings.php");
|
||||
}
|
||||
}
|
||||
|
@@ -3,9 +3,10 @@
|
||||
require_once('include/security.php');
|
||||
require_once('include/bbcode.php');
|
||||
|
||||
|
||||
function menu_fetch($name,$uid,$observer_xchan) {
|
||||
|
||||
$sql_options = permissions_sql($uid);
|
||||
$sql_options = permissions_sql($uid,$observer_xchan);
|
||||
|
||||
$r = q("select * from menu where menu_channel_id = %d and menu_name = '%s' limit 1",
|
||||
intval($uid),
|
||||
@@ -237,7 +238,6 @@ function menu_edit($arr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
$r = q("select * from menu where menu_id = %d and menu_channel_id = %d limit 1",
|
||||
intval($menu_id),
|
||||
intval($menu_channel_id)
|
||||
@@ -299,19 +299,18 @@ function menu_add_item($menu_id, $uid, $arr) {
|
||||
$channel = get_app()->get_channel();
|
||||
}
|
||||
|
||||
$str_group_allow = perms2str($arr['group_allow']);
|
||||
$str_contact_allow = perms2str($arr['contact_allow']);
|
||||
$str_group_deny = perms2str($arr['group_deny']);
|
||||
$str_contact_deny = perms2str($arr['contact_deny']);
|
||||
$acl = new AccessList($channel);
|
||||
$acl->set_from_array($arr);
|
||||
$p = $acl->get();
|
||||
|
||||
$r = q("insert into menu_item ( mitem_link, mitem_desc, mitem_flags, allow_cid, allow_gid, deny_cid, deny_gid, mitem_channel_id, mitem_menu_id, mitem_order ) values ( '%s', '%s', %d, '%s', '%s', '%s', '%s', %d, %d, %d ) ",
|
||||
dbesc($mitem_link),
|
||||
dbesc($mitem_desc),
|
||||
intval($mitem_flags),
|
||||
dbesc($str_contact_allow),
|
||||
dbesc($str_group_allow),
|
||||
dbesc($str_contact_deny),
|
||||
dbesc($str_group_deny),
|
||||
dbesc($p['allow_cid']),
|
||||
dbesc($p['allow_gid']),
|
||||
dbesc($p['deny_cid']),
|
||||
dbesc($p['deny_gid']),
|
||||
intval($uid),
|
||||
intval($menu_id),
|
||||
intval($mitem_order)
|
||||
@@ -341,19 +340,19 @@ function menu_edit_item($menu_id, $uid, $arr) {
|
||||
$channel = get_app()->get_channel();
|
||||
}
|
||||
|
||||
$str_group_allow = perms2str($arr['group_allow']);
|
||||
$str_contact_allow = perms2str($arr['contact_allow']);
|
||||
$str_group_deny = perms2str($arr['group_deny']);
|
||||
$str_contact_deny = perms2str($arr['contact_deny']);
|
||||
$acl = new AccessList($channel);
|
||||
$acl->set_from_array($arr);
|
||||
$p = $acl->get();
|
||||
|
||||
|
||||
$r = q("update menu_item set mitem_link = '%s', mitem_desc = '%s', mitem_flags = %d, allow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid = '%s', mitem_order = %d where mitem_channel_id = %d and mitem_menu_id = %d and mitem_id = %d",
|
||||
dbesc($mitem_link),
|
||||
dbesc($mitem_desc),
|
||||
intval($mitem_flags),
|
||||
dbesc($str_contact_allow),
|
||||
dbesc($str_group_allow),
|
||||
dbesc($str_contact_deny),
|
||||
dbesc($str_group_deny),
|
||||
dbesc($p['allow_cid']),
|
||||
dbesc($p['allow_gid']),
|
||||
dbesc($p['deny_cid']),
|
||||
dbesc($p['deny_gid']),
|
||||
intval($mitem_order),
|
||||
intval($uid),
|
||||
intval($menu_id),
|
||||
@@ -388,3 +387,14 @@ function menu_del_item($menu_id,$uid,$item_id) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
function menu_sync_packet($uid,$observer_hash,$menu_id,$delete = false) {
|
||||
$r = menu_fetch_id($menu_id,$uid);
|
||||
if($r) {
|
||||
$m = menu_fetch($r['menu_name'],$uid,$observer_hash);
|
||||
if($m) {
|
||||
if($delete)
|
||||
$m['menu_delete'] = 1;
|
||||
build_sync_packet($uid,array('menu' => array(menu_element($m))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
|
||||
|
||||
// look for any existing conversation structure
|
||||
|
||||
|
||||
if(strlen($replyto)) {
|
||||
$r = q("select convid from mail where channel_id = %d and ( mid = '%s' or parent_mid = '%s' ) limit 1",
|
||||
intval(local_channel()),
|
||||
@@ -75,13 +76,16 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
|
||||
|
||||
$handles = $recip_handle . ';' . $sender_handle;
|
||||
|
||||
if($subject)
|
||||
$nsubject = str_rot47(base64url_encode($subject));
|
||||
|
||||
$r = q("insert into conv (uid,guid,creator,created,updated,subject,recips) values(%d, '%s', '%s', '%s', '%s', '%s', '%s') ",
|
||||
intval(local_channel()),
|
||||
dbesc($conv_guid),
|
||||
dbesc($sender_handle),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc(datetime_convert()),
|
||||
dbesc($subject),
|
||||
dbesc($nsubject),
|
||||
dbesc($handles)
|
||||
);
|
||||
|
||||
@@ -170,11 +174,11 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
|
||||
|
||||
|
||||
|
||||
$r = q("INSERT INTO mail ( account_id, convid, mail_flags, channel_id, from_xchan, to_xchan, title, body, attach, mid, parent_mid, created, expires )
|
||||
$r = q("INSERT INTO mail ( account_id, convid, mail_obscured, channel_id, from_xchan, to_xchan, title, body, attach, mid, parent_mid, created, expires )
|
||||
VALUES ( %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' )",
|
||||
intval($channel['channel_account_id']),
|
||||
intval($convid),
|
||||
intval(MAIL_OBSCURED),
|
||||
intval(1),
|
||||
intval($channel['channel_id']),
|
||||
dbesc($channel['channel_hash']),
|
||||
dbesc($recipient),
|
||||
@@ -212,6 +216,12 @@ function send_message($uid = 0, $recipient='', $body='', $subject='', $replyto='
|
||||
intval($channel['channel_id']),
|
||||
dbesc('<' . $channel['channel_hash'] . '>')
|
||||
);
|
||||
$r = q("UPDATE attach SET allow_cid = '%s' WHERE hash = '%s' AND is_photo = 1 and uid = %d and allow_cid = '%s'",
|
||||
dbesc('<' . $recipient . '>'),
|
||||
dbesc($image_uri),
|
||||
intval($channel['channel_id']),
|
||||
dbesc('<' . $channel['channel_hash'] . '>')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,18 +262,30 @@ function private_messages_list($uid, $mailbox = '', $start = 0, $numitems = 0) {
|
||||
);
|
||||
if(! $x)
|
||||
return array();
|
||||
if($mailbox === 'inbox')
|
||||
$where = " and sender_xchan != '" . dbesc($x[0]['channel_hash']) . "' ";
|
||||
elseif($mailbox === 'outbox')
|
||||
$where = " and sender_xchan = '" . dbesc($x[0]['channel_hash']) . "' ";
|
||||
|
||||
$channel_hash = dbesc($x[0]['channel_hash']);
|
||||
$local_channel = intval(local_channel());
|
||||
|
||||
switch($mailbox) {
|
||||
|
||||
case 'inbox':
|
||||
$sql = "SELECT * FROM mail WHERE channel_id = $local_channel AND from_xchan != '$channel_hash' ORDER BY created DESC $limit";
|
||||
break;
|
||||
|
||||
case 'outbox':
|
||||
$sql = "SELECT * FROM mail WHERE channel_id = $local_channel AND from_xchan = '$channel_hash' ORDER BY created DESC $limit";
|
||||
break;
|
||||
|
||||
case 'combined':
|
||||
$sql = "SELECT * FROM ( SELECT * FROM mail WHERE channel_id = $local_channel ORDER BY created DESC $limit ) AS temp_table GROUP BY parent_mid ORDER BY created DESC";
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// For different orderings, consider applying usort on the results. We thought of doing that
|
||||
// inside this function or having some preset sorts, but don't wish to limit app developers.
|
||||
|
||||
$r = q("SELECT * from mail WHERE channel_id = %d $where order by created desc $limit",
|
||||
intval(local_channel())
|
||||
);
|
||||
$r = q($sql);
|
||||
|
||||
if(! $r) {
|
||||
return array();
|
||||
}
|
||||
@@ -330,6 +352,7 @@ function private_messages_fetch_message($channel_id, $messageitem_id, $updatesee
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if($updateseen) {
|
||||
$r = q("UPDATE `mail` SET mail_seen = 1 where mail_seen = 0 and id = %d AND channel_id = %d",
|
||||
dbesc($messageitem_id),
|
||||
@@ -416,6 +439,7 @@ function private_messages_fetch_conversation($channel_id, $messageitem_id, $upda
|
||||
}
|
||||
|
||||
|
||||
|
||||
if($updateseen) {
|
||||
$r = q("UPDATE `mail` SET mail_seen = 1 where mail_seen = 0 and parent_mid = '%s' AND channel_id = %d",
|
||||
dbesc($r[0]['parent_mid']),
|
||||
@@ -425,4 +449,4 @@ function private_messages_fetch_conversation($channel_id, $messageitem_id, $upda
|
||||
|
||||
return $messages;
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -94,9 +94,8 @@ EOT;
|
||||
|
||||
require_once('include/chat.php');
|
||||
$has_chats = chatroom_list_count(local_channel());
|
||||
if($has_chats) {
|
||||
$nav['usermenu'][] = Array('chat/' . $channel['channel_address'],t('Chat'),"",t('Your chatrooms'),'chat_nav_btn');
|
||||
}
|
||||
$nav['usermenu'][] = Array('chat/' . $channel['channel_address'] . (($has_chats) ? '' : '/new'), t('Chat'),"",t('Your chatrooms'),'chat_nav_btn');
|
||||
|
||||
|
||||
require_once('include/menu.php');
|
||||
$has_bookmarks = menu_list_count(local_channel(),'',MENU_BOOKMARK) + menu_list_count(local_channel(),'',MENU_SYSTEM|MENU_BOOKMARK);
|
||||
@@ -172,8 +171,8 @@ EOT;
|
||||
if(local_channel()) {
|
||||
|
||||
|
||||
$nav['network'] = array('network', t('Matrix'), "", t('Your matrix'),'network_nav_btn');
|
||||
$nav['network']['mark'] = array('', t('Mark all matrix notifications seen'), '','');
|
||||
$nav['network'] = array('network', t('Grid'), "", t('Your grid'),'network_nav_btn');
|
||||
$nav['network']['mark'] = array('', t('Mark all grid notifications seen'), '','');
|
||||
|
||||
$nav['home'] = array('channel/' . $channel['channel_address'], t('Channel Home'), "", t('Channel home'),'home_nav_btn');
|
||||
$nav['home']['mark'] = array('', t('Mark all channel notifications seen'), '','');
|
||||
@@ -186,11 +185,11 @@ EOT;
|
||||
$nav['notifications']['all']=array('notifications/system', t('See all notifications'), "", "");
|
||||
$nav['notifications']['mark'] = array('', t('Mark all system notifications seen'), '','');
|
||||
|
||||
$nav['messages'] = array('message', t('Mail'), "", t('Private mail'),'mail_nav_btn');
|
||||
$nav['messages']['all']=array('message', t('See all private messages'), "", "");
|
||||
$nav['messages'] = array('mail/combined', t('Mail'), "", t('Private mail'),'mail_nav_btn');
|
||||
$nav['messages']['all']=array('mail/combined', t('See all private messages'), "", "");
|
||||
$nav['messages']['mark'] = array('', t('Mark all private messages seen'), '','');
|
||||
$nav['messages']['inbox'] = array('message', t('Inbox'), "", t('Inbox'));
|
||||
$nav['messages']['outbox']= array('message/sent', t('Outbox'), "", t('Outbox'));
|
||||
$nav['messages']['inbox'] = array('mail/inbox', t('Inbox'), "", t('Inbox'));
|
||||
$nav['messages']['outbox']= array('mail/outbox', t('Outbox'), "", t('Outbox'));
|
||||
$nav['messages']['new'] = array('mail/new', t('New Message'), "", t('New Message'));
|
||||
|
||||
|
||||
|
@@ -1035,7 +1035,7 @@ function discover_by_url($url,$arr = null) {
|
||||
dbesc(datetime_convert())
|
||||
);
|
||||
|
||||
$photos = import_profile_photo($photo,$guid);
|
||||
$photos = import_xchan_photo($photo,$guid);
|
||||
$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]),
|
||||
@@ -1053,16 +1053,20 @@ function discover_by_webbie($webbie) {
|
||||
|
||||
$webbie = strtolower($webbie);
|
||||
|
||||
$x = webfinger_rfc7033($webbie);
|
||||
$x = webfinger_rfc7033($webbie,true);
|
||||
if($x && array_key_exists('links',$x) && $x['links']) {
|
||||
foreach($x['links'] as $link) {
|
||||
if(array_key_exists('rel',$link) && $link['rel'] == 'http://purl.org/zot/protocol') {
|
||||
logger('discover_by_webbie: zot found for ' . $webbie, LOGGER_DEBUG);
|
||||
$z = z_fetch_url($link['href']);
|
||||
if($z['success']) {
|
||||
$j = json_decode($z['body'],true);
|
||||
$i = import_xchan($j);
|
||||
return true;
|
||||
if(array_key_exists('zot',$x) && $x['zot']['success'])
|
||||
$i = import_xchan($x['zot']);
|
||||
else {
|
||||
$z = z_fetch_url($link['href']);
|
||||
if($z['success']) {
|
||||
$j = json_decode($z['body'],true);
|
||||
$i = import_xchan($j);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1137,6 +1141,8 @@ function discover_by_webbie($webbie) {
|
||||
if($hcard) {
|
||||
$vcard = scrape_vcard($hcard);
|
||||
$vcard['nick'] = substr($webbie,0,strpos($webbie,'@'));
|
||||
if(! $vcard['fn'])
|
||||
$vcard['fn'] = $webbie;
|
||||
}
|
||||
|
||||
$r = q("select * from xchan where xchan_hash = '%s' limit 1",
|
||||
@@ -1192,7 +1198,7 @@ function discover_by_webbie($webbie) {
|
||||
dbescdate(datetime_convert())
|
||||
);
|
||||
}
|
||||
$photos = import_profile_photo($vcard['photo'],$addr);
|
||||
$photos = import_xchan_photo($vcard['photo'],$addr);
|
||||
$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'",
|
||||
dbescdate(datetime_convert('UTC','UTC',$arr['photo_updated'])),
|
||||
dbesc($photos[0]),
|
||||
@@ -1280,7 +1286,7 @@ LSIeXnd14lQYK/uxW/8cTFjcmddsKxeXysoQxbSa9VdDK+KkpZdgYXYrTTofXs6v+
|
||||
}
|
||||
|
||||
|
||||
function webfinger_rfc7033($webbie) {
|
||||
function webfinger_rfc7033($webbie,$zot = false) {
|
||||
|
||||
|
||||
if(! strpos($webbie,'@'))
|
||||
@@ -1290,7 +1296,7 @@ function webfinger_rfc7033($webbie) {
|
||||
|
||||
$resource = 'acct:' . $webbie;
|
||||
|
||||
$s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?resource=' . $resource);
|
||||
$s = z_fetch_url('https://' . $rhs . '/.well-known/webfinger?f=&resource=' . $resource . (($zot) ? '&zot=1' : ''));
|
||||
|
||||
if($s['success'])
|
||||
$j = json_decode($s['body'],true);
|
||||
|