Compare commits
2799 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6859053727 | |||
| 8c207cf1eb | |||
| bce8c2ee5a | |||
| e1922bd555 | |||
| fc9a901c4c | |||
| 6f93d9848c | |||
| bde429cff6 | |||
| 4c8d33d1eb | |||
| fac7826efa | |||
| 3e133bbfa3 | |||
| 6c8d1bdffe | |||
| 59fc495593 | |||
| 60827bdcc4 | |||
| f992feb71c | |||
| cf66e66db8 | |||
| 63aa3948e5 | |||
| 7899ed6f69 | |||
| 5e44239657 | |||
| 17cd452fff | |||
| 004861fbb7 | |||
| 8727f12b18 | |||
| 05604e4bd2 | |||
| fd7d497cd1 | |||
| a974d0d52d | |||
| c850a61a89 | |||
| 3a2fdec241 | |||
| 08b804cd2d | |||
| de7891771d | |||
| 602768209b | |||
| 73b1f8fcdd | |||
| e1b923ab7d | |||
| bed9876d68 | |||
| d184e2708f | |||
| 580c3f4ffe | |||
| 158b8aea38 | |||
| d22766f458 | |||
| 70391243dc | |||
| 61eef68ff3 | |||
| 41cc2854c5 | |||
| 478014f02a | |||
| aff7c2d771 | |||
| 00dd52317a | |||
| 17522b31e9 | |||
| 163b1ee9f8 | |||
| 7b9a992f83 | |||
| 4efb258671 | |||
| 7532358806 | |||
| 13c05e7937 | |||
| c6e9bca76c | |||
| 3706afbd01 | |||
| bcd0802ea4 | |||
| 9360148829 | |||
| a6165c00ce | |||
| a5826fec25 | |||
| 839c6668cf | |||
| e9a9fc5050 | |||
| 426668cd2e | |||
| 926d7c56a6 | |||
| 9934dbfe69 | |||
| b6314c109d | |||
| f8955f90b8 | |||
| 9248fc96b3 | |||
| 2875ee2423 | |||
| 36f707b25e | |||
| 2a05bd9ed6 | |||
| b7db9944ec | |||
| 86f7d08483 | |||
| 1358a81c32 | |||
| 09ad48c12b | |||
| aa137fb2d2 | |||
| 09284d512d | |||
| 02fd7e51ff | |||
| b359b89aa1 | |||
| 873b20677e | |||
| a049664219 | |||
| 64c6e25896 | |||
| 9f9122ab8e | |||
| d0661cd4a3 | |||
| 707b19dc35 | |||
| 6fd15d66a7 | |||
| 8c9a814e18 | |||
| 74ef5f38e9 | |||
| 624a3ee1a7 | |||
| fc658a25d7 | |||
| 308619a726 | |||
| e87d8d9856 | |||
| 7594264725 | |||
| 69533ce8f5 | |||
| 9fac43a3a3 | |||
| 972270ff3e | |||
| b00db39739 | |||
| 6f2a584279 | |||
| de717268f7 | |||
| e27b19c756 | |||
| 045cb461f1 | |||
| 088c0eedc6 | |||
| e5137b03fc | |||
| 76d34a4d74 | |||
| a3f7121a3a | |||
| ae4f0e5728 | |||
| 5df59027ad | |||
| c888e33f04 | |||
| 1a56ecaa39 | |||
| d778c3cf19 | |||
| 8bf57c6226 | |||
| 3c762b8809 | |||
| 3561fd7c43 | |||
| 66bfc0ec64 | |||
| 7d0e576e3b | |||
| a65453676f | |||
| aa330bc8c7 | |||
| b4de492e0d | |||
| 5bf3114e6f | |||
| 1fc82c5daf | |||
| d2b1a2e5a3 | |||
| 4b01f6359b | |||
| bcfa62f45a | |||
| e7e8a2ca5f | |||
| 5edeb0250b | |||
| 0c2657df78 | |||
| e4c57e8031 | |||
| 6a25548097 | |||
| db7cbdfc44 | |||
| 2f26badb84 | |||
| f7e665c42f | |||
| 3bc44ee451 | |||
| 125de855ef | |||
| 3881ebcce0 | |||
| ca50e9e6d6 | |||
| bef5324fea | |||
| c2655370e0 | |||
| d017e34795 | |||
| aa44da35ba | |||
| 5c4c6e68f6 | |||
| a435363b94 | |||
| d6634eb14e | |||
| afee2cf71a | |||
| 79b0a6ba9c | |||
| 0c2438b36a | |||
| d6da46f94b | |||
| 562e39c9c5 | |||
| 2d08e0955a | |||
| baffa969d3 | |||
| 1fbc8739b9 | |||
| b9dec84489 | |||
| 6feb864c38 | |||
| b6db1898b1 | |||
| de902d179e | |||
| 58b77e3427 | |||
| cdcac86256 | |||
| 79b05e48e8 | |||
| 541146e8ce | |||
| 97b161c536 | |||
| ba3a6ecb52 | |||
| cf27b7440d | |||
| 407b9c9cd7 | |||
| d0055310ba | |||
| 02f5fa32af | |||
| b6590e95b5 | |||
| 4f9f5ac3e6 | |||
| ec65211d54 | |||
| 8dfa08f146 | |||
| daef2d0546 | |||
| 15eaa80301 | |||
| 1e924a8530 | |||
| 23995ccb07 | |||
| a4f2603454 | |||
| cc860b4a76 | |||
| 0be82602ce | |||
| b42c42692e | |||
| 7fcbff3ceb | |||
| efec0af394 | |||
| aafecd9d1e | |||
| e37c43ea06 | |||
| 3fac7b5bb7 | |||
| 9b90114d03 | |||
| 7c5cfe6697 | |||
| d1fd69337f | |||
| 3fc218111a | |||
| c63fb0fc6b | |||
| 6fe4ac241d | |||
| c385b80807 | |||
| 97f36fa46f | |||
| 856d4b39d1 | |||
| 01abd73a2a | |||
| 375c2a87c7 | |||
| 6ca507f8dd | |||
| 86b4a53858 | |||
| 9a61b7682b | |||
| 8959ba9b82 | |||
| a62a230d3d | |||
| cc45129e9f | |||
| bffc9d5aba | |||
| f2b121cd58 | |||
| c1e22f9e86 | |||
| e6e49ae3f7 | |||
| fd30be7644 | |||
| 4b191b9cc7 | |||
| efbe737439 | |||
| 172fe3d7ff | |||
| 5dc70562bf | |||
| a598e1fc2c | |||
| d9052c7e3c | |||
| dcfe10b691 | |||
| 914a096b42 | |||
| 5fa9dcbc7e | |||
| 93ec01e0a1 | |||
| bbc98db6b4 | |||
| 1f8d29a221 | |||
| d267dd2515 | |||
| 51954c7f3d | |||
| df842a8e8d | |||
| 60919488f1 | |||
| 4dbaaa63bb | |||
| 8cc4003837 | |||
| 35790c584b | |||
| 09d7cf2cc1 | |||
| 58d7c7f6ae | |||
| cab24836d8 | |||
| cf9ef615c9 | |||
| 8c96032b2b | |||
| d256551907 | |||
| e800e2db2b | |||
| ae09281bb8 | |||
| 9a776b3cdf | |||
| 63d7bfde81 | |||
| cc9f41df5f | |||
| bb3784d8dd | |||
| e5539c0d01 | |||
| c997360b4a | |||
| ea8621d6ec | |||
| 88fa18204f | |||
| ac05a2ede7 | |||
| 808baf203d | |||
| beeafc6bc5 | |||
| 6f8c977e73 | |||
| 9a2fbdde20 | |||
| b325b2c003 | |||
| feda23587c | |||
| e8f3b7f853 | |||
| e28341ca4b | |||
| 6c11a020ee | |||
| 7200c2ac0c | |||
| 732ca49b02 | |||
| ee976ed460 | |||
| 06ac3e896a | |||
| 6ce0f6e806 | |||
| e006586275 | |||
| e9d6b17a00 | |||
| bf2f199f37 | |||
| 718ca548be | |||
| 51c0dc070a | |||
| d5e0d52bc4 | |||
| f6b99db738 | |||
| ef69294072 | |||
| c56d395c90 | |||
| 778e9141d8 | |||
| c70a4662b4 | |||
| e441a31051 | |||
| 9f5ec5cc50 | |||
| 825ded2e08 | |||
| a7c3776557 | |||
| 1e7cfc2644 | |||
| c6fd32ffde | |||
| 5f551a8b47 | |||
| f73ff57148 | |||
| c538d7372e | |||
| 4e7804ca75 | |||
| 8fe715983a | |||
| 4a3fb07d5f | |||
| f5062c0507 | |||
| f0d7a17b72 | |||
| b89d2d7580 | |||
| 7a7f57fa45 | |||
| 047dd31724 | |||
| 0ce1a200f7 | |||
| 0e0024218f | |||
| 4886d088e9 | |||
| 6eec6e2d65 | |||
| 6c12880f5b | |||
| eb472111a8 | |||
| 8d8b7ed567 | |||
| 681dc70205 | |||
| 130cfbf231 | |||
| 940e4a6152 | |||
| 38f7d9ad37 | |||
| e896d316f2 | |||
| af690b64d6 | |||
| 699aad8626 | |||
| 4382e53acb | |||
| 832adf92a6 | |||
| 33e2582918 | |||
| 1c2f413211 | |||
| 2300581c93 | |||
| 03c4fba730 | |||
| 75a8b209f5 | |||
| d554b41fea | |||
| b0db1f827e | |||
| 3070baf04e | |||
| 72629ca511 | |||
| 1c39fc71d9 | |||
| 0bb59b66be | |||
| 31b177f8ad | |||
| 8ee5ced08d | |||
| c96a1632f5 | |||
| b3b2649814 | |||
| 95805d2e7c | |||
| d4b92141fd | |||
| 829e915c90 | |||
| aaffc7485d | |||
| 9ea1d6e8af | |||
| 17661b4b5f | |||
| 32874b89ca | |||
| d4a038c437 | |||
| 59fed33797 | |||
| feea137dbf | |||
| 70e4a2c4fa | |||
| 696359daba | |||
| 5695350e98 | |||
| 4e3a0720c3 | |||
| dc56d8560d | |||
| 81ecea29c8 | |||
| ad58697521 | |||
| 6ca7527ec9 | |||
| 8ced3699c2 | |||
| c4de5b45df | |||
| 71056e1db1 | |||
| f94faeeace | |||
| 80f56a1315 | |||
| 485f5a07ed | |||
| 821af482f0 | |||
| b2d1fadf66 | |||
| 3b73e5223e | |||
| 6a964e7caf | |||
| a6f06c2d94 | |||
| a85f0a93c6 | |||
| 250387c7e5 | |||
| dde7144f5a | |||
| 68733a2bc0 | |||
| b2d3a11de8 | |||
| a024e4c10a | |||
| db6e4d1c32 | |||
| 8393c382c3 | |||
| 5c0e3688fe | |||
| 1e6c07246e | |||
| e5370971d6 | |||
| 090d921006 | |||
| 39c0a7525b | |||
| 407b02bde8 | |||
| da7912b879 | |||
| 02c08aed12 | |||
| 87668f7fa8 | |||
| 001734a725 | |||
| 276ab3eae3 | |||
| 1b976f30f3 | |||
| 019afe2a1a | |||
| 37ebcd3b4f | |||
| 5ad6eeccdf | |||
| 65cd33cb15 | |||
| 4aa59226d7 | |||
| d53c98860d | |||
| d022e1acce | |||
| 98100520eb | |||
| 42526fc2dc | |||
| 9c76afa2a3 | |||
| 943db4496b | |||
| 4a77b6673b | |||
| 62b31b1e4a | |||
| ddde4e1965 | |||
| 96a99935ef | |||
| 60c003733e | |||
| 9def9a5cb7 | |||
| 145295302d | |||
| 302d2dbd51 | |||
| 49ba3ffee6 | |||
| d83ce0863a | |||
| cf844cb27c | |||
| 5ccef18d4e | |||
| 40bbdfdf6a | |||
| ad8ad0ccd7 | |||
| 1cf012650b | |||
| 4f280b5497 | |||
| 5ee7009271 | |||
| 07f850ed15 | |||
| dde0c41c84 | |||
| 1b6fbe3a2e | |||
| b1b415ec5b | |||
| 8730bbac2f | |||
| e8918ca149 | |||
| 82478eef09 | |||
| 892e9cd835 | |||
| 3dd6499ac4 | |||
| 037da34e5d | |||
| ad30d35663 | |||
| 8d70b3b79e | |||
| 109c66aea3 | |||
| 24b0f8e27e | |||
| 1a76e83fa4 | |||
| 2fa788b01b | |||
| 028cbdcffa | |||
| 8aefbd911b | |||
| f37387de80 | |||
| 4f705fc3f8 | |||
| 5b727065cf | |||
| 952e466d91 | |||
| c1cc76119c | |||
| 9d156141b1 | |||
| 8c92b0cd3a | |||
| dd515da889 | |||
| 2862b69d56 | |||
| db8e46184b | |||
| 99a7cd3cfb | |||
| 75746d714a | |||
| 983d6d3b42 | |||
| 060dd8b020 | |||
| b5be0a2e3e | |||
| 46a687b0a6 | |||
| 4ff7aa4352 | |||
| 750d1f820d | |||
| f046a34d34 | |||
| 0d165920bb | |||
| 9e3a4402e0 | |||
| 34d7aea1be | |||
| e2abc0b727 | |||
| a677a68ab7 | |||
| df228237de | |||
| fc2a038ee1 | |||
| 619b39f955 | |||
| becaa3b920 | |||
| c0b9ab930d | |||
| f106b1db15 | |||
| 958217dd55 | |||
| 2f80fdae97 | |||
| 9507f191b0 | |||
| 92f5d8c8be | |||
| 8535eb7bf5 | |||
| c9604eaabf | |||
| 3bc214e544 | |||
| 43cec4398d | |||
| 335394aaa1 | |||
| c9615cc19c | |||
| 5315d8fe3f | |||
| 75dedb3345 | |||
| 134dfb8804 | |||
| 86f4a8d33a | |||
| abeb924554 | |||
| 4da3933f24 | |||
| c5703306ef | |||
| a26774b99e | |||
| 9258593776 | |||
| 48604041e8 | |||
| 110af3b524 | |||
| 57ed9ec8e2 | |||
| 5434b53a99 | |||
| f4361818e0 | |||
| 801ab611ed | |||
| bc34167c84 | |||
| decd0dc035 | |||
| 9ac9c693ad | |||
| 9b2cd69c0f | |||
| b3f1a19db6 | |||
| f3b6708a92 | |||
| 99cdc7af32 | |||
| 8848885d9a | |||
| c1cab6789e | |||
| 907777eeb0 | |||
| 7889612edc | |||
| e81e264988 | |||
| eacc29ded0 | |||
| ea04c93bfd | |||
| 8692977585 | |||
| 6a40f3ed60 | |||
| dd1f631d9d | |||
| 15874ac45c | |||
| 761fc74a67 | |||
| 0e2239e50b | |||
| e9a17517d3 | |||
| 94254e61c1 | |||
| 32eb81d4ae | |||
| 6f7e38b94c | |||
| 87f271af29 | |||
| ff74310e32 | |||
| a181fa2992 | |||
| 76e879e5de | |||
| c01ab3ed39 | |||
| 9f403a4d6b | |||
| 55792d5528 | |||
| a3f726baa8 | |||
| ebc2b23c3a | |||
| e4ca3609d9 | |||
| bc092d8d78 | |||
| dd5933b048 | |||
| 5d6128b25c | |||
| 24cb04c346 | |||
| f1b54cf0a4 | |||
| e64a7b87a8 | |||
| 2b452ea3e8 | |||
| 66c6c6c7d1 | |||
| 5b4aa1afc2 | |||
| 89205276ab | |||
| 6d2ab6a7d6 | |||
| e6da910ee2 | |||
| 2100ac3cfc | |||
| c7476a1d96 | |||
| d8c3033941 | |||
| 7e26ee5a73 | |||
| a8e25ccfe6 | |||
| b6267ec7c2 | |||
| b6bd2884d5 | |||
| 767a235611 | |||
| 620fc06b6c | |||
| 0fa4c89a1b | |||
| 1bf046c142 | |||
| 52f8429218 | |||
| 932b414063 | |||
| 097b2390db | |||
| ca8d252ad7 | |||
| 23a0dbe3cc | |||
| 545ece82b3 | |||
| eaea947b74 | |||
| f1b61d5882 | |||
| e466d72058 | |||
| 385be35ed5 | |||
| 528b9b6a60 | |||
| dd374eaebf | |||
| 9ea483d1dc | |||
| d8a396bf24 | |||
| b1813df61a | |||
| 8715f74d29 | |||
| 152224944b | |||
| f86d12c8f4 | |||
| 94d4bc4bac | |||
| c95488549d | |||
| 39613aa2d9 | |||
| 7c2aafd4ee | |||
| e834c7fe3e | |||
| f96958adf8 | |||
| 776074b24f | |||
| c9d64d75f3 | |||
| 9651689bb8 | |||
| 75be0475ba | |||
| e130b58b20 | |||
| e44f0c497f | |||
| 2d0f96d28b | |||
| 34d1f79777 | |||
| 2185ccd4ea | |||
| 125634759d | |||
| 350e636e3d | |||
| 429140df97 | |||
| a921deafd1 | |||
| 071fba2f71 | |||
| 9de729e3e7 | |||
| 7cf5bd30f2 | |||
| e6cee2965a | |||
| af2b263bc7 | |||
| aa120e0478 | |||
| b07c55a0d9 | |||
| e7f1f496c5 | |||
| 823c0434eb | |||
| 22162635e7 | |||
| 8be0031602 | |||
| 29c5e74d31 | |||
| 3c8867a1e8 | |||
| c439fe0437 | |||
| b21db670b4 | |||
| 1f84aa9809 | |||
| 4ac249c26c | |||
| 85a29fce94 | |||
| 71ecb470b6 | |||
| 15a000bb45 | |||
| 18e4a7ac6e | |||
| d0322f5fbd | |||
| c1f01b7e35 | |||
| 71064f481b | |||
| 436293713b | |||
| fc726bfb4b | |||
| b0c3780667 | |||
| 3e431c65be | |||
| 5b0b90d1f5 | |||
| d16714e84b | |||
| 1d5fff9f58 | |||
| fbe8d6144a | |||
| d5f59a57bf | |||
| 7465c79884 | |||
| 769195fcff | |||
| dc786bd1cc | |||
| 960f4ed649 | |||
| 91ad3bf1b6 | |||
| 91b495d526 | |||
| 973d91d120 | |||
| bf5deace8e | |||
| 0e4acf6299 | |||
| a5cd0061c5 | |||
| 630e3903fa | |||
| 0b6a5fad70 | |||
| 67ca1b82cc | |||
| 9866053f0c | |||
| 89a2c1a09c | |||
| 70220d8b9c | |||
| 274f69526f | |||
| d7026fe36b | |||
| b9b65d7dfb | |||
| 1545c78d05 | |||
| f0c292e77b | |||
| 62336127e3 | |||
| 5beaf8ac98 | |||
| 9efd484e27 | |||
| 44d5cf980a | |||
| e53650d6c6 | |||
| 5bf9a9828c | |||
| 24f3bc9f0c | |||
| c200e55f95 | |||
| ea19d59fca | |||
| d34d14c1f4 | |||
| 7b17306dbd | |||
| 6731564c2d | |||
| 194ba0cf8d | |||
| 6fc2429540 | |||
| bdcbe61273 | |||
| de5d7bfbd3 | |||
| 242878c45c | |||
| c0911da887 | |||
| 6e0bf04276 | |||
| 56c460d932 | |||
| f0933b66a9 | |||
| 422d633f89 | |||
| 0537be129c | |||
| 9b947c8370 | |||
| 14eb4326e7 | |||
| 89a3e8fcc7 | |||
| 6fd5133bed | |||
| e010877490 | |||
| f56371c79b | |||
| c98f3c5d29 | |||
| 5c8de9d82f | |||
| b9c8b6ba23 | |||
| 6cd968b53b | |||
| 2aa76d257c | |||
| 32c0be8bde | |||
| 88d283a89d | |||
| 66b370c421 | |||
| 20bf139b3f | |||
| 1da4602567 | |||
| e7ef69e6e7 | |||
| d55904d4db | |||
| 740dc59255 | |||
| 98b6362c07 | |||
| cd829c096b | |||
| f127c55802 | |||
| 13247a0e00 | |||
| 609752d331 | |||
| 413410d02d | |||
| 3528610a51 | |||
| 59ee045c24 | |||
| b1dec12893 | |||
| 319b0acdd8 | |||
| c605c46f83 | |||
| 9ef692b48c | |||
| 6da4dfe605 | |||
| 7b4cb31a10 | |||
| 03ce4d7e2b | |||
| f55f5fa92a | |||
| 76757ad1f2 | |||
| 347e88dc65 | |||
| 746d032e58 | |||
| b6d598a001 | |||
| b35961c53c | |||
| 47fba5827b | |||
| 47f75ad8bf | |||
| 516167c0f8 | |||
| 238b3a97a8 | |||
| d4ab8a5a5d | |||
| 6672299f8a | |||
| ea5f515f18 | |||
| ea6293544d | |||
| cbe35281b9 | |||
| 51a0fc45e2 | |||
| 1e7e2bd34f | |||
| fa2f3d136f | |||
| 92b6026695 | |||
| c9a5f21344 | |||
| 0174bf3722 | |||
| 0d003e7450 | |||
| 8847838c43 | |||
| 9594ce9a8a | |||
| 4a91d09c86 | |||
| 06837bd32b | |||
| b8d8887d5a | |||
| 256f8dd41b | |||
| e0fdafc7e5 | |||
| 9a55df245f | |||
| 9800d95c50 | |||
| c340416c94 | |||
| 9af8a1d30c | |||
| 4da96ee980 | |||
| 21637e033c | |||
| 9ebf2dc97b | |||
| a04689b784 | |||
| 5066945adc | |||
| e945c12856 | |||
| 0b062d0b8a | |||
| 9cc1eff15c | |||
| 327e5d06e1 | |||
| a2dd0aea92 | |||
| 39da3459c7 | |||
| c0be4c36e1 | |||
| 31e04378cd | |||
| e80c99ad74 | |||
| d9be443e53 | |||
| 6db323b15e | |||
| 5abbfd3f19 | |||
| 674215e9e6 | |||
| dce6a5763d | |||
| d89d6e8a01 | |||
| 6230dbed2d | |||
| 9641254443 | |||
| 95871fe13c | |||
| 0cecfceb14 | |||
| b9f1cb2021 | |||
| 3f208d806c | |||
| ba9ea3f02a | |||
| 13970280d9 | |||
| 55ce80aabe | |||
| 9536a490b3 | |||
| 405e07f0a2 | |||
| d3ce91bd89 | |||
| eb44201c5f | |||
| 73248aadd5 | |||
| f6a4084f81 | |||
| d5f89c165a | |||
| a518471a27 | |||
| dce5080e53 | |||
| 2221d4d612 | |||
| 5f73a46c05 | |||
| b782c6bd16 | |||
| ab8d8aa552 | |||
| f955276694 | |||
| 77cc60faf2 | |||
| a6f50b8c85 | |||
| e2dfa1d72f | |||
| 9a61c0a6fc | |||
| e10b25a12c | |||
| 0c1e803208 | |||
| b57dcc74d1 | |||
| f8c583636c | |||
| e6521d1cf3 | |||
| 96785e8df1 | |||
| d689778465 | |||
| 3c8f8b76aa | |||
| c123fa5422 | |||
| 0ade8be7f7 | |||
| a60c2f38c6 | |||
| f1c0797780 | |||
| 701167bc12 | |||
| a39e63e324 | |||
| 8401e9c2b4 | |||
| c5fca0a1e7 | |||
| e779335d06 | |||
| 26039adf5b | |||
| c88286556a | |||
| 831b9d4433 | |||
| e937e8fff9 | |||
| f616b2d49a | |||
| fe84dae313 | |||
| 9104933b18 | |||
| 79654635d3 | |||
| f0edfca75c | |||
| e845da2edc | |||
| 7a3050f2c0 | |||
| 9a6531e2a2 | |||
| a6a17a85f3 | |||
| 9275fd16c2 | |||
| 904ae05810 | |||
| 54f95389a8 | |||
| a8fc70a5b9 | |||
| c374072822 | |||
| 0212de68a4 | |||
| 2ea9b6d409 | |||
| 823d71df28 | |||
| 7560918b32 | |||
| fd87faa7a6 | |||
| cb2d706fa1 | |||
| 6b638ac896 | |||
| 2bd5ae3617 | |||
| 39a5311315 | |||
| 9b6e46dc6b | |||
| 7311d1182d | |||
| ea1d8b8104 | |||
| fb03e3f00e | |||
| c9c35255e7 | |||
| 99a578dbad | |||
| e56c0a6251 | |||
| 66479e2aa7 | |||
| 6feddcbced | |||
| db020ca1a3 | |||
| 6c93518ef7 | |||
| eb02d01eed | |||
| 7a9093f634 | |||
| d55f691ec0 | |||
| f222030edb | |||
| 5f691fb05c | |||
| 1732b2dfe3 | |||
| a62f891a60 | |||
| a22ecd42ed | |||
| b7cb2a2951 | |||
| c490970324 | |||
| 5a9c8a9343 | |||
| 5ba7e5d7d7 | |||
| f7b281a65f | |||
| df5a1c59e6 | |||
| 0615709a7a | |||
| d85a0130b7 | |||
| 71f17a233e | |||
| 25c35cbbe4 | |||
| 257ba570ee | |||
| 91e96b2314 | |||
| c2ee7cbff5 | |||
| 27f813e043 | |||
| 00ed91f12e | |||
| 4cb5efc277 | |||
| 65a453d21b | |||
| 9c8cb4dea3 | |||
| ed902fdb70 | |||
| 509067391b | |||
| 04b261057d | |||
| 852343f254 | |||
| 26e35344d0 | |||
| d3a619659f | |||
| 979f2415fb | |||
| 28c1d219f6 | |||
| 5792f4bf07 | |||
| 3a0fa5cb29 | |||
| 074ee656f0 | |||
| 064f93185c | |||
| 4b5922f652 | |||
| 85be906b68 | |||
| 775285cdf8 | |||
| 42f96dc7a6 | |||
| e96fa64625 | |||
| 8dc495c9bc | |||
| 5d70d889e9 | |||
| 999ae6eb49 | |||
| ae1450bbcf | |||
| dcd8a05809 | |||
| 62e466f774 | |||
| 70777a047d | |||
| 47fd95db9d | |||
| 7602d9e54b | |||
| 1ed0079882 | |||
| b026be410c | |||
| 767a1711ff | |||
| a93bd8d944 | |||
| 4e12f86e90 | |||
| 3007009fab | |||
| 2d886b65ce | |||
| 8700b87030 | |||
| 5a46f1229d | |||
| 9d5f8883a7 | |||
| 8e0b9b82e9 | |||
| ea4b4ddce4 | |||
| bd95c7b82a | |||
| e20c5cf9cf | |||
| 6adb489cb3 | |||
| 0c2db1cea5 | |||
| e33604887b | |||
| 410f37df1b | |||
| c9f3883c8c | |||
| 4346d7605d | |||
| a0a2c27973 | |||
| 3fb87ee76e | |||
| 242aeea24c | |||
| c305dc8d22 | |||
| f61b898633 | |||
| 2bdcd436bb | |||
| a1bea7d7cc | |||
| b2bdc73164 | |||
| cbaf0a3864 | |||
| 103563b375 | |||
| 595429fdde | |||
| b384b27546 | |||
| 0b996245d5 | |||
| 1ee91dd690 | |||
| f9e602c44c | |||
| 4fa827ddfd | |||
| 1b3c73618c | |||
| 7b08f1cc8c | |||
| 7d392e5adb | |||
| f44cc2b60c | |||
| 31680898e3 | |||
| 318fd7c9e3 | |||
| b10b8ca3f4 | |||
| b0c33308be | |||
| 1421c4e9d3 | |||
| f55dfc9025 | |||
| c218970890 | |||
| bd27ce2520 | |||
| 44795b65f9 | |||
| af84c4e6bd | |||
| 0a28207200 | |||
| 8ca2a5832c | |||
| 333534dfe7 | |||
| d8ce0d0df0 | |||
| 28c3259449 | |||
| 0d0ede7b14 | |||
| 9ebf6bcc92 | |||
| 9d186e9ba3 | |||
| 3c3a4526bf | |||
| 3094c2ce17 | |||
| 393494a728 | |||
| d2725c3f49 | |||
| 4d4425a5bf | |||
| c11fbe0868 | |||
| c676689df0 | |||
| 0f5625d721 | |||
| 6f5e6bd0f1 | |||
| a0af092ecb | |||
| 3a07a194ab | |||
| 682ffa7cf5 | |||
| dc4a4ca9d3 | |||
| 3c2b6ce112 | |||
| f8b3a395fb | |||
| 087b45ab90 | |||
| 33ac85f637 | |||
| efd9421dc9 | |||
| 9b696a872b | |||
| aab515b16c | |||
| f220628354 | |||
| 322bc5dc87 | |||
| 75c3bda866 | |||
| b2b776169b | |||
| 8e8d7ae614 | |||
| fa1af5a2cb | |||
| a27e4072b4 | |||
| fad26a49be | |||
| 1742159345 | |||
| ed8d2cb482 | |||
| 8e1f022810 | |||
| 4c25072c18 | |||
| 564ec32520 | |||
| a743feb040 | |||
| b028667de1 | |||
| 41888f84bc | |||
| 6a918dbde9 | |||
| 578230e32c | |||
| d486b03089 | |||
| 8559334339 | |||
| 968c6ed8be | |||
| 8893d9edc4 | |||
| 43753ec113 | |||
| 2ec3e4a912 | |||
| a086745ec0 | |||
| 51156d0582 | |||
| ea9925f489 | |||
| 026b96b8f2 | |||
| 136b2ae37f | |||
| 97009a2748 | |||
| e123f7c743 | |||
| e28bde6ccd | |||
| a976f418e3 | |||
| 3c701e780c | |||
| 769dd174bd | |||
| e92514ee63 | |||
| 8ebc517b41 | |||
| 91b03e52f1 | |||
| a22406c9f8 | |||
| ebc3666c6f | |||
| f1fee1239b | |||
| 8769fa0156 | |||
| f4d7338687 | |||
| 6a8c3f82ef | |||
| 05bcbfa28c | |||
| 6a55500c1b | |||
| a5a5ac60ba | |||
| 6ed7f47b3f | |||
| a3e94855f9 | |||
| 503da97a79 | |||
| 088a93e023 | |||
| 30f71ad632 | |||
| 0026849821 | |||
| cf5a310286 | |||
| 72384ff2cb | |||
| c33ef01af8 | |||
| 11116bdcb7 | |||
| 09a5cf4e68 | |||
| a9172129d2 | |||
| 3ec06705ca | |||
| 5fb0d38ad8 | |||
| 9ed5cddb89 | |||
| 4e97fb0e58 | |||
| 1688e373bc | |||
| cada0b6df1 | |||
| 91358010a0 | |||
| 51024d3821 | |||
| b329d998ca | |||
| 482f1dba27 | |||
| 23fc7e65d4 | |||
| 8f594ad6d9 | |||
| d8d46039a2 | |||
| 19e1325604 | |||
| 220d6ed494 | |||
| b5ed3edc8f | |||
| 9772726065 | |||
| 8ecdde6cb5 | |||
| 73c96f35c1 | |||
| 5b3824917d | |||
| ca4f10dc5e | |||
| 853fb33913 | |||
| e352cfc861 | |||
| b8d79d9132 | |||
| 507c71f64c | |||
| ce0067d8eb | |||
| c0b238b19a | |||
| d961cf21fb | |||
| 1f7622e4c4 | |||
| b019ca0746 | |||
| 04fe7e61de | |||
| beb4e00afb | |||
| 3e6607585f | |||
| 0b2213dd41 | |||
| 9450305568 | |||
| 08725c44c6 | |||
| e18c64c9d9 | |||
| 7b018c60cb | |||
| a81286c795 | |||
| 75a66b716e | |||
| 0c05e6593e | |||
| 571e9bf26a | |||
| c4714e95b6 | |||
| c43ab50d66 | |||
| 0d283b2666 | |||
| 26e7da0b96 | |||
| 98b1c7a38c | |||
| d407e5556e | |||
| 6a3cfe54af | |||
| a0bffe4a78 | |||
| 336c716a44 | |||
| ccdbec619c | |||
| 47001c3303 | |||
| 8e50fecccc | |||
| 938fcdd1a6 | |||
| 9ede57b228 | |||
| 8810658858 | |||
| e074d02714 | |||
| e26de9c1d1 | |||
| 7dc3835a54 | |||
| 117a8cafca | |||
| 337dfd5ee4 | |||
| e37c9ed0a1 | |||
| aa6a31eba5 | |||
| 8a0a0aef5c | |||
| 4750e15c20 | |||
| 747ce9b1f1 | |||
| 7fa874d9ef | |||
| 5febc3e07d | |||
| 2244bf2ba2 | |||
| 29cb62af3d | |||
| 027847a663 | |||
| 8134ba1faf | |||
| d30748f1de | |||
| 6aa041b193 | |||
| 0fdc0a01d0 | |||
| de7f2eef47 | |||
| a449ffe49d | |||
| 08cacc4943 | |||
| 04b9216758 | |||
| 1ff97754af | |||
| 20e43311db | |||
| 89bcb1de42 | |||
| 7a1a44f802 | |||
| e9edec0875 | |||
| 06aa32db22 | |||
| 6f8593cf47 | |||
| 3b2efb1000 | |||
| 87482e3746 | |||
| ef6a280019 | |||
| 326ae05b06 | |||
| 3f13c85b64 | |||
| 1ae7bd6477 | |||
| c91641aa83 | |||
| f92d2e3f7c | |||
| 3e2489465f | |||
| a5bf32a97d | |||
| 8bb2d29a8d | |||
| a9b75d059b | |||
| 938e8110ca | |||
| 93039081d5 | |||
| 3d253309b7 | |||
| 301c1861f3 | |||
| a3a90ea09b | |||
| e6f289deb6 | |||
| 0e22618d93 | |||
| a0ad110cff | |||
| 89ee28f858 | |||
| 5917786296 | |||
| 7f1e0313a0 | |||
| c89be96209 | |||
| fcd6c3065e | |||
| a700ef5e24 | |||
| 3a6ea57d2c | |||
| e960bcfd1c | |||
| 65e8ed6871 | |||
| a77d7b8442 | |||
| 51e9f302b0 | |||
| 72fd1cc5a6 | |||
| 1a77bdd1d0 | |||
| 1ea9002fe8 | |||
| 7d1c3920fd | |||
| c5bb074573 | |||
| cead10b9af | |||
| 382e94e282 | |||
| 7e8434404f | |||
| cfcbaf33af | |||
| 175f78fa84 | |||
| c8ab2bec5e | |||
| 136d50a7c5 | |||
| 0fa653d580 | |||
| 48f2c85791 | |||
| 13ca56d380 | |||
| b5109d2a1a | |||
| 8ab532efb5 | |||
| f11c17063c | |||
| 72eb44aebc | |||
| b070503e77 | |||
| f48e1ee0ac | |||
| a5b7590d3a | |||
| f0955f1620 | |||
| 6dda2713cf | |||
| 4769254978 | |||
| ca917f7b9a | |||
| b9df4c99cf | |||
| e6dadb215e | |||
| d70bba2806 | |||
| 3217452b02 | |||
| ff0494b180 | |||
| 8be15c1b5b | |||
| 0207b5ba8b | |||
| 5ab917f606 | |||
| ea541ca21b | |||
| fc223f5924 | |||
| 7b8eb84cb8 | |||
| 38443c72c3 | |||
| 0cef3e67ce | |||
| b98d4875da | |||
| ae52db41de | |||
| c3e2b463e4 | |||
| 5b3ea012ab | |||
| 07df43aa2a | |||
| 6e3bc77369 | |||
| 24ddefe3ad | |||
| 7db645587b | |||
| cbf6d53e84 | |||
| 5f012c5dc9 | |||
| 5e0ce96e49 | |||
| 4a2228a372 | |||
| d9a0382539 | |||
| f52a532771 | |||
| efc4c53b44 | |||
| 4837f9cdad | |||
| 317c53acf6 | |||
| f02af5fe6e | |||
| 92e6c21210 | |||
| beb26e84f3 | |||
| 2b7a605223 | |||
| d70f0092f7 | |||
| 7f6e4a9744 | |||
| 96a4fc7ca2 | |||
| 29c1797493 | |||
| 860dead985 | |||
| 518ceb53a8 | |||
| 4bcddca1f0 | |||
| cf80f03084 | |||
| 47f31eed37 | |||
| 8ff9a9ff08 | |||
| 8dcf27ba29 | |||
| d97043725d | |||
| 90fd323ac5 | |||
| b6c384a0f7 | |||
| cda8a7be38 | |||
| c657d766cf | |||
| 4706ff6938 | |||
| c444af007f | |||
| 6e80bb49fb | |||
| bf3d0c1274 | |||
| 0ded1d326c | |||
| 708d288121 | |||
| 6462c83f69 | |||
| f30bb452cc | |||
| ad4dd2def5 | |||
| 76582a60b5 | |||
| 004246163d | |||
| a2cae45f00 | |||
| c1159337da | |||
| 71adbd7c39 | |||
| ded949052c | |||
| 40fd6eb358 | |||
| 48b65bf9d8 | |||
| a761f9eb55 | |||
| d1bf0da144 | |||
| de15a1e7c8 | |||
| a56bc0e1e0 | |||
| 519db2aace | |||
| e64c5661da | |||
| b15421826d | |||
| 3b31dbaa16 | |||
| 318957cb81 | |||
| 4b516fdb09 | |||
| 913b620c66 | |||
| cd4d90c647 | |||
| 456207b4e7 | |||
| 39604d2fdc | |||
| 27e415e664 | |||
| c57a4cf926 | |||
| 0a868b5c27 | |||
| 753f137575 | |||
| 728788e3b9 | |||
| ec6e130eb3 | |||
| 8972ca8134 | |||
| 671b6d2eda | |||
| 043f7bf2ab | |||
| 625cdde9a4 | |||
| e3d39fbf3f | |||
| 94cbc8bd31 | |||
| e262de9b2d | |||
| 17d9e30be5 | |||
| 37b7dc8e7c | |||
| 5c2f7a744a | |||
| 535f0f45c9 | |||
| b9cef2f38f | |||
| 793d78fba6 | |||
| 5ad055efb4 | |||
| 3277595366 | |||
| b11be32063 | |||
| 725652006d | |||
| 10587e3a84 | |||
| 073115e7ab | |||
| 45dcd987c5 | |||
| 960246fbb9 | |||
| 2fa274de1e | |||
| 4cc98874a0 | |||
| fafd05afb2 | |||
| 7a3ad30bfa | |||
| 32acf9cb72 | |||
| ddbc35181c | |||
| 0946ac2ff9 | |||
| 1d314834a4 | |||
| 875aecf9c6 | |||
| 13e0151cd2 | |||
| 51a7be29f5 | |||
| ef46738384 | |||
| 54806f6ee8 | |||
| ae538a2259 | |||
| 66f443fd00 | |||
| ca9c29e2b6 | |||
| 273beb016b | |||
| cd8a0f33b5 | |||
| b1e05b4832 | |||
| 4c0378eeae | |||
| ea14398929 | |||
| 1b5dd8bbd7 | |||
| c85acf8044 | |||
| 78a587791f | |||
| f4a3ebcb41 | |||
| 4e8fc6d198 | |||
| 086dab902c | |||
| 722c03b6c6 | |||
| 39128c34cc | |||
| 542d21c4e1 | |||
| 90a62405ca | |||
| bba20c27fe | |||
| d355e57fa6 | |||
| f2d7c4091a | |||
| bf879ce742 | |||
| e89a3b05ec | |||
| 52305ca91b | |||
| d6167636fa | |||
| cc1e1a525f | |||
| 96deae43fa | |||
| 5aa0267936 | |||
| b1b1e0eba4 | |||
| 07f6465872 | |||
| eda7c5369c | |||
| e9f709301c | |||
| 7e29bd10b6 | |||
| 20eea2184b | |||
| eaa375936f | |||
| de8582ec07 | |||
| e6ccdc2378 | |||
| 4450a01014 | |||
| bb962b90cc | |||
| a1ac507a94 | |||
| ad6eb15eac | |||
| 2e94e4cd67 | |||
| 44f75d94e1 | |||
| ad89310c45 | |||
| c26e112bee | |||
| 7daf18b077 | |||
| a8a5d2fc4e | |||
| 90f6abfa7c | |||
| 65f2d7fd66 | |||
| f3554804bf | |||
| f5e571ba40 | |||
| e43331b7a2 | |||
| e78fd09e07 | |||
| b4c1ca88f3 | |||
| dba9c2fbb0 | |||
| ab074f52fe | |||
| 121fa834d5 | |||
| 598cbf2210 | |||
| f481ba1c1c | |||
| 9e42dfd094 | |||
| 8aa117e4ae | |||
| f6f4e40a64 | |||
| caf2c0a6c4 | |||
| 57dde3e980 | |||
| dc8da4717f | |||
| 7b30fc4b82 | |||
| 6791b05a40 | |||
| b54ddccd7b | |||
| d32360cb3e | |||
| 3eba0c2297 | |||
| 01f4ce96f1 | |||
| 90b6afe06b | |||
| b22caef65f | |||
| db4281164c | |||
| 217c2cacaf | |||
| df4b6f0376 | |||
| 6ec1bfebec | |||
| 5d88326915 | |||
| 24354b9dcc | |||
| 39de8e28da | |||
| 06beb59628 | |||
| 2dbe567e3b | |||
| 563a5088be | |||
| c10c59db4b | |||
| 463f084b3e | |||
| 312e0dcbc8 | |||
| 6f93001658 | |||
| 48821a6da5 | |||
| b93bc142d3 | |||
| ab9b8b8b0a | |||
| 1c4a90626a | |||
| 3bf1866f4a | |||
| 1a652b555f | |||
| 3f61d24d0a | |||
| 16064d5614 | |||
| d9f21db623 | |||
| 8ac541e634 | |||
| da2688403e | |||
| dbd230da74 | |||
| f660530ef5 | |||
| a19563e139 | |||
| c4400cf72a | |||
| aae4943e64 | |||
| b0339b848f | |||
| f3f106c21f | |||
| 7fbff885dd | |||
| 60b0e652df | |||
| bb3405ef60 | |||
| 9ef0883011 | |||
| a50433dd95 | |||
| 37d7d18bb7 | |||
| fa0176c1e6 | |||
| 695c60c3fe | |||
| ffadb70d81 | |||
| 414b7e28d3 | |||
| fca464071f | |||
| cdb85f1309 | |||
| 4f08f4b84c | |||
| 1b5175d018 | |||
| 6d7fba6758 | |||
| 0bfda6d4c8 | |||
| 880b22604b | |||
| 04a2dc075f | |||
| 01448c152c | |||
| a09beb3833 | |||
| feda1e6d84 | |||
| 4256bea418 | |||
| 4d47b098e5 | |||
| 163754a46c | |||
| 66b56416b6 | |||
| c855346358 | |||
| 0e32c86c3d | |||
| fac3579fb0 | |||
| 19952264c8 | |||
| 5ec1e97cae | |||
| 5f5746a2f6 | |||
| 458b023204 | |||
| 4bad4ec632 | |||
| e34853e19e | |||
| 6cbdb1b4c3 | |||
| 60f890ce0d | |||
| c82c0a9812 | |||
| 123b1d4002 | |||
| e4958d5bb9 | |||
| 89e734dcca | |||
| 090fe394e4 | |||
| 389b4beba4 | |||
| d0ee6d1ad2 | |||
| ec769bc9f9 | |||
| 6b259070f0 | |||
| 651ea8cc2f | |||
| 3f0e948981 | |||
| 24ed7fbf3f | |||
| b13c3979c2 | |||
| 7a55dd512a | |||
| fdd0dbd973 | |||
| 774dd6d5e3 | |||
| 4cbaddf4c4 | |||
| 10f1da2736 | |||
| 0e5d76e735 | |||
| 339c9cceec | |||
| 2354bb5427 | |||
| fe80f8179c | |||
| b97143e9db | |||
| aaab905e72 | |||
| bc6d384ca9 | |||
| 6fc8c174f9 | |||
| 63b205c601 | |||
| f0a834f7e8 | |||
| fdb2cf09c7 | |||
| a67738380c | |||
| 15ce8bc79b | |||
| 8d70b91955 | |||
| a33ed05bec | |||
| aace8a14ce | |||
| d80b8ff30f | |||
| 3a66255576 | |||
| 1541f67eab | |||
| a2959c6e9e | |||
| 06c71eec65 | |||
| 70a7661711 | |||
| d190b1995b | |||
| a6f8230063 | |||
| aabc6c2825 | |||
| 8323458da9 | |||
| e4c60d70b0 | |||
| 4d8a815932 | |||
| b0e5f5973a | |||
| 05cb4fd897 | |||
| 72dc6ea77c | |||
| 1b0a6fe9eb | |||
| 363ad01bce | |||
| 04a45a407e | |||
| 14735e0a48 | |||
| 1c07428f89 | |||
| e0d68664c4 | |||
| 6c72c3d4a5 | |||
| 9df8dbee08 | |||
| 140af45bb0 | |||
| 2bf2f2518c | |||
| 5bcc379530 | |||
| c854ec0686 | |||
| 6a825cc504 | |||
| 3ed6763da9 | |||
| dbeabb8ff0 | |||
| cc66e1d966 | |||
| d7c7ff1c12 | |||
| 919ea9f750 | |||
| 5816ee9f9a | |||
| bcb258bcbb | |||
| e02c09d361 | |||
| 09b2cdd618 | |||
| 1e526e68ab | |||
| d77c7d51e3 | |||
| 4ff3c57976 | |||
| d51d0160d3 | |||
| c2ad9d4996 | |||
| 3416190e4b | |||
| de7cb6d6ad | |||
| eb297104de | |||
| dfa6463e5b | |||
| 9cd9776b7d | |||
| 097afab9f4 | |||
| 03a214c8b9 | |||
| 3f06a857c2 | |||
| 79f828125d | |||
| ad4b18cbbe | |||
| 1bd49671b7 | |||
| 9896057549 | |||
| 44832bbacb | |||
| f20a923dd7 | |||
| 30403da326 | |||
| f81a3ba45d | |||
| 018fa052f2 | |||
| c771d2809f | |||
| fc78206049 | |||
| 618d673947 | |||
| 6464099364 | |||
| 7c19f0cca7 | |||
| c2181c23ef | |||
| 3cf145aa6a | |||
| 6bea3d6bfc | |||
| 993db01400 | |||
| f2d078e3cd | |||
| 4cb4f17500 | |||
| 15a689c6f5 | |||
| 7894fed741 | |||
| 61f7c1e7d7 | |||
| 30efeb5bec | |||
| 18caf0273f | |||
| 214b81e491 | |||
| e60fb17524 | |||
| 4f1fdf85c8 | |||
| 33865993db | |||
| 5a27aaef24 | |||
| 7f65d82a74 | |||
| 8ab1f31058 | |||
| 4cd5529027 | |||
| 770036c5a8 | |||
| d38b75900a | |||
| e8acf7e87a | |||
| 2a4aea67b8 | |||
| d12744011a | |||
| c0e4c92d47 | |||
| cc3e910194 | |||
| 5d9f993352 | |||
| eaa52c19a8 | |||
| 42aeb19562 | |||
| ffc3dba682 | |||
| 1acc5ceb5f | |||
| 7d694dca07 | |||
| 7a693500c4 | |||
| 1c44912aff | |||
| 5e14da67e1 | |||
| 6b68a76bbe | |||
| b586fcebab | |||
| 244c0d828a | |||
| 57ebd7e170 | |||
| 8f10b58cb1 | |||
| f8bc408abc | |||
| f581f6163a | |||
| 5776471547 | |||
| 88486a1278 | |||
| 9fcadc2d7c | |||
| c50e3a702a | |||
| 2173ef5fb6 | |||
| 9ef6c57ca5 | |||
| 443d7684db | |||
| 1f6da1c653 | |||
| c165894ce9 | |||
| 19903ea3c1 | |||
| 0b38ab259c | |||
| 5d82037ffb | |||
| a41713febb | |||
| 5002d8e1fa | |||
| 237c6eed50 | |||
| a3ba7f0788 | |||
| f13b1e8604 | |||
| f083c0cba1 | |||
| defa2d9df1 | |||
| 05c422ef23 | |||
| 51d274961b | |||
| 4b4cc04897 | |||
| 4bf3d4d87a | |||
| 71cc980e96 | |||
| 58c0b81908 | |||
| 3b42bd43ab | |||
| a151532ffa | |||
| a0d1ce77dc | |||
| 863cae1bab | |||
| 4010ea814a | |||
| 8e25c091f4 | |||
| 2a57e00cb4 | |||
| 52424b0f9c | |||
| 132547a9d9 | |||
| fdb0459288 | |||
| df84352385 | |||
| 8d4f6a7865 | |||
| d72276df94 | |||
| 450bb1c2cb | |||
| 6f22e47feb | |||
| c6acb6191c | |||
| 6cade7d935 | |||
| c857ecab46 | |||
| 53d9cbc69c | |||
| 0ee403eab3 | |||
| 6f2d09eb20 | |||
| d6442ec991 | |||
| f3831fa77f | |||
| 3265c2e543 | |||
| 1a9ea64523 | |||
| 9de650e175 | |||
| d8b5f383f5 | |||
| 658c0734e2 | |||
| 5c7f01140a | |||
| 12767746ca | |||
| ffa86b25db | |||
| 2763c0f40e | |||
| 6aa99a903f | |||
| d9faf6c4bb | |||
| 48cd5855fe | |||
| bd0fc8a2d7 | |||
| 476bd7400d | |||
| bd10d48338 | |||
| bb91064416 | |||
| 72d2fe2fd4 | |||
| 92a5b9ac41 | |||
| cded6b1136 | |||
| 19f0ce7e37 | |||
| a88a515fa0 | |||
| a4b2eac0f0 | |||
| 0bd38290e6 | |||
| 19e4f3c2f0 | |||
| e6edac1589 | |||
| 781d0c0fe0 | |||
| b48cb47f41 | |||
| 1ece7caa57 | |||
| 0c1a3b1a61 | |||
| 2b5d4ef346 | |||
| 2dbd990017 | |||
| 34961b39fe | |||
| 088a54dacb | |||
| bc9d4a7643 | |||
| e0ee14d5b0 | |||
| e88db3d609 | |||
| f7d3550122 | |||
| 896681b671 | |||
| fbdbd440d2 | |||
| c0af854cb6 | |||
| 92889397e6 | |||
| 7c10b53209 | |||
| a154fedbfb | |||
| 7c43f5b554 | |||
| d19769115c | |||
| 561ffce031 | |||
| 61e2190f98 | |||
| c56abbf7df | |||
| 1cd2f7e0f4 | |||
| 516ad23aa5 | |||
| 0599d27463 | |||
| f56107c84d | |||
| dd61824df5 | |||
| 531b4d955c | |||
| 8bede7b81f | |||
| 37d563c30e | |||
| 3775be4ce9 | |||
| 5ac08ec3aa | |||
| 87e2aa42b8 | |||
| d9560ad124 | |||
| b93397e415 | |||
| 44d89c7209 | |||
| 5bb9890660 | |||
| f22d589c49 | |||
| 17f873db70 | |||
| 1647c39bf2 | |||
| 026d6d4a70 | |||
| 93113e0f00 | |||
| 236692908a | |||
| 6eea7c7e50 | |||
| 31516acec2 | |||
| c9728961bf | |||
| 7bd89a9ab1 | |||
| 39b553529d | |||
| e5883dd605 | |||
| 6b02c664fb | |||
| c7ae3fdc9a | |||
| c667572d3e | |||
| 9bbd6ff67d | |||
| ca98a566ee | |||
| f865d6e5da | |||
| bc9f2922e0 | |||
| c5a9b00eae | |||
| f408ff982c | |||
| 9a8d1200ec | |||
| 16c7aa2813 | |||
| 85f52d2aed | |||
| 8e71324514 | |||
| ea235c0c67 | |||
| ea995d017b | |||
| 1aecbbece5 | |||
| e30be643c9 | |||
| 0bba9482df | |||
| 07fd2dbc99 | |||
| f8a8559523 | |||
| 6481c9dca1 | |||
| 7aaa1973f4 | |||
| a12abaac9d | |||
| 4dea1b5a0d | |||
| da44ab0529 | |||
| 1a1e8463cc | |||
| 343fccd7fd | |||
| 577102c4ec | |||
| 73b836c73d | |||
| af0c2f59cc | |||
| f5faa053bf | |||
| 1044e8e91a | |||
| dffc0a4ed8 | |||
| ba4b1cb5af | |||
| 5cb4cdaa5e | |||
| 0525eb2d29 | |||
| 7be1d9e45a | |||
| f34af496ec | |||
| ae97649948 | |||
| 3787c490d4 | |||
| c3f1aae570 | |||
| 0c94747ab1 | |||
| 783cca1e13 | |||
| f15e32d063 | |||
| 238a616292 | |||
| 6010b5c619 | |||
| 4812c5486d | |||
| afc75af62f | |||
| 23b30fdd10 | |||
| 2778a7220f | |||
| c69556f2ff | |||
| b0689614bf | |||
| e42a401987 | |||
| 5162459e4a | |||
| 39d914c9df | |||
| 8d2f4d9dfd | |||
| a7d2f9b530 | |||
| 26f593afaa | |||
| ca4e7f9b4f | |||
| b11858bcac | |||
| 034f23b47e | |||
| 9c25f300cf | |||
| db4ff56f0b | |||
| 830c2472cb | |||
| 079e2af0c0 | |||
| 5f166158c3 | |||
| 4a06378d67 | |||
| d0f0a74df8 | |||
| 65a8965e85 | |||
| ab2376f8d8 | |||
| 48717dff00 | |||
| b64dd7ab57 | |||
| bf013ecf00 | |||
| 22b744fa23 | |||
| f560fe3b37 | |||
| 839a29a2a6 | |||
| 81bc44b30f | |||
| 58083ccb0c | |||
| 71cc2d7d5d | |||
| 976a4da0a1 | |||
| 74c48e5906 | |||
| d7f0b130ce | |||
| 1d0ad72800 | |||
| 23b65c8e6e | |||
| 62b367fa81 | |||
| beac45b075 | |||
| dfc5159aa3 | |||
| 886cdb440b | |||
| 6ed9443972 | |||
| 08e0f172de | |||
| cfc43f6dea | |||
| f1d168f781 | |||
| 302d9796c4 | |||
| ee85784be1 | |||
| 1260887fa7 | |||
| ce8073d25e | |||
| 31f4d9066b | |||
| 35e66770be | |||
| cf2f7f2132 | |||
| a145559662 | |||
| d029e3dc16 | |||
| 286326a98e | |||
| 2f59d78737 | |||
| adf4782076 | |||
| b38ffef2be | |||
| 6375f2d73a | |||
| 1a2df9c51c | |||
| 770fdb2b7d | |||
| a7d3a49171 | |||
| 920e7db709 | |||
| 4a6b45cf04 | |||
| 7bd60adfbe | |||
| 171ff54ea4 | |||
| da452decf6 | |||
| c335719e8f | |||
| d57cdf645e | |||
| e47a96bf24 | |||
| daad607c7c | |||
| 29f1f9c872 | |||
| a49cfa8142 | |||
| b57d296adc | |||
| 01d8bd445e | |||
| 04e220cc4b | |||
| cb70c48b36 | |||
| 750d6f4be9 | |||
| c6e14a696e | |||
| d34423fce9 | |||
| 4999547f87 | |||
| fc5dc9717a | |||
| d20759c141 | |||
| f7b00c62a4 | |||
| 32873ce70d | |||
| dc59561a95 | |||
| 4bf3fdd898 | |||
| d87eece1d2 | |||
| 4fe4eacc00 | |||
| 108a892a11 | |||
| 2c4bd9a3fe | |||
| c80ac58eff | |||
| d56e1f6285 | |||
| 22b3ddab66 | |||
| 3fe2491b73 | |||
| 4e6758e31d | |||
| 098ec1abb4 | |||
| 17cf824545 | |||
| e35f5d3c93 | |||
| f4f98e5856 | |||
| dc0335d1d5 | |||
| 6013814cf4 | |||
| e0a0570cc4 | |||
| 61deb4fcfd | |||
| 7c4c60425b | |||
| 302f49baf2 | |||
| 3f6cd5a663 | |||
| 1b232041c9 | |||
| eaf117cce1 | |||
| 88d49c7c3e | |||
| db8bd30dcd | |||
| 9e3ec63637 | |||
| d2aa2c080f | |||
| 7148311953 | |||
| c23dfa0d23 | |||
| b08de33b0b | |||
| fc1d8c0138 | |||
| a5a77d1e7c | |||
| f57fcefe6b | |||
| a5483a03c9 | |||
| bb8b3b9291 | |||
| 6c6dca05e7 | |||
| 97b4a31b16 | |||
| 40d9277ef3 | |||
| 009044b71e | |||
| 4760a3f3e8 | |||
| 3302012c02 | |||
| 812c5a314f | |||
| c2da8c3fd4 | |||
| aa78640491 | |||
| 7c49688e1b | |||
| dbe10c7965 | |||
| f1f5107282 | |||
| cc06250bf8 | |||
| af1ea7f495 | |||
| 3491c488d3 | |||
| 1828b6daab | |||
| c26f45b7c2 | |||
| e116b90116 | |||
| fff14fca50 | |||
| 1c0290df2d | |||
| c72b7a8830 | |||
| a31ea72ced | |||
| 487e415de5 | |||
| 825709870d | |||
| 970ef5e51c | |||
| 04aa58d920 | |||
| e7f1d350c9 | |||
| cb4a1d51c1 | |||
| 352d110622 | |||
| 3b9aedec5f | |||
| fabcf841c9 | |||
| 43a5f928ba | |||
| 873fa16517 | |||
| f7ce374a28 | |||
| 2dd124d09e | |||
| bd6c1b06c1 | |||
| 116915890d | |||
| 0e9347efa5 | |||
| d3bd55e628 | |||
| 6901a37cd2 | |||
| c52a5a2974 | |||
| d6523c67a6 | |||
| a9fd3608ea | |||
| b25cace3ea | |||
| 4320f047db | |||
| b4b3e7b9a4 | |||
| b6938da552 | |||
| 4830a1559d | |||
| 92ea3ef720 | |||
| 73d2719330 | |||
| af82aab3a6 | |||
| 51b4b6216f | |||
| 3eb6748578 | |||
| de32b0bba5 | |||
| de0fab78ed | |||
| 71425c3b23 | |||
| 75f7b1e261 | |||
| 9af35d998f | |||
| 34e3f3907a | |||
| 46b0510b99 | |||
| a7624ea48b | |||
| 2f3b4a7aaf | |||
| a9bbe0b128 | |||
| 0d9d0a4b70 | |||
| 8235d0bd50 | |||
| c2e01bedc5 | |||
| 32c4614a32 | |||
| 24ae6c91ea | |||
| 346a4f5933 | |||
| c6551336c8 | |||
| a240e1de75 | |||
| a776210aa7 | |||
| 88a6a2d1de | |||
| e022a7edee | |||
| 5d912efb32 | |||
| 5243af975c | |||
| 43486e7137 | |||
| b2430495f5 | |||
| 1b1a6e357a | |||
| 626b5f36ad | |||
| 746ceebcdc | |||
| 2a40051475 | |||
| 2406574041 | |||
| 23c40b9618 | |||
| 95e4dca38a | |||
| 66e562af72 | |||
| 1f70331a12 | |||
| 38e3369566 | |||
| 7303cdbe08 | |||
| 4677e34ea6 | |||
| a48dc3ddf6 | |||
| c548969877 | |||
| 68150edbb9 | |||
| 8e347e1b2e | |||
| b26989f594 | |||
| 0a3259d77c | |||
| d95492c5d0 | |||
| 3555c7f0c5 | |||
| 272e2d5654 | |||
| 3dab0d365d | |||
| 3abd110d45 | |||
| cebb406277 | |||
| 71e4f1c8a7 | |||
| 403e42b662 | |||
| a5598c33f3 | |||
| 0c1cc32017 | |||
| 994fb6c043 | |||
| 0252bac4ba | |||
| b468069875 | |||
| a1842491ad | |||
| 241e449564 | |||
| ad8848f96a | |||
| 7f3c1a89c3 | |||
| 7e1f431eca | |||
| 70c55da1df | |||
| f9ab7647dd | |||
| 623aa7ea48 | |||
| 046d264688 | |||
| 944e168120 | |||
| 9594105e57 | |||
| 675343f575 | |||
| fc6ff45c49 | |||
| b4bac88c39 | |||
| c622ba84b9 | |||
| 339f95c647 | |||
| ec67e0ab22 | |||
| 0b371c8103 | |||
| 2192ea6fdf | |||
| 0060f88c45 | |||
| 1eac4db491 | |||
| 0d2c3be367 | |||
| d12c6ccb72 | |||
| 1eb63fd8b9 | |||
| 2cf2171ac2 | |||
| c8dd516d6c | |||
| 0f19627407 | |||
| 3eb71fe7b5 | |||
| 0035584d91 | |||
| 8cbd2e3e9e | |||
| b0f5c7f36f | |||
| 412eb0a90b | |||
| f8e816629d | |||
| 3d0138569d | |||
| 7bb7d736a2 | |||
| 7910f39613 | |||
| bf6ef2a588 | |||
| a11d89daa3 | |||
| b8a4a6b959 | |||
| dd6045d9f8 | |||
| e1c3a19420 | |||
| cc586685e6 | |||
| 31883f603c | |||
| f377c81c8a | |||
| 32384eaf07 | |||
| 7c2efa697c | |||
| e1df69dfcb | |||
| 6dd84fde33 | |||
| 60eaedc67f | |||
| ce908b31c1 | |||
| f687739cfe | |||
| 56d1e3792a | |||
| ce8215ec6c | |||
| db5b86dbac | |||
| ecab83264c | |||
| 81194b2caa | |||
| ce185c14d3 | |||
| ff1db9a055 | |||
| f928f17bb5 | |||
| 1241e778f9 | |||
| 3ab0ef1902 | |||
| c7c35b8b5a | |||
| 3d9b1fd343 | |||
| 96bed3a623 | |||
| e72b0edce2 | |||
| ae4aeb4b1e | |||
| 302abc2a60 | |||
| 2b3cbc638b | |||
| 3de055bf65 | |||
| df449e7bfe | |||
| 6326a50d20 | |||
| aef212ada9 | |||
| 802a7ff3a8 | |||
| 9cedc864c2 | |||
| ee804cd6b1 | |||
| 25c7e64ded | |||
| 5c4fbbebe1 | |||
| 615402ea83 | |||
| a0a72a9f6d | |||
| 8b9acf750b | |||
| 24d68a7f09 | |||
| 781eeff021 | |||
| 3e6c2c6024 | |||
| f180558041 | |||
| 506ea71302 | |||
| 01e11e9043 | |||
| 7ed197f46b | |||
| 5c36eef039 | |||
| 26e20f9999 | |||
| 71195895ba | |||
| c7ebb4b009 | |||
| c0cef8dd12 | |||
| ea850e58d2 | |||
| dcdd97a985 | |||
| a61ce45a32 | |||
| 1326c4e71e | |||
| ad5f3877f1 | |||
| 9cbbc80f7a | |||
| 8a02e967d3 | |||
| 7c49f22702 | |||
| fdb7c115a7 | |||
| fa9e9510e5 | |||
| 06b3ad1071 | |||
| d96a731e93 | |||
| 847ff77a81 | |||
| df746c7911 | |||
| 2583270774 | |||
| 5393d674f9 | |||
| 4aed866d69 | |||
| d775a7ee21 | |||
| c044ff3444 | |||
| 6e75842354 | |||
| ac2b6bcc33 | |||
| c440b758a3 | |||
| e9471124c0 | |||
| 442d1cb48f | |||
| 5030c55b1e | |||
| fa91e2a60c | |||
| 32de123db0 | |||
| 90e9c37d35 | |||
| 84d4036117 | |||
| e38e85572e | |||
| f50d6208c8 | |||
| 34d189c02e | |||
| ba9b49bc83 | |||
| ed08eb07c6 | |||
| ae875734e2 | |||
| d2d6f8c970 | |||
| 04edb741a6 | |||
| 34b4b65865 | |||
| 25a74f3664 | |||
| fa5537bfc0 | |||
| 3588c4ab99 | |||
| 5a9b1f769d | |||
| 782ec06f2b | |||
| 5b43db7171 | |||
| df62037c4a | |||
| ad1cc82b38 | |||
| 05b8c53ff7 | |||
| 7268426248 | |||
| c39de966df | |||
| eb133ef9a7 | |||
| 721461dd3e | |||
| 337e25ad43 | |||
| 7042528d26 | |||
| ce52c27a8a | |||
| f9c3b80780 | |||
| ab0e2f5236 | |||
| b7280a442e | |||
| 8af91b0209 | |||
| ee4a262953 | |||
| d584293cde | |||
| c60c9b323b | |||
| eaee27c9e4 | |||
| a2575059e2 | |||
| 54bdf59dde | |||
| e96e3dc6e6 | |||
| 3ac4337aec | |||
| f68674b35a | |||
| 729d0d5368 | |||
| 5c0d31873a | |||
| 5310f4e310 | |||
| 2c961328f1 | |||
| c36773674e | |||
| 54c615dbc2 | |||
| 483ef09890 | |||
| 81a741e760 | |||
| 278f2a6cac | |||
| cf277261dc | |||
| 451ee5a593 | |||
| ba3811a284 | |||
| e2241b9365 | |||
| fe2bb84403 | |||
| 6f1067a889 | |||
| f0cdbd0f52 | |||
| 9632cafa95 | |||
| 321b2b9b49 | |||
| fb3dd5eee6 | |||
| e518445853 | |||
| 8ce240b95c | |||
| 0db047e572 | |||
| 22275f3077 | |||
| b77acb3e53 | |||
| 6ae9ef571e | |||
| 8e5189464e | |||
| 0de713ff36 | |||
| 137bee9d27 | |||
| 3641ab8c7d | |||
| 16b6b76507 | |||
| 5cd9540d5f | |||
| ae7873260e | |||
| 3dfe604ba0 | |||
| 3e19c4ddae | |||
| de59300aaf | |||
| 8cb05a91ab | |||
| 5f2c3f607e | |||
| 8ebcc4439b | |||
| b65ee01aef | |||
| 2b311bd860 | |||
| a841b75b98 | |||
| 9b3b7dc098 | |||
| f783454774 | |||
| 81d9258e80 | |||
| c6bfd5e7be | |||
| 3c5cfd465b | |||
| f61f9bdc5f | |||
| 2ab6e0843d | |||
| d21bf41b6c | |||
| c54ba1fb86 | |||
| 4d86a199f0 | |||
| 4756826054 | |||
| ea309aa19e | |||
| bad4ea6e65 | |||
| cf4288767a | |||
| 802ccdff4a | |||
| ba50de15ea | |||
| 73e30e8085 | |||
| a53912cc19 | |||
| f105f70ded | |||
| f0cd084738 | |||
| ae5158b676 | |||
| bfd45a0017 | |||
| 78be0c66da | |||
| 562cde37f4 | |||
| 263dea0e36 | |||
| de743e35d0 | |||
| 09a46d0c74 | |||
| ca5a1d0853 | |||
| 97fcc495f2 | |||
| 4e69467b14 | |||
| d2e366a46f | |||
| 94905a71ac | |||
| c7644ad29d | |||
| 0daa462207 | |||
| d8f79f48e9 | |||
| bf878dc446 | |||
| c06b37b798 | |||
| 30e3580856 | |||
| d29caa099a | |||
| d1270aab4d | |||
| cd55298616 | |||
| c6f3298f78 | |||
| 350db4ed9f | |||
| 1ccca9863c | |||
| a7b03c1cea | |||
| 2cb52f8875 | |||
| 2c797807cd | |||
| 37b94bf5fa | |||
| cbbe4b33a3 | |||
| a00a849952 | |||
| e877a001ab | |||
| 709665846e | |||
| 93a310582f | |||
| 9f4219773e | |||
| f0b7a7e5d3 | |||
| 97502f4c04 | |||
| 737f660011 | |||
| e0568f33e8 | |||
| 2ba95758eb | |||
| fc3d0233af | |||
| 13c08f9660 | |||
| 82528e2f38 | |||
| 90a983a7e5 | |||
| 58a9cde61d | |||
| a00aae702d | |||
| 69584f541d | |||
| 855f4b869a | |||
| 60d5443f00 | |||
| 527b0a7065 | |||
| 22a7c21886 | |||
| 484d240e7e | |||
| 108855aca2 | |||
| 8ca321df7c | |||
| ed97800c80 | |||
| 78c6f40093 | |||
| 5acd166d18 | |||
| 3efeeecace | |||
| 259db3778c | |||
| 52be5c1660 | |||
| f85cce714f | |||
| 2eb93387c2 | |||
| 2d9fe72215 | |||
| dd3ec468f6 | |||
| 88d28cd6fe | |||
| b4035c2d19 | |||
| 65dcb39bac | |||
| b92bb0bd28 | |||
| 0a840c02f7 | |||
| 62433b5f05 | |||
| 6ffdf3880f | |||
| 9bfa5c82d1 | |||
| 66cf085272 | |||
| 567448e2fd | |||
| d174531931 | |||
| a38ded702f | |||
| cd5f255966 | |||
| d1a3561585 | |||
| da8b276699 | |||
| 5aa0304149 | |||
| 7877e2467e | |||
| 96277372d5 | |||
| 98ee99071c | |||
| b8991750c5 | |||
| 97acfd23fb | |||
| 18726737d0 | |||
| af05fa3e85 | |||
| 6a297a8f3d | |||
| 309904b15a | |||
| 453ce4df3b | |||
| 02537b80b2 | |||
| 62730366ee | |||
| 0558a25141 | |||
| 3f57609b75 | |||
| 9850d18420 | |||
| 05ae18d74e | |||
| 778086ce19 | |||
| 63ba72331f | |||
| 3e231e7c13 | |||
| a522a66715 | |||
| c2c891723f | |||
| c087aaf5be | |||
| 4cb46c124a | |||
| 2e4772ac0e | |||
| 4f70fd3e71 | |||
| ebb4811a75 | |||
| 835e222af0 | |||
| a5e63aa90a | |||
| 1922a2139d | |||
| f5acbccb79 | |||
| d39ebebc9d | |||
| b5ed1de31e | |||
| 5cf156f698 | |||
| dcd99c2d30 | |||
| a29e5521cc | |||
| 59bd90b967 | |||
| ff53da5b0a | |||
| 9520123f6d | |||
| d9efb037e3 | |||
| c403c9aece | |||
| df5115e7b8 | |||
| 22fbb512d5 | |||
| 2acfa7e525 | |||
| 69659e9bd5 | |||
| 6c066f6107 | |||
| b96a05494b | |||
| 0d42b4cf8a | |||
| df0c77ccd3 | |||
| 3a0a611f15 | |||
| 1eaf6df842 | |||
| 9fe9137c96 | |||
| 363fc5c72b | |||
| d4af745fc8 | |||
| 6e03104e3e | |||
| e89a84608f | |||
| 1dbd83a582 | |||
| c1002557cf | |||
| cccea911fa | |||
| eb10120607 | |||
| c00dc6120d | |||
| d0605e8d5f | |||
| d33c331abd | |||
| 05b6c33a2c | |||
| 3064f2ced5 | |||
| 5e7c9b9d4a | |||
| 009e03c3ba | |||
| af3b0146a8 | |||
| 883e2ccc91 | |||
| 7c1e99884c | |||
| 29e1302f3f | |||
| 798f2466e4 | |||
| 67f19745fd | |||
| 72abe5f3d3 | |||
| 08a287dea1 | |||
| 7dadf387e5 | |||
| 8febcc2705 | |||
| ff20370d0b | |||
| cc9ca8bbff | |||
| 5906d6cce3 | |||
| 8265dac9c0 | |||
| 6eeac03a0e | |||
| 7ca8f7b5cc | |||
| d7ed5518d1 | |||
| 6f036bc778 | |||
| ba4a8aa762 | |||
| 5f992ffe15 | |||
| 2904e58a9f | |||
| c45a9504e7 | |||
| 403ead44f9 | |||
| 9b0d123217 | |||
| 8e673a6cdf | |||
| 6d3c1fb7fc | |||
| 01043fa790 | |||
| 23d5e15f0f | |||
| 5500473387 | |||
| c8399e8104 | |||
| 423e1422ef | |||
| c34c0c6718 | |||
| e3e96e59d2 | |||
| accb211280 | |||
| f07a4667b6 | |||
| cb768ea23f | |||
| b3249c10c2 | |||
| c6fce5de24 | |||
| 5c8e1169cd | |||
| c0a485083d | |||
| 5f7d83bd4d | |||
| 52916bfcec | |||
| cb2646154a | |||
| 61a7c4fb33 | |||
| 3a3abc8087 | |||
| e9b60cfb26 | |||
| eea9e2c1d0 | |||
| 171d129ad1 | |||
| 0154c5d74e | |||
| 9032a656fa | |||
| fda57a93a5 | |||
| 4ad208668a | |||
| 23edb51ba4 | |||
| adf10296f1 | |||
| d3e6d6b6a6 | |||
| 82de0862a1 | |||
| 1969537fd7 | |||
| 973afe042a | |||
| 99ceb1691b | |||
| 4a904fa3a8 | |||
| c13d7e29ef | |||
| 58d9ca1bfd | |||
| e2115e8ea5 | |||
| ba417894ed | |||
| a237248388 | |||
| 7fd332f8cf | |||
| 2811d6ae53 | |||
| d8c6d93c6e | |||
| 134529a09d | |||
| 24c7bb600e | |||
| 90e9948dbe | |||
| db006b911a | |||
| eb2c2b9400 | |||
| 86fc5b5ed8 | |||
| f7e9454697 | |||
| 02a16050d9 | |||
| 598fe91464 | |||
| 21272735ae | |||
| 52fea09c53 | |||
| d9ccd24b02 | |||
| 27fef98a39 | |||
| c6db644c42 | |||
| 41108fc4d3 | |||
| d7a20821c3 | |||
| 20285d076b | |||
| 44bb070203 | |||
| 9e87219aea | |||
| 1b7e220de7 | |||
| fe8b723622 | |||
| 1e85c40c42 | |||
| f72464a240 | |||
| 65785ead69 | |||
| c550100a55 | |||
| 2836bce8fe | |||
| 7f95d47721 | |||
| 51c0045be4 | |||
| abfbfd9e9b | |||
| 5d6c8fd807 | |||
| f4799b2ddb | |||
| 9afa6cc245 | |||
| 25e8d70786 | |||
| 978e45911f | |||
| da7bce3470 | |||
| 4efa5cfa75 | |||
| 444ae51a3e | |||
| 07f82e4a14 | |||
| 3379f6f793 | |||
| 80b47734a7 | |||
| 69d46538ce | |||
| 208d38207e | |||
| ffe80c66d7 | |||
| bfa672f42c | |||
| 9f89f3190a | |||
| 71931b423c | |||
| b54aabc958 | |||
| a45fe72eb9 | |||
| 62d64631b5 | |||
| 11945ce7bc | |||
| bb3d908bcf | |||
| 98b3946fca | |||
| c15de3b68b | |||
| 78ed1ae446 | |||
| 56fdc4f3fe | |||
| f17261020d | |||
| 6f98ca68af | |||
| 269538fdc7 | |||
| 6b23c3e179 | |||
| 5cc19ce053 | |||
| bdf6289b32 | |||
| e3c04b1fd0 | |||
| a7948d7bfe | |||
| 505782f224 | |||
| 1353c291e9 | |||
| 9af1b62bee | |||
| d7ec36e3da | |||
| aab97adb23 | |||
| 91502b4104 | |||
| 9bc76b4259 | |||
| 9948bb3f2a | |||
| 0722775038 | |||
| 65423b1768 | |||
| 9bb0f1d18e | |||
| 39866b7463 | |||
| 4c58a5cef2 | |||
| c748230b35 | |||
| c3aa15cc16 | |||
| b45bd901e0 | |||
| 317fd06357 | |||
| 4a7c678213 | |||
| 85e06a77af | |||
| 7cadc30914 | |||
| 995fc63f2c | |||
| e735220691 | |||
| 9b7c6e96f7 | |||
| d83fe9d417 | |||
| a1d1d5dba7 | |||
| 781fdaafcd | |||
| 1f1d5b9181 | |||
| 9e22ec267c | |||
| b296a73330 | |||
| 65be3de200 | |||
| 45078dda82 | |||
| 822bbd9ad5 | |||
| c873f7e702 | |||
| 0a5ac62b59 | |||
| 1e5405ccaf | |||
| 12d2270935 | |||
| ed00d1b2e3 | |||
| 2b452ffbd3 | |||
| 3b4a23c4a1 | |||
| 4484985c2d | |||
| 6f99ca1d31 | |||
| 8efa103041 | |||
| 9638bf2b1e | |||
| 6f43468724 | |||
| 18a9ebdb1e | |||
| 604142af93 | |||
| 2d83868ed9 | |||
| 73195a0215 | |||
| 13d05549f8 | |||
| 0143bc734c | |||
| ff860a3310 | |||
| ed0044aeab | |||
| 1a6d290d71 | |||
| dbb7245e22 | |||
| 437aa4082c | |||
| 0f9802a47c | |||
| 46d6d1c329 | |||
| 4dd1521677 | |||
| 32fba39915 | |||
| c1697ce96b | |||
| ba49e6a588 | |||
| 5525f082e6 | |||
| a4d987b45a | |||
| 3cc66b6816 | |||
| 21ff570c4d | |||
| f2e4cf3a92 | |||
| 7123de66f9 | |||
| e4fe202fc6 | |||
| bde6caf167 | |||
| 96f45b5fbe | |||
| 4352afeeb0 | |||
| 369f34b2d1 | |||
| 1ca558f011 | |||
| a6db822a69 | |||
| ad8226d549 | |||
| 1b27327057 | |||
| 3d713cee62 | |||
| afd4da8f11 | |||
| 3ee632514c | |||
| 456fe71ca9 | |||
| f2c59b3881 | |||
| 2c1560e027 | |||
| 34fec995f7 | |||
| ec7cbe272a | |||
| 98bc1ed600 | |||
| 7756773683 | |||
| dfdf11d461 | |||
| cc5ef57843 | |||
| 71c599f50e | |||
| a1f3a5d9b6 | |||
| a9e89d2fcc | |||
| fdc89d1b89 | |||
| c4c1b1f5a2 | |||
| 12b9106fc7 | |||
| faaffdd618 | |||
| 774729b221 | |||
| 1455fa6bc3 | |||
| a9853e6033 | |||
| eefa47776b | |||
| 0b12a7e66f | |||
| 3019d8341d | |||
| dcacfc1124 | |||
| 2f6cb764a4 | |||
| a0cf2b53e0 | |||
| 593a5072d9 | |||
| 27617efbfb | |||
| 6ab12597f5 | |||
| 07cd1d1272 | |||
| abe35817cd | |||
| 585bdf562a | |||
| 034441bd13 | |||
| 1819704620 | |||
| 18801a6c60 | |||
| f83c2d5cd1 | |||
| 724dc48fe8 | |||
| 791ff25d52 | |||
| 299eb469f8 | |||
| 0f9a8a43e4 | |||
| 7856f5882b | |||
| 284e5dd2e8 | |||
| 3d3f4f50fb | |||
| 8d89c4bbce | |||
| 85d8225cc0 | |||
| 8ad24ca3e8 | |||
| 6360dee125 | |||
| e931616011 | |||
| ab611e9ef3 | |||
| 240d4704aa | |||
| f9d43479f2 | |||
| c2f6f87cae | |||
| 869534fafa | |||
| 56f88f2e30 | |||
| a1d5ce3716 | |||
| 78dc679a72 | |||
| 57e3ee47ee | |||
| 184928204a | |||
| 2651eae663 | |||
| 28e4977c33 | |||
| adc164b825 | |||
| 66bf55710e | |||
| c6abe87ec2 | |||
| 4bb16b18ed | |||
| 4cc413cdaf | |||
| be3b630474 | |||
| 677ad71b96 | |||
| 9607bb29fd | |||
| d29415a6e2 | |||
| 54fa28441c | |||
| bb42ec2bfc | |||
| d31251c54e | |||
| 6a338e28b2 | |||
| f3ce5e73fe | |||
| c53d3a4b3a | |||
| 5135f236c2 | |||
| 78c847ef7d | |||
| 673a2f67f1 | |||
| c5bc4fe245 | |||
| bc4a92b702 | |||
| ea381d9180 | |||
| 4f82428a20 | |||
| e494a76b33 | |||
| 1753e40466 | |||
| 6667ba4172 | |||
| 75e8aa8aee | |||
| a81a1bd5f1 | |||
| 5d1539df75 | |||
| a821682c8c | |||
| 9446e0348e | |||
| 41ccb61c2e | |||
| 1b7781a159 | |||
| d66f58a550 | |||
| e2824f9259 | |||
| 4376f8f030 | |||
| d377660b5a | |||
| c5ce9b0699 | |||
| c74a7ce4fc | |||
| d98ed68749 | |||
| 70d6d2f2db | |||
| da441c59f6 | |||
| 42093aedcf | |||
| 74d80473df | |||
| 7ecb337405 | |||
| 07792adc56 | |||
| c0c827d3ad | |||
| 6a2bbed73d | |||
| 4c1944a08d | |||
| 95f870f1b4 | |||
| c250de7dae | |||
| e4b6a143c7 | |||
| 9367e9fe5a | |||
| a0c2bbac9d | |||
| f5f6ec3d71 | |||
| c57c1c8b2e | |||
| 44f639f371 | |||
| 4435717168 | |||
| 6767ff5434 | |||
| ff1a0d217f | |||
| 42c5e98670 | |||
| c9b80a3612 | |||
| e78a4d61d8 | |||
| 88ebcb56e7 | |||
| 308dda1587 | |||
| 67a9dd8497 | |||
| 732ce25d7f | |||
| c16fda1cb6 | |||
| f036c25dca | |||
| 7fc4292ed8 | |||
| b50e8a5cf9 | |||
| 7018da3f12 | |||
| a66c43166a | |||
| 2893f7d481 | |||
| 398e42acb5 | |||
| 6ecd31a715 | |||
| 456bc2ef86 | |||
| e071cd4635 | |||
| cc03e1ceef | |||
| e4d08fc5d7 | |||
| b25192332b | |||
| 0eeaf8713f | |||
| 42c4a0da51 | |||
| 79eb6d3942 | |||
| db853134e3 | |||
| 218029ee57 | |||
| 4295fbf6c6 | |||
| 0985adb770 | |||
| 5d2ac10073 | |||
| 85aa495741 | |||
| 8bf1e3a944 | |||
| 066febdf40 | |||
| 9b620b2a35 | |||
| a9bbfe9c4f | |||
| d95735deaf | |||
| af31bbeba1 | |||
| 1d7d604016 | |||
| df26fec1b3 | |||
| 6086a70e06 | |||
| e5529938ea | |||
| e25db4d1b5 | |||
| 32acb0ff01 | |||
| f230c07ba5 | |||
| 2becc3273a | |||
| f4f610f1a3 | |||
| 10c5b46e3b | |||
| b503ef8761 | |||
| 94393d27c8 | |||
| 12f4787b67 | |||
| f15c1c4e54 | |||
| 62925c4c3f | |||
| 4fdf5d28ca | |||
| b78c9a2251 | |||
| b436c4a94c | |||
| db1a546aba | |||
| 9402f537b6 | |||
| 2d29095348 | |||
| ac03b4ccd7 | |||
| 759a18685b | |||
| e07ab65d73 | |||
| 26f51ece90 | |||
| 99066ae939 | |||
| 5ff0f09a45 | |||
| 5afe779ffc | |||
| af042ccf07 | |||
| e587fe5ce8 | |||
| 0b31c677f2 | |||
| d3362dfa0c | |||
| 7890157f52 | |||
| b3d1ea4cd5 | |||
| 7c842f3170 | |||
| 054c5da294 | |||
| 5c5a808290 | |||
| 5c30b2f271 | |||
| ce2216f544 | |||
| 1d13cc1601 | |||
| 166879b8b0 | |||
| aeb9d5cd90 | |||
| 8e9d076216 | |||
| 0d48cb959f | |||
| d908f53607 | |||
| 238551b024 | |||
| 4e6539efec | |||
| c806279fa9 | |||
| ee1fde4262 | |||
| 4d0611b7d4 | |||
| 1358303e42 | |||
| c17f0fb44f | |||
| 569cd6c57c | |||
| 0cfaf34a22 | |||
| e8aeecc4c9 | |||
| edf834188d | |||
| 4e402dca7d | |||
| 7f6bf7170a | |||
| 0ed9d3c62c | |||
| 149071bf0c | |||
| 720e691f33 | |||
| 32614e4074 | |||
| 9dc5a3bfc9 | |||
| 8db006d9a1 | |||
| cb4afd39bd | |||
| e078caffd8 | |||
| 90a9febb6c | |||
| e4a1286aae | |||
| 08a8011456 | |||
| 643b6f0aa3 | |||
| 45d262d6c0 | |||
| 5dbd11c6ed | |||
| 3fcb6df0f1 | |||
| 9701516228 | |||
| 77dfe63d90 | |||
| 2367d94a42 | |||
| d85c849668 | |||
| cbd8c07265 | |||
| 3a6d3cb396 | |||
| 6e52f552cf | |||
| 973114caf6 | |||
| e27e0ca198 | |||
| 27329e39e4 | |||
| 38c2070aab | |||
| a0f28708ab | |||
| e25d205a7f | |||
| e28dab17d6 | |||
| 05b3237bae | |||
| 4fd9d1ee5f | |||
| 0fe7004d38 | |||
| 06b0dbdfba | |||
| 48fb3d3653 | |||
| baa5fd9739 | |||
| e01c277c56 | |||
| ec3a066e4e | |||
| b0c8e75c6e | |||
| d39942902c | |||
| 87fc4e6588 | |||
| 84e57d040b | |||
| a4f64c02d0 | |||
| 278eeb5ee9 | |||
| 3342fc2244 | |||
| 87857fe5d9 | |||
| 64efd07f6b | |||
| 6be66d6df9 | |||
| a68934f498 | |||
| 95ef78ab23 | |||
| 5be0743751 | |||
| 8fc7f2aca1 | |||
| 4db4ab9798 | |||
| b6c2c8117e | |||
| 86a42aad16 | |||
| 8e2e09bb16 | |||
| 3713aa210f | |||
| a65c23546b | |||
| f6de91bf0f | |||
| 062633d312 | |||
| 4a54699c1f | |||
| c72f6e6ea8 | |||
| 790a9155d4 | |||
| f141b845fd | |||
| a274c87cb3 | |||
| a94c9d2709 | |||
| f9b18aa62f | |||
| 0866cea72c | |||
| 6adbb93f0a | |||
| fe0e00f8f8 | |||
| 13d19d42cb | |||
| ec852b0c8d | |||
| a05c8ff66b | |||
| 5ce50d0a2e | |||
| dfbdeafa39 | |||
| eb322e8312 | |||
| c2e819771f | |||
| 744d548380 | |||
| 82a4bbd571 | |||
| c187461985 | |||
| cc91db55b7 | |||
| d71e70bedf |
+1
-1
@@ -37,7 +37,7 @@ pageheader.html
|
|||||||
doc/SiteTOS.md
|
doc/SiteTOS.md
|
||||||
# themes except for redbasic
|
# themes except for redbasic
|
||||||
view/theme/*
|
view/theme/*
|
||||||
! view/theme/redbasic
|
!view/theme/redbasic
|
||||||
# site theme schemas
|
# site theme schemas
|
||||||
view/theme/redbasic/schema/default.php
|
view/theme/redbasic/schema/default.php
|
||||||
# Doxygen API documentation, run 'doxygen util/Doxyfile' to generate it
|
# Doxygen API documentation, run 'doxygen util/Doxyfile' to generate it
|
||||||
|
|||||||
+147
@@ -0,0 +1,147 @@
|
|||||||
|
# Select image from https://hub.docker.com/_/php/
|
||||||
|
#image: php:7.2
|
||||||
|
# Use a prepared Hubzilla image to optimise pipeline duration
|
||||||
|
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.2
|
||||||
|
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- test
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
|
||||||
|
# Select what we should cache
|
||||||
|
cache:
|
||||||
|
paths:
|
||||||
|
- vendor/
|
||||||
|
- .cache/
|
||||||
|
|
||||||
|
|
||||||
|
# global variables for all jobs, if no job specific variables
|
||||||
|
variables:
|
||||||
|
# Tell composer to use the project workspace .cache folder
|
||||||
|
COMPOSER_CACHE_DIR: "$CI_PROJECT_DIR/.cache/composer"
|
||||||
|
# Ignore a Composer warning
|
||||||
|
COMPOSER_ALLOW_SUPERUSER: 1
|
||||||
|
# Configure MySQL/MariaDB service (https://hub.docker.com/_/mysql/, https://hub.docker.com/_/mariadb/)
|
||||||
|
MYSQL_DATABASE: hello_world_test
|
||||||
|
MYSQL_ROOT_PASSWORD: mysql
|
||||||
|
# Configure PostgreSQL service (https://hub.docker.com/_/postgres/)
|
||||||
|
POSTGRES_DB: ci-db
|
||||||
|
POSTGRES_USER: ci-user
|
||||||
|
POSTGRES_PASSWORD: ci-pass
|
||||||
|
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
# pecl and composer do not work with PHP production restrictions (from Hubzilla Docker image)
|
||||||
|
- if [ -f /usr/local/etc/php/conf.d/z_prod.ini ]; then mv /usr/local/etc/php/conf.d/z_prod.ini /usr/local/etc/php/conf.d/z_prod.ini.off; fi
|
||||||
|
# Install & enable Xdebug for code coverage reports
|
||||||
|
- pecl install xdebug
|
||||||
|
- docker-php-ext-enable xdebug
|
||||||
|
# Install composer
|
||||||
|
- curl -sS https://getcomposer.org/installer | php
|
||||||
|
# Install dev libraries from composer
|
||||||
|
- php ./composer.phar install --no-progress
|
||||||
|
|
||||||
|
|
||||||
|
# hidden job definition with template for MySQL/MariaDB
|
||||||
|
.job_template_mysql: &job_definition_mysql
|
||||||
|
stage: test
|
||||||
|
script:
|
||||||
|
- echo "USE $MYSQL_DATABASE; $(cat ./install/schema_mysql.sql)" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||||
|
- echo "SHOW DATABASES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||||
|
- echo "USE $MYSQL_DATABASE; SHOW TABLES;" | mysql --user=root --password="$MYSQL_ROOT_PASSWORD" --host=mysql "$MYSQL_DATABASE"
|
||||||
|
- vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-text
|
||||||
|
|
||||||
|
# hidden job definition with template for PostgreSQL
|
||||||
|
.job_template_postgres: &job_definition_postgres
|
||||||
|
stage: test
|
||||||
|
services:
|
||||||
|
- postgres:latest
|
||||||
|
script:
|
||||||
|
- export PGPASSWORD=$POSTGRES_PASSWORD
|
||||||
|
- psql --version
|
||||||
|
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT VERSION();"
|
||||||
|
# Import hubzilla's DB schema
|
||||||
|
- psql -h "postgres" -U "$POSTGRES_USER" -v ON_ERROR_STOP=1 --quiet "$POSTGRES_DB" < ./install/schema_postgres.sql
|
||||||
|
# Show databases and relations/tables of hubzilla's database
|
||||||
|
#- psql -h "postgres" -U "$POSTGRES_USER" -l
|
||||||
|
#- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "\dt;"
|
||||||
|
# Run the actual tests
|
||||||
|
- vendor/bin/phpunit --configuration tests/phpunit-pgsql.xml --testdox
|
||||||
|
|
||||||
|
# hidden job definition with artifacts config template
|
||||||
|
.artifacts_template:
|
||||||
|
artifacts: &artifacts_template
|
||||||
|
expire_in: 1 week
|
||||||
|
# Gitlab should show the results, but has problems parsing PHPUnit's junit file.
|
||||||
|
reports:
|
||||||
|
junit: tests/results/junit.xml
|
||||||
|
# Archive test results (coverage, testdox, junit)
|
||||||
|
name: "$CI_COMMIT_REF_SLUG-$CI_JOB_NAME"
|
||||||
|
paths:
|
||||||
|
- tests/results/
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.2 with MySQL 5.7
|
||||||
|
php7.2_mysql5.7:
|
||||||
|
<<: *job_definition_mysql
|
||||||
|
services:
|
||||||
|
- mysql:5.7
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.2 with MySQL 8 (latest)
|
||||||
|
php7.2_mysql8:
|
||||||
|
<<: *job_definition_mysql
|
||||||
|
services:
|
||||||
|
- name: mysql:8
|
||||||
|
command: ["--default-authentication-plugin=mysql_native_password"]
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.2 with MariaDB 10.2
|
||||||
|
php7.2_mariadb10.2:
|
||||||
|
<<: *job_definition_mysql
|
||||||
|
services:
|
||||||
|
- name: mariadb:10.2
|
||||||
|
alias: mysql
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.3 with MariaDB 10.3 (latest)
|
||||||
|
php7.3_mariadb10.3:
|
||||||
|
<<: *job_definition_mysql
|
||||||
|
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||||
|
services:
|
||||||
|
- name: mariadb:10.3
|
||||||
|
alias: mysql
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.2 with PostgreSQL latest (11)
|
||||||
|
php7.2_postgres11:
|
||||||
|
<<: *job_definition_postgres
|
||||||
|
artifacts: *artifacts_template
|
||||||
|
|
||||||
|
|
||||||
|
# PHP7.3 with PostgreSQL latest (11)
|
||||||
|
php7.3_postgres11:
|
||||||
|
<<: *job_definition_postgres
|
||||||
|
image: registry.gitlab.com/dawnbreak/hubzilla/core:php7.3
|
||||||
|
artifacts: *artifacts_template
|
||||||
|
|
||||||
|
|
||||||
|
# Generate Doxygen API Documentation and deploy it as GitLab pages
|
||||||
|
pages:
|
||||||
|
stage: deploy
|
||||||
|
cache: {}
|
||||||
|
image: php:7-cli-alpine
|
||||||
|
before_script:
|
||||||
|
- apk update
|
||||||
|
- apk add doxygen ttf-freefont graphviz
|
||||||
|
script:
|
||||||
|
- doxygen util/Doxyfile
|
||||||
|
- mv doc/html/ public/
|
||||||
|
- echo "API documentation should be accessible at https://hubzilla.frama.io/core/ soon"
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
only:
|
||||||
|
# Only generate it on main repo's master branch
|
||||||
|
- master@hubzilla/core
|
||||||
+58
-156
@@ -1,23 +1,10 @@
|
|||||||
# Hubzilla at Home next to your Router
|
# How to use
|
||||||
|
|
||||||
Run hubzilla-setup.sh for an unattended installation of hubzilla.
|
|
||||||
|
|
||||||
The script is known to work without adjustments with
|
|
||||||
|
|
||||||
+ Hardware
|
|
||||||
- Mini-PC with Debian-9.2-amd64, or
|
|
||||||
- Rapberry 3 with Raspbian, Debian-9.3
|
|
||||||
+ DynDNS
|
|
||||||
- selfHOST.de
|
|
||||||
- freedns.afraid.org
|
|
||||||
|
|
||||||
## Disclaimers
|
## Disclaimers
|
||||||
|
|
||||||
- This script does work with Debian 9 only.
|
- This script does work with Debian 10 only.
|
||||||
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
- This script has to be used on a fresh debian install only (it does not take account for a possibly already installed and configured webserver or sql implementation).
|
||||||
|
|
||||||
# Step-by-Step Overwiew
|
|
||||||
|
|
||||||
## Preconditions
|
## Preconditions
|
||||||
|
|
||||||
Hardware
|
Hardware
|
||||||
@@ -28,35 +15,27 @@ Hardware
|
|||||||
|
|
||||||
Software
|
Software
|
||||||
|
|
||||||
+ Fresh installation of Debian 9 (Stretch)
|
+ Fresh installation of Debian 10 (Stretch)
|
||||||
+ Router with open ports 80 and 443 for your Hub
|
+ Router with open ports 80 and 443 for your web server
|
||||||
|
|
||||||
## The basic steps (quick overview)
|
## How to run the script
|
||||||
|
|
||||||
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
+ Register your own domain (for example at selfHOST) or a free subdomain (for example at freeDNS)
|
||||||
+ Log on to your fresh Debian
|
+ Log on to your fresh Debian
|
||||||
- apt-get install git
|
- apt-get install git
|
||||||
- mkdir -p /var/www
|
- mkdir -p /var/www
|
||||||
- cd /var/www
|
- cd /var/www
|
||||||
- git clone https://github.com/redmatrix/hubzilla.git html
|
- git clone https://framagit.org/hubzilla/core.git html
|
||||||
- cd html/.homeinstall
|
- cd html/.homeinstall
|
||||||
- cp hubzilla-config.txt.template hubzilla-config.txt
|
- cp hubzilla-config.txt.template hubzilla-config.txt
|
||||||
- nano hubzilla-config.txt
|
- nano hubzilla-config.txt
|
||||||
- Read the comments carefully
|
- Read the comments carefully
|
||||||
- Enter your values: db pass, domain, values for dyn DNS
|
- Enter your values: db pass, domain, values for dyn DNS
|
||||||
- Make sure your external drive (for backups) is mounted
|
- Prepare your external disk for backups
|
||||||
- hubzilla-setup.sh as root
|
- hubzilla-setup.sh as root
|
||||||
- ... wait, wait, wait until the script is finised
|
- ... wait, wait, wait until the script is finised
|
||||||
- reboot
|
|
||||||
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
+ Open your domain with a browser and step throught the initial configuration of hubzilla.
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
If the check of the mail address fails when you try to register the very first user in the browser. Do...
|
|
||||||
|
|
||||||
cd /var/www/html
|
|
||||||
util/config system.do_not_check_dns 1
|
|
||||||
|
|
||||||
## Optional - Set path to imagemagick
|
## Optional - Set path to imagemagick
|
||||||
|
|
||||||
In Admin settings of hubzilla or via terminal
|
In Admin settings of hubzilla or via terminal
|
||||||
@@ -64,60 +43,74 @@ In Admin settings of hubzilla or via terminal
|
|||||||
cd /var/www/html
|
cd /var/www/html
|
||||||
util/config system.imagick_convert_path /usr/bin/convert
|
util/config system.imagick_convert_path /usr/bin/convert
|
||||||
|
|
||||||
# Step-by-Step in Detail
|
## Optional - Switch verification of email on/off
|
||||||
|
|
||||||
## Preparations Hardware
|
Do this just befor you register the user.
|
||||||
|
|
||||||
### Mini-PC
|
In Admin settings of hubzilla or via terminal
|
||||||
|
|
||||||
### Recommended: USB Drive for Backups
|
cd /var/www/html
|
||||||
|
|
||||||
The installation will create a daily backup written to an external drive.
|
Check the current setting
|
||||||
|
|
||||||
The USB drive must be compatible with the filesystems
|
util/config system verify_email
|
||||||
|
|
||||||
- ext4 (if you do not want to encrypt the USB)
|
Switch the verification on/off (1/0)
|
||||||
- LUKS + ext4 (if you want to encrypt the USB)
|
|
||||||
|
|
||||||
The backup includes
|
util/config system verify_email 0
|
||||||
|
|
||||||
- Hubzilla DB
|
## What the script will do for you...
|
||||||
- Hubzilla installation /var/www/html
|
|
||||||
- Certificates for letsencrypt
|
|
||||||
|
|
||||||
## Preparations Software
|
+ install everything required by Hubzilla, basically a web server (Apache), PHP, a database (MySQL), certbot,...
|
||||||
|
+ create a database
|
||||||
|
+ run certbot to have everything for a secure connection (httpS)
|
||||||
|
+ create a script for daily maintenance
|
||||||
|
- backup to external disk (certificates, database, /var/www/)
|
||||||
|
- renew certfificate (letsencrypt)
|
||||||
|
- update of Hubzilla
|
||||||
|
- update of Debian
|
||||||
|
- restart
|
||||||
|
+ create cron jobs for
|
||||||
|
- DynDNS (selfHOST.de or freedns.afraid.org) every 5 minutes
|
||||||
|
- Master.php for Zap/Hubzilla every 10 minutes
|
||||||
|
- daily maintenance script every day at 05:30
|
||||||
|
|
||||||
### Install Debian Linux on the Mini-PC
|
The script is known to work without adjustments with
|
||||||
|
|
||||||
Download the stable Debian at https://www.debian.org/
|
+ Hardware
|
||||||
(Debian 8 is no longer supported.)
|
- Mini-PC with Debian 10 (stretch), or
|
||||||
|
- Rapberry 3 with Raspbian, Debian 10
|
||||||
|
+ DynDNS
|
||||||
|
- selfHOST.de
|
||||||
|
- freedns.afraid.org
|
||||||
|
|
||||||
Create bootable USB drive with Debian on it.You could use
|
The script can install both [Hubzilla](https://zotlabs.org/page/hubzilla/hubzilla-project) and [Zap](https://zotlabs.com/zap/). Make sure to use the correct GIT repositories.
|
||||||
|
|
||||||
- unetbootin, https://en.wikipedia.org/wiki/UNetbootin
|
+ Hubzilla
|
||||||
- or simply the linux command "dd"
|
- core: git clone https://framagit.org/hubzilla/core.git html (in this readme)
|
||||||
|
- addons: util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons (in hubzilla-setup.sh)
|
||||||
Example for command dd...
|
+ Zap
|
||||||
|
- core: git clone https://framagit.org/zot/zap.git html (in this readme)
|
||||||
su -
|
- addons: util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons (in hubzilla-setup.sh)
|
||||||
dd if=2017-11-29-raspbian-stretch.img of=/dev/mmcblk0
|
|
||||||
|
|
||||||
Do not forget to unmount the SD card before and check if unmounted like in this example...
|
|
||||||
|
|
||||||
su -
|
|
||||||
umount /dev/mmcblk0*
|
|
||||||
df -h
|
|
||||||
|
|
||||||
|
|
||||||
Switch off your mini pc, plug in your USB drive and start the mini pc from the
|
|
||||||
stick. Install Debian. Follow the instructions of the installation.
|
|
||||||
|
|
||||||
### Configure your Router
|
# Step-by-Step - some Details
|
||||||
|
|
||||||
Open the ports 80 and 443 on your router for your Debian
|
## Preparations
|
||||||
|
|
||||||
|
## Configure your Router
|
||||||
|
|
||||||
|
Your web has to be visible in the internet.
|
||||||
|
|
||||||
|
Open the ports 80 and 443 on your router for your Debian. Make sure your web server is marked as "exposed host".
|
||||||
|
|
||||||
## Preparations Dynamic IP Address
|
## Preparations Dynamic IP Address
|
||||||
|
|
||||||
|
Follow the instructions in .homeinstall/hubzilla-config.txt.
|
||||||
|
|
||||||
|
In short...
|
||||||
|
|
||||||
Your Hubzilla must be reachable by a domain that you can type in your browser
|
Your Hubzilla must be reachable by a domain that you can type in your browser
|
||||||
|
|
||||||
cooldomain.org
|
cooldomain.org
|
||||||
@@ -132,99 +125,15 @@ There are two ways to get a domain...
|
|||||||
|
|
||||||
...for example buy at selfHOST.de
|
...for example buy at selfHOST.de
|
||||||
|
|
||||||
The cost are around 10,- € once and 1,50 € per month (2017).
|
The cost is 1,50 € per month (2019).
|
||||||
|
|
||||||
### Method 2: Register a free subdomain
|
### Method 2: Register a free subdomain
|
||||||
|
|
||||||
...for example register at freedns.afraid.org
|
...for example register at freedns.afraid.org
|
||||||
|
|
||||||
Follow the instructions in .homeinstall/hubzilla-config.txt.
|
## Note on Rasperry
|
||||||
|
|
||||||
|
The script was tested with an Raspberry 3 under Raspian, Debian 10.
|
||||||
## Install Hubzilla on your Debian
|
|
||||||
|
|
||||||
Login to your debian
|
|
||||||
(Provided your username is "you" and the name of the mini pc is "debian". You
|
|
||||||
could take the IP address instead of "debian")
|
|
||||||
|
|
||||||
ssh -X you@debian
|
|
||||||
|
|
||||||
Change to root user
|
|
||||||
|
|
||||||
su -l
|
|
||||||
|
|
||||||
Install git
|
|
||||||
|
|
||||||
apt-get install git
|
|
||||||
|
|
||||||
Make the directory for apache and change diretory to it
|
|
||||||
|
|
||||||
mkdir /var/www
|
|
||||||
cd /var/www/
|
|
||||||
|
|
||||||
Clone hubzilla from git ("git pull" will update it later)
|
|
||||||
|
|
||||||
git clone https://framagit.org/hubzilla/core html
|
|
||||||
|
|
||||||
Change to the install script
|
|
||||||
|
|
||||||
cd html/.homeinstall/
|
|
||||||
|
|
||||||
Copy the template file
|
|
||||||
|
|
||||||
cp hubzilla-config.txt.template hubzilla-config.txt
|
|
||||||
|
|
||||||
Modify the file "hubzilla-config.txt". Read the instructions there carefully and enter your values.
|
|
||||||
|
|
||||||
nano hubzilla-config.txt
|
|
||||||
|
|
||||||
Make sure your external drive (for backups) is plugged in and can be mounted as configured in "hubzilla-config.txt". Otherwise the daily backups will not work.
|
|
||||||
|
|
||||||
Run the script
|
|
||||||
|
|
||||||
./hubzilla-setup.sh
|
|
||||||
|
|
||||||
Wait... The script should not finish with an error message.
|
|
||||||
|
|
||||||
In a webbrowser open your domain.
|
|
||||||
Expected: A test page of hubzilla is shown. All checks there should be
|
|
||||||
successfull. Go on...
|
|
||||||
Expected: A page for the Hubzilla server configuration shows up.
|
|
||||||
|
|
||||||
Leave db server name "127.0.0.1" and port "0" untouched.
|
|
||||||
|
|
||||||
Enter
|
|
||||||
|
|
||||||
- DB user name = hubzilla
|
|
||||||
- DB pass word = This is the password you entered in "hubzilla-config.txt"
|
|
||||||
- DB name = hubzilla
|
|
||||||
|
|
||||||
Leave db type "MySQL" untouched.
|
|
||||||
|
|
||||||
Follow the instructions in the next pages.
|
|
||||||
|
|
||||||
Recommended: Set path to imagemagick
|
|
||||||
|
|
||||||
- in admin settings of hubzilla or
|
|
||||||
- via terminal
|
|
||||||
|
|
||||||
util/config system.imagick_convert_path /usr/bin/convert
|
|
||||||
|
|
||||||
After the daily script was executed at 05:30 (am)
|
|
||||||
|
|
||||||
- look at /var/www/html/hubzilla-daily.log
|
|
||||||
- check your backup on the external drive
|
|
||||||
- optionally view the daily log under yourdomain.org/admin/logs/
|
|
||||||
- set the logfile to var/www/html/hubzilla-daily.log
|
|
||||||
|
|
||||||
## Note for the Rasperry
|
|
||||||
|
|
||||||
The script was tested with an Raspberry 3 under Raspian (Debian 9.3, 2017-11-29-raspbian-stretch.img).
|
|
||||||
|
|
||||||
It is recommended to deinstall these programms to avoid endless updates. Use...
|
|
||||||
|
|
||||||
sudo apt-get purge wolfram-engine sonic-pi
|
|
||||||
sudo apt-get autoremove
|
|
||||||
|
|
||||||
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
|
It is recommended to run the Raspi without graphical frontend (X-Server). Use...
|
||||||
|
|
||||||
@@ -234,12 +143,5 @@ to boot the Rapsi to the client console.
|
|||||||
|
|
||||||
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
DO NOT FORGET TO CHANGE THE DEFAULT PASSWORD FOR USER PI!
|
||||||
|
|
||||||
On a Raspian Stretch (Debian 9) the validation of the mail address fails for the very first user.
|
|
||||||
This used to happen on some *bsd distros but there was some work to fix that a year ago (2017).
|
|
||||||
|
|
||||||
So if your system isn't registered in DNS or DNS isn't active do
|
|
||||||
|
|
||||||
cd /var/www/html
|
|
||||||
util/config system.do_not_check_dns 1
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
### MANDATORY - database password #############
|
### MANDATORY - database password #############
|
||||||
#
|
#
|
||||||
# Please give your database password
|
# Please give your database password
|
||||||
|
# It is better to not use blanks inside the password.
|
||||||
# Example: db_pass=pass_word_with_no_blanks_in_it
|
# Example: db_pass=pass_word_with_no_blanks_in_it
|
||||||
# Example: db_pass="this password has blanks in it"
|
|
||||||
db_pass=
|
db_pass=
|
||||||
|
|
||||||
###############################################
|
###############################################
|
||||||
@@ -18,7 +18,12 @@ db_pass=
|
|||||||
# Example: my.cooldomain.org
|
# Example: my.cooldomain.org
|
||||||
# Example: cooldomain.org
|
# Example: cooldomain.org
|
||||||
#
|
#
|
||||||
# Email is optional
|
# You might use "localhost" for a LOCAL TEST installation.
|
||||||
|
# This is usefull if you want to debug the server inside a VM.
|
||||||
|
#
|
||||||
|
# Example: localhost
|
||||||
|
#
|
||||||
|
# Email is optional if you use "localhost".
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
le_domain=
|
le_domain=
|
||||||
@@ -28,7 +33,7 @@ le_email=
|
|||||||
### OPTIONAL - selfHOST - dynamic IP address ##
|
### OPTIONAL - selfHOST - dynamic IP address ##
|
||||||
#
|
#
|
||||||
# 1. Register a domain at selfhost.de
|
# 1. Register a domain at selfhost.de
|
||||||
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 08.01.2016
|
# - choose offer "DOMAIN dynamisch" 1,50€/mon at 04/2019
|
||||||
# 2. Get your configuration for dynamic IP update
|
# 2. Get your configuration for dynamic IP update
|
||||||
# - Log in at selfhost.de
|
# - Log in at selfhost.de
|
||||||
# - go to "DynDNS Accounte"
|
# - go to "DynDNS Accounte"
|
||||||
|
|||||||
+137
-311
@@ -3,7 +3,10 @@
|
|||||||
# How to use
|
# How to use
|
||||||
# ----------
|
# ----------
|
||||||
#
|
#
|
||||||
# This file automates the installation of hubzilla under Debian Linux
|
# This file automates the installation of
|
||||||
|
# - hubzilla: https://zotlabs.org/page/hubzilla/hubzilla-project and
|
||||||
|
# - zap: https://zotlabs.com/zap/
|
||||||
|
# under Debian Linux
|
||||||
#
|
#
|
||||||
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
|
# 1) Copy the file "hubzilla-config.txt.template" to "hubzilla-config.txt"
|
||||||
# Follow the instuctions there
|
# Follow the instuctions there
|
||||||
@@ -23,18 +26,15 @@
|
|||||||
# - install
|
# - install
|
||||||
# * apache webserer,
|
# * apache webserer,
|
||||||
# * php,
|
# * php,
|
||||||
# * mysql - the database for hubzilla,
|
# * mariadb - the database for hubzilla,
|
||||||
# * phpmyadmin,
|
# * adminer,
|
||||||
# * git to download and update hubzilla itself
|
# * git to download and update addons
|
||||||
# - download hubzilla core and addons
|
|
||||||
# - configure cron
|
# - configure cron
|
||||||
# * "poller.php" for regular background prozesses of hubzilla
|
# * "Master.php" for regular background prozesses of hubzilla
|
||||||
# * to_do "apt-get update" and "apt-get dist-upgrade" to keep linux
|
# * "apt-get update" and "apt-get dist-upgrade" and "apt-get autoremove" to keep linux up-to-date
|
||||||
# up-to-date
|
# * run command to keep the IP up-to-date > DynDNS provided by selfHOST.de or freedns.afraid.org
|
||||||
# * to_do backup hubzillas database and files (rsnapshot)
|
# * backup hubzillas database and files (rsync)
|
||||||
# - configure dynamic ip with cron
|
# - run letsencrypt to create, register and use a certifacte for https
|
||||||
# - to_do letsencrypt
|
|
||||||
# - to_do redirection to https
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Discussion
|
# Discussion
|
||||||
@@ -44,26 +44,6 @@
|
|||||||
# - The script runs into installation errors for phpmyadmin if it uses
|
# - The script runs into installation errors for phpmyadmin if it uses
|
||||||
# different passwords. For the sake of simplicity one singel password.
|
# different passwords. For the sake of simplicity one singel password.
|
||||||
#
|
#
|
||||||
# Security - suhosin for PHP
|
|
||||||
# - The script does not install suhosin.
|
|
||||||
# - Is the security package suhosin usefull or not usefull?
|
|
||||||
#
|
|
||||||
# Hubzilla - email verification
|
|
||||||
# - The script switches off email verification off in all htconfig.tpl.
|
|
||||||
# Example: /var/www/html/view/en/htconfig.tpl
|
|
||||||
# - Is this a silly idea or not?
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Remove Hubzilla (for a fresh start using the script)
|
|
||||||
# ----------------------------------------------------
|
|
||||||
#
|
|
||||||
# You could use /var/www/hubzilla-remove.sh
|
|
||||||
# that is created by hubzilla-setup.sh.
|
|
||||||
#
|
|
||||||
# The script will remove (almost everything) what was installed by the script.
|
|
||||||
# After the removal you could run the script again to have a fresh install
|
|
||||||
# of all applications including hubzilla and its database.
|
|
||||||
#
|
|
||||||
# How to restore from backup
|
# How to restore from backup
|
||||||
# --------------------------
|
# --------------------------
|
||||||
#
|
#
|
||||||
@@ -75,19 +55,11 @@
|
|||||||
# - creates a daily cron that runs the hubzilla-daily.sh
|
# - creates a daily cron that runs the hubzilla-daily.sh
|
||||||
#
|
#
|
||||||
# hubzilla-daily.sh makes a (daily) backup of all relevant files
|
# hubzilla-daily.sh makes a (daily) backup of all relevant files
|
||||||
# - /var/lib/mysql/ > hubzilla database
|
# - /var/lib/mysql/ > database
|
||||||
# - /var/www/html/ > hubzilla from github
|
# - /var/www/ > hubzilla/zap from github
|
||||||
# - /var/www/letsencrypt/ > certificates
|
# - /etc/letsencrypt/ > certificates
|
||||||
#
|
#
|
||||||
# hubzilla-daily.sh writes the backup
|
# hubzilla-daily.sh writes the backup to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
|
||||||
# - either to an external disk compatible to LUKS+ext4 (see hubzilla-config.txt)
|
|
||||||
# - or to /var/cache/rsnapshot in case the external disk is not plugged in
|
|
||||||
#
|
|
||||||
# Restore backup
|
|
||||||
# - - - - - - -
|
|
||||||
#
|
|
||||||
# This was not tested yet.
|
|
||||||
# Bacically you can copy the files from the backup to the server.
|
|
||||||
#
|
#
|
||||||
# Credits
|
# Credits
|
||||||
# -------
|
# -------
|
||||||
@@ -95,8 +67,6 @@
|
|||||||
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
# The script is based on Thomas Willinghams script "debian-setup.sh"
|
||||||
# which he used to install the red#matrix.
|
# which he used to install the red#matrix.
|
||||||
#
|
#
|
||||||
# The script uses another script from https://github.com/lukas2511/letsencrypt.sh
|
|
||||||
#
|
|
||||||
# The documentation for bash is here
|
# The documentation for bash is here
|
||||||
# https://www.gnu.org/software/bash/manual/bash.html
|
# https://www.gnu.org/software/bash/manual/bash.html
|
||||||
#
|
#
|
||||||
@@ -116,9 +86,9 @@ function check_sanity {
|
|||||||
then
|
then
|
||||||
die "Debian is supported only"
|
die "Debian is supported only"
|
||||||
fi
|
fi
|
||||||
if ! grep -q 'Linux 9' /etc/issue
|
if ! grep -q 'Linux 10' /etc/issue
|
||||||
then
|
then
|
||||||
die "Linux 9 (stretch) is supported only"x
|
die "Linux 10 (buster) is supported only"x
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,11 +106,11 @@ function check_config {
|
|||||||
# backup is important and should be checked
|
# backup is important and should be checked
|
||||||
if [ -n "$backup_device_name" ]
|
if [ -n "$backup_device_name" ]
|
||||||
then
|
then
|
||||||
if [ ! -d "$backup_mount_point" ]
|
if [ ! -d "$backup_mount_point" ]
|
||||||
then
|
then
|
||||||
mkdir "$backup_mount_point"
|
mkdir "$backup_mount_point"
|
||||||
fi
|
fi
|
||||||
device_mounted=0
|
device_mounted=0
|
||||||
if fdisk -l | grep -i "$backup_device_name.*linux"
|
if fdisk -l | grep -i "$backup_device_name.*linux"
|
||||||
then
|
then
|
||||||
print_info "ok - filesystem of external device is linux"
|
print_info "ok - filesystem of external device is linux"
|
||||||
@@ -229,21 +199,17 @@ function print_warn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function stop_hubzilla {
|
function stop_hubzilla {
|
||||||
if [ -d /etc/apache2 ]
|
print_info "stopping apache webserver..."
|
||||||
then
|
systemctl stop apache2
|
||||||
print_info "stopping apache webserver..."
|
print_info "stopping mysql db..."
|
||||||
service apache2 stop
|
systemctl stop mariadb
|
||||||
fi
|
|
||||||
if [ -f /etc/init.d/mysql ]
|
|
||||||
then
|
|
||||||
print_info "stopping mysql db..."
|
|
||||||
/etc/init.d/mysql stop
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_apache {
|
function install_apache {
|
||||||
print_info "installing apache..."
|
print_info "installing apache..."
|
||||||
nocheck_install "apache2 apache2-utils"
|
nocheck_install "apache2 apache2-utils"
|
||||||
|
a2enmod rewrite
|
||||||
|
systemctl restart apache2
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_imagemagick {
|
function install_imagemagick {
|
||||||
@@ -256,6 +222,11 @@ function install_curl {
|
|||||||
nocheck_install "curl"
|
nocheck_install "curl"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function install_wget {
|
||||||
|
print_info "installing wget..."
|
||||||
|
nocheck_install "wget"
|
||||||
|
}
|
||||||
|
|
||||||
function install_sendmail {
|
function install_sendmail {
|
||||||
print_info "installing sendmail..."
|
print_info "installing sendmail..."
|
||||||
nocheck_install "sendmail sendmail-bin"
|
nocheck_install "sendmail sendmail-bin"
|
||||||
@@ -264,65 +235,47 @@ function install_sendmail {
|
|||||||
function install_php {
|
function install_php {
|
||||||
# openssl and mbstring are included in libapache2-mod-php
|
# openssl and mbstring are included in libapache2-mod-php
|
||||||
print_info "installing php..."
|
print_info "installing php..."
|
||||||
nocheck_install "libapache2-mod-php php php-pear php-curl php-mcrypt php-gd"
|
nocheck_install "libapache2-mod-php php php-pear php-curl php-gd php-mysqli php-mbstring php-xml php-zip"
|
||||||
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.0/apache2/php.ini
|
sed -i "s/^upload_max_filesize =.*/upload_max_filesize = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||||
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.0/apache2/php.ini
|
sed -i "s/^post_max_size =.*/post_max_size = 100M/g" /etc/php/7.3/apache2/php.ini
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_mysql {
|
function install_mysql {
|
||||||
# http://www.microhowto.info/howto/perform_an_unattended_installation_of_a_debian_package.html
|
|
||||||
#
|
|
||||||
# To determine the required package name, key and type you can perform
|
|
||||||
# a trial installation then search the configuration database.
|
|
||||||
#
|
|
||||||
# debconf-get-selections | grep mysql-server
|
|
||||||
#
|
|
||||||
# The command debconf-get-selections is provided by the package
|
|
||||||
# debconf-utils, which you may need to install.
|
|
||||||
#
|
|
||||||
# apt-get install debconf-utils
|
|
||||||
#
|
|
||||||
# If you want to supply an answer to a configuration question but do not
|
|
||||||
# want to be prompted for it then this can be arranged by preseeding the
|
|
||||||
# DebConf database with the required information.
|
|
||||||
#
|
|
||||||
# echo mysql-server mysql-server/root_password password xyzzy | debconf-set-selections
|
|
||||||
# echo mysql-server mysql-server/root_password_again password xyzzy | debconf-set-selections
|
|
||||||
#
|
|
||||||
print_info "installing mysql..."
|
print_info "installing mysql..."
|
||||||
if [ -z "$mysqlpass" ]
|
if [ -z "$mysqlpass" ]
|
||||||
then
|
then
|
||||||
die "mysqlpass not set in $configfile"
|
die "mysqlpass not set in $configfile"
|
||||||
fi
|
fi
|
||||||
echo mysql-server mysql-server/root_password password $mysqlpass | debconf-set-selections
|
if type mysql ; then
|
||||||
echo mysql-server mysql-server/root_password_again password $mysqlpass | debconf-set-selections
|
echo "Yes, mysql is installed"
|
||||||
nocheck_install "php-mysql mysql-server mysql-client"
|
else
|
||||||
|
echo "mariadb-server"
|
||||||
|
nocheck_install "mariadb-server"
|
||||||
|
systemctl status mariadb
|
||||||
|
systemctl start mariadb
|
||||||
|
mysql --user=root <<_EOF_
|
||||||
|
UPDATE mysql.user SET Password=PASSWORD('${db_root_password}') WHERE User='root';
|
||||||
|
DELETE FROM mysql.user WHERE User='';
|
||||||
|
DROP DATABASE IF EXISTS test;
|
||||||
|
DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
_EOF_
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_phpmyadmin {
|
function install_adminer {
|
||||||
print_info "installing phpmyadmin..."
|
print_info "installing adminer..."
|
||||||
if [ -z "$phpmyadminpass" ]
|
nocheck_install "adminer"
|
||||||
|
if [ ! -f /etc/adminer/adminer.conf ]
|
||||||
then
|
then
|
||||||
die "phpmyadminpass not set in $configfile"
|
echo "Alias /adminer /usr/share/adminer/adminer" > /etc/adminer/adminer.conf
|
||||||
|
ln -s /etc/adminer/adminer.conf /etc/apache2/conf-available/adminer.conf
|
||||||
|
else
|
||||||
|
print_info "file /etc/adminer/adminer.conf exists already"
|
||||||
fi
|
fi
|
||||||
echo phpmyadmin phpmyadmin/setup-password password $phpmyadminpass | debconf-set-selections
|
|
||||||
echo phpmyadmin phpmyadmin/mysql/app-pass password $phpmyadminpass | debconf-set-selections
|
|
||||||
echo phpmyadmin phpmyadmin/app-password-confirm password $phpmyadminpass | debconf-set-selections
|
|
||||||
echo phpmyadmin phpmyadmin/mysql/admin-pass password $phpmyadminpass | debconf-set-selections
|
|
||||||
echo phpmyadmin phpmyadmin/password-confirm password $phpmyadminpass | debconf-set-selections
|
|
||||||
echo phpmyadmin phpmyadmin/reconfigure-webserver multiselect apache2 | debconf-set-selections
|
|
||||||
nocheck_install "phpmyadmin"
|
|
||||||
|
|
||||||
# It seems to be not neccessary to check rewrite.load because it comes
|
|
||||||
# with the installation. To be sure you could check this manually by:
|
|
||||||
#
|
|
||||||
# nano /etc/apache2/mods-available/rewrite.load
|
|
||||||
#
|
|
||||||
# You should find the content:
|
|
||||||
#
|
|
||||||
# LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so
|
|
||||||
|
|
||||||
a2enmod rewrite
|
a2enmod rewrite
|
||||||
|
|
||||||
if [ ! -f /etc/apache2/apache2.conf ]
|
if [ ! -f /etc/apache2/apache2.conf ]
|
||||||
then
|
then
|
||||||
die "could not find file /etc/apache2/apache2.conf"
|
die "could not find file /etc/apache2/apache2.conf"
|
||||||
@@ -330,12 +283,10 @@ function install_phpmyadmin {
|
|||||||
sed -i \
|
sed -i \
|
||||||
"s/AllowOverride None/AllowOverride all/" \
|
"s/AllowOverride None/AllowOverride all/" \
|
||||||
/etc/apache2/apache2.conf
|
/etc/apache2/apache2.conf
|
||||||
if [ -z "`grep 'Include /etc/phpmyadmin/apache.conf' /etc/apache2/apache2.conf`" ]
|
|
||||||
then
|
a2enconf adminer
|
||||||
echo "Include /etc/phpmyadmin/apache.conf" >> /etc/apache2/apache2.conf
|
systemctl restart mariadb
|
||||||
fi
|
systemctl reload apache2
|
||||||
service apache2 restart
|
|
||||||
/etc/init.d/mysql start
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function create_hubzilla_db {
|
function create_hubzilla_db {
|
||||||
@@ -352,6 +303,7 @@ function create_hubzilla_db {
|
|||||||
then
|
then
|
||||||
die "hubzilla_db_pass not set in $configfile"
|
die "hubzilla_db_pass not set in $configfile"
|
||||||
fi
|
fi
|
||||||
|
systemctl restart mariadb
|
||||||
Q1="CREATE DATABASE IF NOT EXISTS $hubzilla_db_name;"
|
Q1="CREATE DATABASE IF NOT EXISTS $hubzilla_db_name;"
|
||||||
Q2="GRANT USAGE ON *.* TO $hubzilla_db_user@localhost IDENTIFIED BY '$hubzilla_db_pass';"
|
Q2="GRANT USAGE ON *.* TO $hubzilla_db_user@localhost IDENTIFIED BY '$hubzilla_db_pass';"
|
||||||
Q3="GRANT ALL PRIVILEGES ON $hubzilla_db_name.* to $hubzilla_db_user@localhost identified by '$hubzilla_db_pass';"
|
Q3="GRANT ALL PRIVILEGES ON $hubzilla_db_name.* to $hubzilla_db_user@localhost identified by '$hubzilla_db_pass';"
|
||||||
@@ -449,11 +401,11 @@ function configure_cron_selfhost {
|
|||||||
print_info "configure cron for selfhost..."
|
print_info "configure cron for selfhost..."
|
||||||
if [ -z "$selfhost_user" ]
|
if [ -z "$selfhost_user" ]
|
||||||
then
|
then
|
||||||
print_info "freedns is not configured because freedns_key is empty in $configfile"
|
print_info "selfhost is not configured because selfhost_key is empty in $configfile"
|
||||||
else
|
else
|
||||||
# Use cron for dynamich ip update
|
# Use cron for dynamich ip update
|
||||||
# - at reboot
|
# - at reboot
|
||||||
# - every 30 minutes
|
# - every 5 minutes
|
||||||
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
|
if [ -z "`grep 'selfhost-updater.sh' /etc/crontab`" ]
|
||||||
then
|
then
|
||||||
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
echo "@reboot root bash /etc/selfhost/selfhost-updater.sh update > /dev/null 2>&1" >> /etc/crontab
|
||||||
@@ -471,89 +423,13 @@ function install_letsencrypt {
|
|||||||
then
|
then
|
||||||
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
die "Failed to install let's encrypt: 'le_domain' is empty in $configfile"
|
||||||
fi
|
fi
|
||||||
# configure apache
|
if [ -z "$le_email" ]
|
||||||
apache_le_conf=/etc/apache2/sites-available/le-default.conf
|
|
||||||
if [ -f $apache_le_conf ]
|
|
||||||
then
|
then
|
||||||
print_info "$apache_le_conf exist already"
|
die "Failed to install let's encrypt: 'le_email' is empty in $configfile"
|
||||||
else
|
|
||||||
cat > $apache_le_conf <<END
|
|
||||||
# letsencrypt default Apache configuration
|
|
||||||
Alias /.well-known/acme-challenge /var/www/letsencrypt
|
|
||||||
|
|
||||||
<Directory /var/www/letsencrypt>
|
|
||||||
Options FollowSymLinks
|
|
||||||
Allow from all
|
|
||||||
</Directory>
|
|
||||||
END
|
|
||||||
a2ensite le-default.conf
|
|
||||||
service apache2 restart
|
|
||||||
fi
|
fi
|
||||||
# download the shell script
|
nocheck_install "certbot python-certbot-apache"
|
||||||
if [ -d $le_dir ]
|
print_info "run certbot ..."
|
||||||
then
|
certbot --apache -w /var/www/html -d $le_domain -m $le_email --agree-tos --non-interactive --redirect --hsts --uir
|
||||||
print_info "letsenrypt exists already (nothing downloaded > no certificate created and registered)"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
git clone https://github.com/lukas2511/dehydrated $le_dir
|
|
||||||
cd $le_dir
|
|
||||||
# create config file for letsencrypt.sh
|
|
||||||
echo "WELLKNOWN=$le_dir" > $le_dir/config.sh
|
|
||||||
if [ -n "$le_email" ]
|
|
||||||
then
|
|
||||||
echo "CONTACT_EMAIL=$le_email" >> $le_dir/config.sh
|
|
||||||
fi
|
|
||||||
# create domain file for letsencrypt.sh
|
|
||||||
# WATCH THIS:
|
|
||||||
# - It did not work wit "sub.domain.org www.sub.domain.org".
|
|
||||||
# - So just use "sub.domain.org" only!
|
|
||||||
echo "$le_domain" > $le_dir/domains.txt
|
|
||||||
# test apache config for letsencrpyt
|
|
||||||
url_http=http://$le_domain/.well-known/acme-challenge/domains.txt
|
|
||||||
wget_output=$(wget -nv --spider --max-redirect 0 $url_http)
|
|
||||||
if [ $? -ne 0 ]
|
|
||||||
then
|
|
||||||
die "Failed to load $url_http"
|
|
||||||
fi
|
|
||||||
# accept terms of service of letsencrypt
|
|
||||||
./dehydrated --register --accept-terms
|
|
||||||
# run script dehydrated
|
|
||||||
#
|
|
||||||
./dehydrated --cron --config $le_dir/config.sh
|
|
||||||
}
|
|
||||||
|
|
||||||
function configure_apache_for_https {
|
|
||||||
print_info "configuring apache to use httpS ..."
|
|
||||||
# letsencrypt.sh
|
|
||||||
#
|
|
||||||
# "${BASEDIR}/certs/${domain}/privkey.pem"
|
|
||||||
# "${BASEDIR}/certs/${domain}/cert.pem"
|
|
||||||
# "${BASEDIR}/certs/${domain}/fullchain.pem"
|
|
||||||
#
|
|
||||||
SSLCertificateFile=${le_dir}/certs/${le_domain}/cert.pem
|
|
||||||
SSLCertificateKeyFile=${le_dir}/certs/${le_domain}/privkey.pem
|
|
||||||
SSLCertificateChainFile=${le_dir}/certs/${le_domain}/fullchain.pem
|
|
||||||
if [ ! -f $SSLCertificateFile ]
|
|
||||||
then
|
|
||||||
print_warn "Failed to configure apache for httpS: Missing certificate file $SSLCertificateFile"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
# make sure that the ssl mode is enabled
|
|
||||||
print_info "...configuring apache to use httpS - a2enmod ssl ..."
|
|
||||||
a2enmod ssl
|
|
||||||
# modify apach' ssl conf file
|
|
||||||
if grep -i "ServerName" $sslconf
|
|
||||||
then
|
|
||||||
print_info "seems that apache was already configered to use httpS with $sslconf"
|
|
||||||
else
|
|
||||||
sed -i "s/ServerAdmin.*$/ServerAdmin webmaster@localhost\\n ServerName ${le_domain}/" $sslconf
|
|
||||||
fi
|
|
||||||
sed -i s#/etc/ssl/certs/ssl-cert-snakeoil.pem#$SSLCertificateFile# $sslconf
|
|
||||||
sed -i s#/etc/ssl/private/ssl-cert-snakeoil.key#$SSLCertificateKeyFile# $sslconf
|
|
||||||
sed -i s#/etc/apache2/ssl.crt/server-ca.crt#$SSLCertificateChainFile# $sslconf
|
|
||||||
sed -i s/#SSLCertificateChainFile/SSLCertificateChainFile/ $sslconf
|
|
||||||
# apply changes
|
|
||||||
a2ensite default-ssl.conf
|
|
||||||
service apache2 restart
|
service apache2 restart
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,9 +446,19 @@ function check_https {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function install_hubzilla {
|
function install_hubzilla {
|
||||||
print_info "installing hubzilla addons..."
|
print_info "installing addons..."
|
||||||
cd /var/www/html/
|
cd /var/www/html/
|
||||||
util/add_addon_repo https://framagit.org/hubzilla/addons.git hzaddons
|
if git remote -v | grep -i "origin.*hubzilla.*core"
|
||||||
|
then
|
||||||
|
print_info "hubzilla"
|
||||||
|
util/add_addon_repo https://framagit.org/hubzilla/addons hzaddons
|
||||||
|
elif git remote -v | grep -i "origin.*zap.*core"
|
||||||
|
then
|
||||||
|
print_info "zap"
|
||||||
|
util/add_addon_repo https://framagit.org/zot/zap-addons.git zaddons
|
||||||
|
else
|
||||||
|
die "neither zap nor hubzilla repository > did not install addons or zap/hubzilla"
|
||||||
|
fi
|
||||||
mkdir -p "store/[data]/smarty3"
|
mkdir -p "store/[data]/smarty3"
|
||||||
chmod -R 777 store
|
chmod -R 777 store
|
||||||
touch .htconfig.php
|
touch .htconfig.php
|
||||||
@@ -582,58 +468,12 @@ function install_hubzilla {
|
|||||||
chown root:www-data /var/www/html/
|
chown root:www-data /var/www/html/
|
||||||
chown root:www-data /var/www/html/.htaccess
|
chown root:www-data /var/www/html/.htaccess
|
||||||
chmod 0644 /var/www/html/.htaccess
|
chmod 0644 /var/www/html/.htaccess
|
||||||
# try to switch off email registration
|
print_info "installed addons"
|
||||||
sed -i "s/verify_email.*1/verify_email'] = 0/" /var/www/html/view/*/ht*
|
|
||||||
if [ -n "`grep -r 'verify_email.*1' /var/www/html/view/`" ]
|
|
||||||
then
|
|
||||||
print_warn "Hubzillas registration prozess might have email verification switched on."
|
|
||||||
fi
|
|
||||||
print_info "installed hubzilla"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function rewrite_to_https {
|
function install_rsync {
|
||||||
print_info "configuring apache to redirect http to httpS ..."
|
print_info "installing rsync..."
|
||||||
htaccessfile=/var/www/html/.htaccess
|
nocheck_install "rsync"
|
||||||
if grep -i "https" $htaccessfile
|
|
||||||
then
|
|
||||||
print_info "...configuring apache to redirect http to httpS was already done in $htaccessfile"
|
|
||||||
else
|
|
||||||
sed -i "s#QSA]#QSA]\\n RewriteCond %{SERVER_PORT} !^443$\\n RewriteRule (.*) https://%{HTTP_HOST}/$1 [R=301,L]#" $htaccessfile
|
|
||||||
fi
|
|
||||||
service apache2 restart
|
|
||||||
}
|
|
||||||
|
|
||||||
# This will allways overwrite both config files
|
|
||||||
# - internal disk
|
|
||||||
# - external disk (LUKS + ext4)
|
|
||||||
# of rsnapshot for hubzilla
|
|
||||||
function install_rsnapshot {
|
|
||||||
print_info "installing rsnapshot..."
|
|
||||||
nocheck_install "rsnapshot"
|
|
||||||
# internal disk
|
|
||||||
cp -f /etc/rsnapshot.conf $snapshotconfig
|
|
||||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig
|
|
||||||
sed -i "s/^backup/#backup/" $snapshotconfig
|
|
||||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig
|
|
||||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig
|
|
||||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig
|
|
||||||
# external disk
|
|
||||||
if [ -n "$backup_device_name" ]
|
|
||||||
then
|
|
||||||
cp -f /etc/rsnapshot.conf $snapshotconfig_external_device
|
|
||||||
sed -i "s#snapshot_root.*#snapshot_root $backup_mount_point#" $snapshotconfig_external_device
|
|
||||||
sed -i "/alpha/s/6/30/" $snapshotconfig_external_device
|
|
||||||
sed -i "s/^cmd_cp/#cmd_cp/" $snapshotconfig_external_device
|
|
||||||
sed -i "s/^backup/#backup/" $snapshotconfig_external_device
|
|
||||||
if [ -z "`grep 'letsencrypt' $snapshotconfig_external_device`" ]
|
|
||||||
then
|
|
||||||
echo "backup /var/lib/mysql/ localhost/" >> $snapshotconfig_external_device
|
|
||||||
echo "backup /var/www/html/ localhost/" >> $snapshotconfig_external_device
|
|
||||||
echo "backup /var/www/letsencrypt/ localhost/" >> $snapshotconfig_external_device
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_info "No backup configuration (rsnapshot) for external device configured. Reason: backup_device_name and/or backup_device_pass not given in $configfile"
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function install_cryptosetup {
|
function install_cryptosetup {
|
||||||
@@ -644,28 +484,28 @@ function install_cryptosetup {
|
|||||||
function configure_cron_daily {
|
function configure_cron_daily {
|
||||||
print_info "configuring cron..."
|
print_info "configuring cron..."
|
||||||
# every 10 min for poller.php
|
# every 10 min for poller.php
|
||||||
if [ -z "`grep 'poller.php' /etc/crontab`" ]
|
if [ -z "`grep 'Master.php' /etc/crontab`" ]
|
||||||
then
|
then
|
||||||
echo "*/10 * * * * www-data cd /var/www/html; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
|
echo "*/10 * * * * www-data cd /var/www/html; php Zotlabs/Daemon/Master.php Cron >> /dev/null 2>&1" >> /etc/crontab
|
||||||
fi
|
fi
|
||||||
# Run external script daily at 05:30
|
# Run external script daily at 05:30
|
||||||
# - stop apache and mysql-server
|
# - stop apache and mysql-server
|
||||||
# - backup hubzilla
|
# - renew the certificate of letsencrypt
|
||||||
|
# - backup db, files (/var/www/html), certificates if letsencrypt
|
||||||
# - update hubzilla core and addon
|
# - update hubzilla core and addon
|
||||||
# - update and upgrade linux
|
# - update and upgrade linux
|
||||||
# - reboot
|
# - reboot is done by "shutdown -h now" because "reboot" hangs sometimes depending on the system
|
||||||
echo "#!/bin/sh" > /var/www/$hubzilladaily
|
echo "#!/bin/sh" > /var/www/$hubzilladaily
|
||||||
echo "#" >> /var/www/$hubzilladaily
|
echo "#" >> /var/www/$hubzilladaily
|
||||||
echo "echo \" \"" >> /var/www/$hubzilladaily
|
echo "echo \" \"" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"+++ \$(date) +++\"" >> /var/www/$hubzilladaily
|
echo "echo \"+++ \$(date) +++\"" >> /var/www/$hubzilladaily
|
||||||
echo "echo \" \"" >> /var/www/$hubzilladaily
|
echo "echo \" \"" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - renew certificate...\"" >> /var/www/$hubzilladaily
|
||||||
echo "bash $le_dir/dehydrated --cron --config $le_dir/config.sh" >> /var/www/$hubzilladaily
|
echo "certbot renew --noninteractive" >> /var/www/$hubzilladaily
|
||||||
echo "#" >> /var/www/$hubzilladaily
|
echo "#" >> /var/www/$hubzilladaily
|
||||||
echo "# stop hubzilla" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - stopping apache and mysql...\"" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - stoping apache and mysql...\"" >> /var/www/$hubzilladaily
|
|
||||||
echo "service apache2 stop" >> /var/www/$hubzilladaily
|
echo "service apache2 stop" >> /var/www/$hubzilladaily
|
||||||
echo "/etc/init.d/mysql stop # to avoid inconsistancies" >> /var/www/$hubzilladaily
|
echo "/etc/init.d/mysql stop # to avoid inconsistencies" >> /var/www/$hubzilladaily
|
||||||
echo "#" >> /var/www/$hubzilladaily
|
echo "#" >> /var/www/$hubzilladaily
|
||||||
echo "# backup" >> /var/www/$hubzilladaily
|
echo "# backup" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - try to mount external device for backup...\"" >> /var/www/$hubzilladaily
|
||||||
@@ -696,11 +536,13 @@ echo " if mount $backup_device_name $backup_mount_point" >> /var/www/$hub
|
|||||||
echo " then" >> /var/www/$hubzilladaily
|
echo " then" >> /var/www/$hubzilladaily
|
||||||
echo " device_mounted=1" >> /var/www/$hubzilladaily
|
echo " device_mounted=1" >> /var/www/$hubzilladaily
|
||||||
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
|
echo " echo \"device $backup_device_name is now mounted. Starting backup...\"" >> /var/www/$hubzilladaily
|
||||||
echo " rsnapshot -c $snapshotconfig_external_device alpha" >> /var/www/$hubzilladaily
|
echo " rsync -a --delete /var/lib/mysql/ /media/hubzilla_backup/mysql" >> /var/www/$hubzilladaily
|
||||||
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
|
echo " rsync -a --delete /var/www/ /media/hubzilla_backup/www" >> /var/www/$hubzilladaily
|
||||||
echo " df -h" >> /var/www/$hubzilladaily
|
echo " rsync -a --delete /etc/letsencrypt/ /media/hubzilla_backup/letsencrypt" >> /var/www/$hubzilladaily
|
||||||
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
echo " echo \"\$(date) - disk sizes...\"" >> /var/www/$hubzilladaily
|
||||||
echo " du -h $backup_mount_point | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
echo " df -h" >> /var/www/$hubzilladaily
|
||||||
|
echo " echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
||||||
|
echo " du -h $backup_mount_point | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||||
echo " echo \"unmounting backup device...\"" >> /var/www/$hubzilladaily
|
echo " echo \"unmounting backup device...\"" >> /var/www/$hubzilladaily
|
||||||
echo " umount $backup_mount_point" >> /var/www/$hubzilladaily
|
echo " umount $backup_mount_point" >> /var/www/$hubzilladaily
|
||||||
echo " else" >> /var/www/$hubzilladaily
|
echo " else" >> /var/www/$hubzilladaily
|
||||||
@@ -722,18 +564,16 @@ echo "echo \"\$(date) - db size...\"" >> /var/www/$hubzilladaily
|
|||||||
echo "du -h /var/lib/mysql/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
echo "du -h /var/lib/mysql/ | grep mysql/hubzilla" >> /var/www/$hubzilladaily
|
||||||
echo "#" >> /var/www/$hubzilladaily
|
echo "#" >> /var/www/$hubzilladaily
|
||||||
echo "# update" >> /var/www/$hubzilladaily
|
echo "# update" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - updating dehydrated...\"" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - updating core and addons...\"" >> /var/www/$hubzilladaily
|
||||||
echo "git -C /var/www/letsencrypt/ pull" >> /var/www/$hubzilladaily
|
|
||||||
echo "echo \"\$(date) - updating hubhilla core...\"" >> /var/www/$hubzilladaily
|
|
||||||
echo "(cd /var/www/html/ ; util/udall)" >> /var/www/$hubzilladaily
|
echo "(cd /var/www/html/ ; util/udall)" >> /var/www/$hubzilladaily
|
||||||
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
|
echo "chown -R www-data:www-data /var/www/html/ # make all accessable for the webserver" >> /var/www/$hubzilladaily
|
||||||
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
|
echo "chown root:www-data /var/www/html/.htaccess" >> /var/www/$hubzilladaily
|
||||||
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
|
echo "chmod 0644 /var/www/html/.htaccess # www-data can read but not write it" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - updating linux...\"" >> /var/www/$hubzilladaily
|
||||||
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$hubzilladaily
|
echo "apt-get -q -y update && apt-get -q -y dist-upgrade && apt-get -q -y autoremove # update linux and upgrade" >> /var/www/$hubzilladaily
|
||||||
echo "echo \"\$(date) - Backup hubzilla and update linux finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
echo "echo \"\$(date) - Backup and update finished. Rebooting...\"" >> /var/www/$hubzilladaily
|
||||||
echo "#" >> /var/www/$hubzilladaily
|
echo "#" >> /var/www/$hubzilladaily
|
||||||
echo "reboot" >> /var/www/$hubzilladaily
|
echo "shutdown -r now" >> /var/www/$hubzilladaily
|
||||||
|
|
||||||
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
|
if [ -z "`grep 'hubzilla-daily.sh' /etc/crontab`" ]
|
||||||
then
|
then
|
||||||
@@ -745,38 +585,6 @@ echo "reboot" >> /var/www/$hubzilladaily
|
|||||||
print_info "configured cron for updates/upgrades"
|
print_info "configured cron for updates/upgrades"
|
||||||
}
|
}
|
||||||
|
|
||||||
function write_uninstall_script {
|
|
||||||
print_info "writing uninstall script..."
|
|
||||||
|
|
||||||
cat > /var/www/hubzilla-remove.sh <<END
|
|
||||||
#!/bin/sh
|
|
||||||
#
|
|
||||||
# This script removes Hubzilla.
|
|
||||||
# You might do this for a fresh start using the script.
|
|
||||||
# The script will remove (almost everything) what was installed by the script,
|
|
||||||
# all applications including hubzilla and its database.
|
|
||||||
#
|
|
||||||
# Backup the certificates of letsencrypt (you never know)
|
|
||||||
cp -a /var/www/letsencrypt/ ~/backup_le_certificats
|
|
||||||
#
|
|
||||||
# Removal
|
|
||||||
apt-get remove apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
|
|
||||||
apt-get purge apache2 apache2-utils libapache2-mod-php5 php5 php-pear php5-xcache php5-curl php5-mcrypt php5-gd php5-mysql mysql-server mysql-client phpmyadmin
|
|
||||||
apt-get autoremove
|
|
||||||
apt-get clean
|
|
||||||
rm /etc/rsnapshot_hubzilla.conf
|
|
||||||
rm /etc/rsnapshot_hubzilla_external_device.conf
|
|
||||||
rm -R /etc/apache2/
|
|
||||||
rm -R /var/lib/mysql/
|
|
||||||
rm -R /var/www
|
|
||||||
rm -R /etc/selfhost/
|
|
||||||
# uncomment the next line if you want to remove the backups
|
|
||||||
# rm -R /var/cache/rsnapshot
|
|
||||||
nano /etc/crontab # remove entries there manually
|
|
||||||
END
|
|
||||||
chmod -x /var/www/hubzilla-remove.sh
|
|
||||||
}
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# START OF PROGRAM
|
# START OF PROGRAM
|
||||||
########################################################################
|
########################################################################
|
||||||
@@ -791,12 +599,7 @@ source $configfile
|
|||||||
selfhostdir=/etc/selfhost
|
selfhostdir=/etc/selfhost
|
||||||
selfhostscript=selfhost-updater.sh
|
selfhostscript=selfhost-updater.sh
|
||||||
hubzilladaily=hubzilla-daily.sh
|
hubzilladaily=hubzilla-daily.sh
|
||||||
plugins_update=.homeinstall/plugins_update.sh
|
|
||||||
snapshotconfig=/etc/rsnapshot_hubzilla.conf
|
|
||||||
snapshotconfig_external_device=/etc/rsnapshot_hubzilla_external_device.conf
|
|
||||||
backup_mount_point=/media/hubzilla_backup
|
backup_mount_point=/media/hubzilla_backup
|
||||||
le_dir=/var/www/letsencrypt
|
|
||||||
sslconf=/etc/apache2/sites-available/default-ssl.conf
|
|
||||||
|
|
||||||
#set -x # activate debugging from here
|
#set -x # activate debugging from here
|
||||||
|
|
||||||
@@ -804,27 +607,50 @@ check_config
|
|||||||
stop_hubzilla
|
stop_hubzilla
|
||||||
update_upgrade
|
update_upgrade
|
||||||
install_curl
|
install_curl
|
||||||
|
install_wget
|
||||||
install_sendmail
|
install_sendmail
|
||||||
install_apache
|
install_apache
|
||||||
install_imagemagick
|
install_imagemagick
|
||||||
install_php
|
install_php
|
||||||
install_mysql
|
install_mysql
|
||||||
install_phpmyadmin
|
install_adminer
|
||||||
create_hubzilla_db
|
create_hubzilla_db
|
||||||
run_freedns
|
run_freedns
|
||||||
install_run_selfhost
|
install_run_selfhost
|
||||||
ping_domain
|
ping_domain
|
||||||
configure_cron_freedns
|
configure_cron_freedns
|
||||||
configure_cron_selfhost
|
configure_cron_selfhost
|
||||||
install_letsencrypt
|
|
||||||
configure_apache_for_https
|
if [ "$le_domain" != "localhost" ]
|
||||||
check_https
|
then
|
||||||
|
install_letsencrypt
|
||||||
|
configure_apache_for_https
|
||||||
|
check_https
|
||||||
|
else
|
||||||
|
print_info "is localhost - skipped installation of letsencrypt and configuration of apache for https"
|
||||||
|
fi
|
||||||
|
|
||||||
install_hubzilla
|
install_hubzilla
|
||||||
rewrite_to_https
|
|
||||||
install_rsnapshot
|
if [ "$le_domain" != "localhost" ]
|
||||||
|
then
|
||||||
|
rewrite_to_https
|
||||||
|
install_rsnapshot
|
||||||
|
else
|
||||||
|
print_info "is localhost - skipped rewrite to https and installation of rsnapshot"
|
||||||
|
fi
|
||||||
|
|
||||||
configure_cron_daily
|
configure_cron_daily
|
||||||
install_cryptosetup
|
|
||||||
write_uninstall_script
|
if [ "$le_domain" != "localhost" ]
|
||||||
|
then
|
||||||
|
install_cryptosetup
|
||||||
|
write_uninstall_script
|
||||||
|
else
|
||||||
|
print_info "is localhost - skipped installation of cryptosetup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#set +x # stop debugging from here
|
#set +x # stop debugging from here
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,608 @@
|
|||||||
Hubzilla 3.6 (????-??-??)
|
Hubzilla 4.6 (2019-12-04)
|
||||||
|
- Improve opengraph support for channels
|
||||||
|
- Add opengraph support for articles
|
||||||
|
- Update abook_connected for RSS feeds only if handle_feed() returned success
|
||||||
|
- Do not embed PDF files by default but allow to enabled this feature in security options
|
||||||
|
- Check if file exists before we include it in the router
|
||||||
|
- Update jquery to version 3.4.1
|
||||||
|
- Update composer libraries
|
||||||
|
- Remove old and unused javascript libraries
|
||||||
|
- Improved BBcode to Markdown conversion
|
||||||
|
- Introduce inline SVG support via BBcode
|
||||||
|
- Sanitize title on Atom/RSS feed import
|
||||||
|
- Improved HTTP headers cache support for photos
|
||||||
|
- Add date headers to signed headers
|
||||||
|
- Add check if item['tag'] is an array
|
||||||
|
- Add hook comments_are_now_closed for addons to override date based comment closure
|
||||||
|
- Change mysql schema for item.llink and item.plink for new installs from char(191) to text
|
||||||
|
- Improved photo cache expiration
|
||||||
|
- Improved plural function processing on translation strings creation from .po file with util/po2php utlility
|
||||||
|
- Improved support for CDN/Infrastructure caching (especially profile images)
|
||||||
|
- New japanese translation
|
||||||
|
- Add connect button for non-zot networks not connected in current location
|
||||||
|
- Allow to send forum channels wall2wall or sent by mentions post to external sites via addons
|
||||||
|
- Allow addons to process forum posts published through mentions
|
||||||
|
- Improved internal routing for ActivityPub messages
|
||||||
|
- Improved admin documentation
|
||||||
|
- Add ITEM_TYPE_CUSTOM and hooks to permit addons to create and distribute custom item types
|
||||||
|
- Support "comment policy" in Zot6 communications
|
||||||
|
- Add selected text as quote on reply if comment button is used
|
||||||
|
- Add more nofollow tags to links to discourage backlink farmers
|
||||||
|
- Improved conversion of emoji reactions from zot to zot6
|
||||||
|
- Add CardDAV/CalDAV autodiscovery
|
||||||
|
- Label source project of zotfeed since it is not completely compatible across projects
|
||||||
|
- Update homeinstall script
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
- Fix once cached embedded content is used and stored forever
|
||||||
|
- Fix wildcard tag issue
|
||||||
|
- Fix duplicate attachment in jot fileupload
|
||||||
|
- Fix regression with audio file upload
|
||||||
|
- Fix can not edit menu name or title (#1402)
|
||||||
|
- Fix pagination encoding issue for some server setups
|
||||||
|
- Fix Zap->Hubzilla event title compatibility
|
||||||
|
- Fix event timezones for Zot6
|
||||||
|
- Fix missing summary in mod article_edit
|
||||||
|
- Fix PHP warning failed to write session data using user defined save handler
|
||||||
|
- Fix possible thumbnails distortion on rebuild with util/thumbrepair utility
|
||||||
|
- Fix issues with image import to zot6
|
||||||
|
- Fix attachment permissions on clonned channels sync
|
||||||
|
- Fix entries without sitekey returned from DB in queue_deliver() and Lib/Queue
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- Twitter: send tweet even if attached image uploading was unsuccessful
|
||||||
|
- Livejournal: add link to original post option
|
||||||
|
- Flashcards: update to version 2.08
|
||||||
|
- Pubcrawl: compatibility changes to support pixelfed
|
||||||
|
- Cart: update paypal button to API v2
|
||||||
|
- Photocache: rework for speed and lower memory consumption
|
||||||
|
- Photocache: etag support for cached photos
|
||||||
|
- Photocache: purge cache on addon uninstall
|
||||||
|
- Openstreetmap: fix regression if no default values set
|
||||||
|
- Livejournal: allow send posts from non channel owner
|
||||||
|
- Pubcrawl: fix event timezones
|
||||||
|
- Pubcrawl: better ActivityPub channel URL detection
|
||||||
|
- Pubcrawl: fix comments delivery for other channels on the same hub
|
||||||
|
- New addon "workflow" with initial basic "issue tracker" capability
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.4.1 (2019-08-16)
|
||||||
|
- Fix wrong profile photo displayed when previewing and editing profiles
|
||||||
|
- Fix regression from 4.4 which prevented encrypted signatures from being used for encrypted messages
|
||||||
|
- Fix typo in queueworker addon which broke filtering of duplicate work
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.4 (2019-08-13)
|
||||||
|
- Change primary directory from zotadel.net to hub.netzgemeinde.eu (requested by zotadel admin)
|
||||||
|
- Add Russian context help files
|
||||||
|
- Replace plink URL with share tag if possible
|
||||||
|
- Catch and exclude trailing punctuation while URL embedding
|
||||||
|
- Do not limit channel if service class property value is set to zero
|
||||||
|
- Streamline keyId and creator/actor
|
||||||
|
- Add daemon_master_summon hook
|
||||||
|
- Serve static files directly if not caught by web server
|
||||||
|
- Update cacert.pem
|
||||||
|
- Calendar: allow different date/time format inputs
|
||||||
|
- Calendar: hide timezone select for allday events
|
||||||
|
⁻ Add opengraph meta info to channel page
|
||||||
|
- Begin directory migration to zot6
|
||||||
|
- Support zot and zot6 in social graph operations
|
||||||
|
- Lowlevel support for zot6 direct messages
|
||||||
|
- Consolidate HTTP signatures
|
||||||
|
- Allow api login by address or url
|
||||||
|
- Provide auto redirect from zot6 /item permalinks
|
||||||
|
- Export all items except photos in channel_export_items_date()
|
||||||
|
- Calendar: clicking a day or week number will now open the day or week view
|
||||||
|
- Remove cached photo location directory on delete if empty
|
||||||
|
- Include zot6 hubs in the Grid scope
|
||||||
|
- Fix os_path replace for thumbnails
|
||||||
|
- Avoid to process original images using storeThumbnail()
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
- Fix URLs on imported item taxonomy
|
||||||
|
- Fix admin not allowed to delete any item
|
||||||
|
- Fix webfiunger issue with URLs containing an @
|
||||||
|
- Fix missing object in emoji reactions
|
||||||
|
- Fix appschema to include diaspora:guid
|
||||||
|
- Fix zotfinger in update_directory_entry()
|
||||||
|
- Fix incorrect media type on links for photo objects
|
||||||
|
- Fix mid not dbesc'd in item_store()
|
||||||
|
- Fix calendar encoding issues
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- twitter: various rendering improvements
|
||||||
|
- cavatar: fix wrong image mimetype
|
||||||
|
- gravatar: fix wrong image mimetype
|
||||||
|
- Add license file
|
||||||
|
- pubcrawl: make repeats render like wall to wall posts
|
||||||
|
- pubcrawl: fix pubcrawl_import_author() sometimes returning a non activitypub xchan
|
||||||
|
- pubcrawl: use Lib/Activity for taxonomy en/decoding
|
||||||
|
- pubcrawl: fix wrong uuid in like activity
|
||||||
|
- pubcrawl: fix issue with encoding hashtags
|
||||||
|
- openstreetmap: use https URLs by default
|
||||||
|
- queueworker: refactor and efficiency improvements
|
||||||
|
- pubcrawl: use unique IDs for follow and accept activities
|
||||||
|
- pubcrawl: implement thread completion
|
||||||
|
- pubcrawl: implement delete activity
|
||||||
|
- photocache: reduce the size of the photo cache subdirectories tree
|
||||||
|
- photocache: use html_entity_decode() for cached photo URL
|
||||||
|
- diaspora: fix possible issue with diaspora relay not initializing
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.2.1 (2019-06-17)
|
||||||
|
- Deprecate mod events
|
||||||
|
- Revisit mod cal
|
||||||
|
- Fix issues with deletion of linked items and resources
|
||||||
|
- Fix zot6 delete issue
|
||||||
|
- Fix attach sync issue
|
||||||
|
- Remove sizeRangeSuffixes in justified gallery wrapper
|
||||||
|
- Fix storageconv issue with postgres
|
||||||
|
- Fix embedphotos image size
|
||||||
|
- pubcrawl: use URI instead of object for actor url
|
||||||
|
- diaspora: adjust loglevel
|
||||||
|
- gallery: remove workaround for margin issue which has been fixed upstream
|
||||||
|
- cart: warn about unsaved changes
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.2 (2019-06-04)
|
||||||
|
- Introduce Calendar app which deprecates Events and CalDAV apps and streamlines the featuresets
|
||||||
|
- Update mod cal to reflect changes in the calendar app
|
||||||
|
- Improve timezone detection for CalDAV calendars
|
||||||
|
- Add mention support to event description in channel calendar
|
||||||
|
- Update jgrowl library
|
||||||
|
- Do not try to oembed URLs without embed tags
|
||||||
|
- Optimise pdf oembed processing
|
||||||
|
- Add form security token to mod register
|
||||||
|
- Replace URLs for mod gallery, mod photos and mod photo on cloned channel post sync
|
||||||
|
- Update justified gallery library
|
||||||
|
- Update bootstrap libraries
|
||||||
|
- Use "cache" flag for bbcode() on content destined for zot6
|
||||||
|
- Improve DB indexing
|
||||||
|
- Drop deprecated columns from channel the table
|
||||||
|
- Replace own image URL in clonned channel posts
|
||||||
|
- Improve DB update handling
|
||||||
|
- Improve item deletion when a contact was removed
|
||||||
|
- Zot6 compatibility for emoji reactions
|
||||||
|
- Add threaded comments support (disabled by default)
|
||||||
|
- Improve xmlify()/unxmlify() performance
|
||||||
|
- Update blueimp/jquery-file-uplad library
|
||||||
|
- Update sabre/vobject library
|
||||||
|
- Various doco updates
|
||||||
|
- Implement remove profile photo button (reset to default photo)
|
||||||
|
- Implement remove cover photo button
|
||||||
|
- Update the homeinstall script
|
||||||
|
- Add command line tool for photo thumbnails storage conversion
|
||||||
|
- Implement option to store photo thumbnails in filesystem instead of DB
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
- Fix category widget when using articles
|
||||||
|
- Fix live update not triggering in mod search
|
||||||
|
- Fix encoded URLs in code blocks
|
||||||
|
- Fix wiki headers not escaped
|
||||||
|
- Fix possible xchan protocol confusion in new_contact()
|
||||||
|
- Fix xchan_url not displayed if xchan_addr not available
|
||||||
|
- Fix suggestion ordering in mod directory
|
||||||
|
- Fix event attachment delivery to zot6
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- pubcrawl: improve friendica compatibility by adding the nonstandard diaspora:guid field
|
||||||
|
- pubcrawl: initial suport for events
|
||||||
|
- pubcrawl: improve permalink detection
|
||||||
|
- flashcards: fix moving learn buttons if viewport sizes changes
|
||||||
|
- flashcards: Move card details to the bottom of a card
|
||||||
|
- upgrade_info: provide links to changelog
|
||||||
|
- photocache: do not save filename for cached photos
|
||||||
|
- pubcrawl: save local comment activitypub payload in iconfig to be used for relay
|
||||||
|
- flashcards: UI improvements in box settings
|
||||||
|
- pubcrawl: implement profile update messages
|
||||||
|
- pubcrawl: use URI instead of object for actor
|
||||||
|
- flashcards: fix jumping sync button
|
||||||
|
- pubcrawl: add threaded comments support
|
||||||
|
- pubcrawl: ignore target encoding errors
|
||||||
|
- pubcrawl: format photo items for activitypub
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.0.3 (2019-04-26)
|
||||||
|
- Add attachments to zot6 event objects
|
||||||
|
- Add zot6 to federated transports
|
||||||
|
- Update import/export to handle zot6 hublocs and xchans
|
||||||
|
- Update fix_system_urls() to handle zot6 hublocs
|
||||||
|
- Fix infinite loop using postgres as backend
|
||||||
|
- Fix magic auth in combination with zot6
|
||||||
|
- Fix check for required PHP version
|
||||||
|
- Diaspora: favour diaspora protocol identities over others with same hubloc or xchan address
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.0.2 (2019-04-08)
|
||||||
|
- Port cdav calendar to fullcalendar version 4
|
||||||
|
- Fix perms_pending not evaluated correctly
|
||||||
|
- Fix return wrong profile photo modification date by plugin
|
||||||
|
- Fix suggestion widget using feature_enabled still
|
||||||
|
- Fix check service class limits when syncing files
|
||||||
|
- Remove xchan_instance_url from notifier query - it is not used anymore
|
||||||
|
- Implement remove cover photo functionality
|
||||||
|
- Fix z6_discover() and create a zot6 hubloc on import if applicable
|
||||||
|
- Add backend support for connections ordering
|
||||||
|
- Deduplicate items in item_store() by uuid if we got one otherwise by mid
|
||||||
|
- Add ITEM_TYPE_CUSTOM support to mod display
|
||||||
|
- Fix mod subthread on sys channel items
|
||||||
|
- Fix "recipient not found" dreport spaming with own xchan
|
||||||
|
- Fix wrong variables in dirsearch
|
||||||
|
- Fix 48 hours timeframe check in mod changeaddr
|
||||||
|
- Fix wrong variable in Libsync
|
||||||
|
- Pubcrawl: revert adding additional receivers to comments
|
||||||
|
- Diaspora: fix intro received when being banned
|
||||||
|
- Pubcrawl: add diaspora:guid from friendica AP posts for deduplication
|
||||||
|
- Diaspora: fix friendica plink
|
||||||
|
- Photocache: fix issue with spaces and quotes in original filenames
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.0.1 (2019-03-21)
|
||||||
|
- Fix permissions not getting decrypted on follow
|
||||||
|
- Add option to add a poster to the video bbcode
|
||||||
|
- Fix SQL performance issue with queries including thr_parent
|
||||||
|
- Fix share encoding issue between hz and zap
|
||||||
|
- Fix edge case in unsupported advisory privacy
|
||||||
|
- Messagefilter enhancements
|
||||||
|
- Fix XSS issues
|
||||||
|
- Clone systems apps to the extent possible
|
||||||
|
- Auto-configure imagick thumbnail binary during setup if possible
|
||||||
|
- Fix array not unserialized in util/service_class
|
||||||
|
- Add phpmd and phpcs to composer require-dev for code linting
|
||||||
|
- Fix issue with email encoding
|
||||||
|
- Fix signature issue for zot6 content imported from zotfeeds to hubzilla
|
||||||
|
- Find unregistered z6 clones on hubzilla sites
|
||||||
|
- Add zot6 to clonable networks
|
||||||
|
- Add owner permission checks to AS item fetch
|
||||||
|
- Perform zot6 discovery in import_author_xchan
|
||||||
|
- Fix authenticated fetches
|
||||||
|
- Port zot_record_preferred() from zap
|
||||||
|
|
||||||
|
Addons:
|
||||||
|
- Pubcrawl: deliver comments to abook contacts and thread participants
|
||||||
|
- Pubcrawl: fix can_comment_on_post()
|
||||||
|
- Deliverynotice: do not save empty postopts
|
||||||
|
- Gravatar: fix URL and use z_fetch_url()
|
||||||
|
- Pubcrawl: improve SQL queries in pubcrawl_item_mod_init()
|
||||||
|
- Pubcrawl: fix authenticated item fetch
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 4.0 (2019-03-08)
|
||||||
|
- Add CURLOPT_CONNECTTIMEOUT option
|
||||||
|
- Allow parameters as final path argument in API router
|
||||||
|
- Remove clones from delivery recipients for top-level posts in favor of clone sync
|
||||||
|
- Mention php-zip module dependency in administrator guide
|
||||||
|
- Iron out some kinks with scrollToItem() in combination with collapsed content and images
|
||||||
|
- Zot API changes to support combined content (items+files) import addon
|
||||||
|
- Update PHP Version check during setup - min version is now 7.1
|
||||||
|
- Urlencode links in category widget
|
||||||
|
- Implement ability for channel visitors to be able to delete their own content
|
||||||
|
- Support zot location independent urls
|
||||||
|
- MySQL 8 admin summary compatibility
|
||||||
|
- Improved gitlab-ci environment
|
||||||
|
- Deprecate and remove addon settings in favour of per app settings
|
||||||
|
- Refactor PhotoDriver class and add tests
|
||||||
|
- Convert affinity tool to app
|
||||||
|
- Refactor linkify_tags() so it works with xchans across multiple protocols
|
||||||
|
- Add the actual mid to viewsrc for debuging reasons
|
||||||
|
- Add filter hooks and the ability to add buttons to the default status editor
|
||||||
|
- Prevent Hubzilla usage for SEO backlinks
|
||||||
|
- Implement privacy warning for forum posts via !-tag
|
||||||
|
- Set document title when title changes on a page update
|
||||||
|
- Cache embeds in the background on initial storage rather than on first access
|
||||||
|
- Custom sessionhandler support
|
||||||
|
- Update nginx and lighttpd sample server configs to explicit disallow access to util
|
||||||
|
- Introduce command line tool for managing site admins
|
||||||
|
- Various doxygen improvements
|
||||||
|
- Add privacygroup_extras_post/drop hooks
|
||||||
|
- Add collect_public_recipients hook
|
||||||
|
- Prevent memory exhaustion on zot message pickup with large message queue
|
||||||
|
- Remove experimental worker queue from core
|
||||||
|
- Add get_base_apps hook
|
||||||
|
- Improve handling of notification updates while commenting
|
||||||
|
- Add warning if upload_filesize < 4MB
|
||||||
|
- Add ITEM_TYPE_CUSTOM and hooks for processing custom item types
|
||||||
|
- Set min/maxversion for plugins to STD_VERSION unless otherwise specified
|
||||||
|
- Add option to make affinity slider 'sticky' across page loads
|
||||||
|
- Add photo_view_filter hook
|
||||||
|
- Reset page title if article has no title
|
||||||
|
- Implement the zot6 protocol
|
||||||
|
- Add PHOTO_CACHE photo type
|
||||||
|
- Basic support for HTTP3
|
||||||
|
- Add native summary support
|
||||||
|
- Disable image caching if personal or group permissions enabled
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
- Fix guest access token xchan record not created on URL login
|
||||||
|
- Fix regression where mod oep was still using hex2bin/bin2hex instead of album hash
|
||||||
|
- Fix regression when selecting multiple images in embed images
|
||||||
|
- Fix broken sync_an_item()
|
||||||
|
- Fix page jumping on like if comments are expanded (show all x comments)
|
||||||
|
- Fix regression in mod display where an page update could display items from multiple channels
|
||||||
|
- Fix starring and filing allowed for other unsupported item types
|
||||||
|
- Fix wrong variable in z_get_temp_dir()
|
||||||
|
- Fix page jumping when liking a collapsed/expanded post
|
||||||
|
- Fix tags detection in URL
|
||||||
|
- Fix warnings in mod embedphotos
|
||||||
|
- Fix wrong variable in can_comment_on_post()
|
||||||
|
- Fix mod new_channel counting removed channels
|
||||||
|
- Fix regression where not all content variables were sslified
|
||||||
|
- Fix default values for affinity tool and other information which could be lost when approving a connection
|
||||||
|
- Fix regression in linkdropper()
|
||||||
|
- Fix issue with unset auto_save_draft variable which resultet in a javascript error
|
||||||
|
- Fix home notifications won't expand if there are more than 300 unseen network notifications ahead of them
|
||||||
|
- Fix total_identities count
|
||||||
|
- Fix delayed items propagate before publication on cloned channels
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- twitter_api: fedilab needs profile_image_url_https
|
||||||
|
- New addon: content_import - imports items and files to cloned channels (this obsoletes hzfiles)
|
||||||
|
- Diaspora: prevent processing of incomplete messages in various places
|
||||||
|
- hzfiles: fix add missing load/unload functions
|
||||||
|
- chess: do not look for games if we have no game_id - improves initial pageload performance
|
||||||
|
- chess: convert to app
|
||||||
|
- channelreputation: convert to app
|
||||||
|
- irc: convert to per app
|
||||||
|
- Provide the addon_common directory for common addon libraries
|
||||||
|
- fuzzloc: convert to app
|
||||||
|
- flattrwidget: convert to app
|
||||||
|
- jappixmini: convert to app
|
||||||
|
- xmpp: convert to app
|
||||||
|
- visage: convert to app
|
||||||
|
- diaspora: reflect linkify_tags() rewrite
|
||||||
|
- twitter: convert to app
|
||||||
|
- smileybutton: convert to app
|
||||||
|
- skeleton: convert to app
|
||||||
|
- planets: convert to app
|
||||||
|
- pumpio: convert to app
|
||||||
|
- pageheader: convert to app
|
||||||
|
- nsabait: convert to app
|
||||||
|
- dwpost: convert to app
|
||||||
|
- diaspora: set the preserve_lf option in various places
|
||||||
|
- diaspora: fix comments from unknown persons are not accpted
|
||||||
|
- nofed: convert to app
|
||||||
|
- ljpost: convert to app
|
||||||
|
- diaspora: call update_queue_item() if delivery failed
|
||||||
|
- pubcrawl: call update_queue_item() if delivery failed
|
||||||
|
- libertree: convert to app
|
||||||
|
- New addon: queueworker advanced - queue handling (experimental)
|
||||||
|
- gallery: extended functionality: implements stream image viewer, converts images at the beginning of a post to a gallery
|
||||||
|
- authchoose: correction to query, add affinity setting
|
||||||
|
- New addon: photocache - local caching for public photos
|
||||||
|
- New addon: totp - two factor authentication using time-based one-time passwords
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.9 (2018-02-03)
|
||||||
|
- Fix typos in mod oep
|
||||||
|
- Fix page jumping when liking collapsed/expanded post
|
||||||
|
- Fix failure to import mail in mod import
|
||||||
|
- Fix wrong channel count in mod new_channel
|
||||||
|
- Fix diaspora addon regression
|
||||||
|
- Remove deprecated diaspora addon endpoint
|
||||||
|
- Fix wrong function call in gallery addon
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.8 (2018-12-22)
|
||||||
|
- Fix issue with linkinfo
|
||||||
|
- Fix cURL with HTTP/2
|
||||||
|
- Remove scale_external_images()
|
||||||
|
- Style highlight bbcode via css
|
||||||
|
- Make mod channel deal with b64 encoded mid's
|
||||||
|
- Fix email retrieval in OAuth2Storage
|
||||||
|
- Add reinstall option to util/addons
|
||||||
|
- Remove deprecated caching protection from mod photo
|
||||||
|
- Add missing check for observer in mod like
|
||||||
|
- Articles: default to logged in channel if channel name is not passed
|
||||||
|
- Wiki: fix preview issue with hyperlinks
|
||||||
|
- Cart: backport fixes from osada
|
||||||
|
- Gallery: provide file extensions for better compatibility
|
||||||
|
- Hsse: fix issue when linkinfo data was inserted
|
||||||
|
- Diaspora: remove deprecated scale_external_images()
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.7 (2018-12-14)
|
||||||
|
- Fix issue with linkdropper in comment area
|
||||||
|
- Fix regression wit app ordering
|
||||||
|
- Fix return if readImnageBlob() throws an exception
|
||||||
|
- Introduce photo_view_filter hook
|
||||||
|
- Fix home notifications not expanding in certain situations
|
||||||
|
- Fix for dark schema
|
||||||
|
- Fix total identities restriction
|
||||||
|
- Fix article page title not updating if article has no title
|
||||||
|
- Gallery: the gallery app will now act as the full-size photo viewer in /photos if installed
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.6 (2018-12-03)
|
||||||
|
- Prevent incompatible export files (osada/zap) from being imported
|
||||||
|
- Catch exception if readImageBlob() receives bogus data
|
||||||
|
- Streamline PDF previews
|
||||||
|
- Allow notification filtering by name or address
|
||||||
|
- Fix too restrictive attached photo permissions
|
||||||
|
- Update ES translation
|
||||||
|
- Use flex for the default template
|
||||||
|
- Do not store serialized pconfig value received via to Module/Pconfig.php
|
||||||
|
- Update jquery-file-upload lib and move to composer
|
||||||
|
- Update imagesloaded lib and move to composer
|
||||||
|
- Fix activitypub tag notifications
|
||||||
|
- Fix call to undefined function in PConfig
|
||||||
|
- Fix typo which prevented propagation of comments to zot6 (dev)
|
||||||
|
- Activitypub: add support for pterotype (wordpress plugin)
|
||||||
|
- Openstreetmap: check validity of lat+lon before rendering a map
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.5 (2018-11-19)
|
||||||
|
- Fix pconfig for new installs
|
||||||
|
- Fix delayed publication of posts in combination with channel clones
|
||||||
|
- Fix issue where photo filesize was not updated in the DB when a photo was edited
|
||||||
|
- Fix issue where the original photo size was not set correct in the DB
|
||||||
|
- Fix delivery issue in zot_fetch()
|
||||||
|
- Fix typo in channel reputation addon
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.4 (2018-11-14)
|
||||||
|
- Fix xss issue (thanks to Eduardo)
|
||||||
|
- Implement hook in enotify to be used by superblock
|
||||||
|
- Various css fixes
|
||||||
|
- Improve photo cache handling
|
||||||
|
- Provide a function hz_syslog() to log to syslog
|
||||||
|
- Fix request_target in z_post_url()
|
||||||
|
- Fix plural handling for various languages
|
||||||
|
- Some preparatory work for zot6
|
||||||
|
- Fix warning in gallery addon
|
||||||
|
- Fix date issue on xchan photo update in diaspora and pubcrawl addons
|
||||||
|
- Fix typos in startpage addon
|
||||||
|
- Improve activitypub addressing
|
||||||
|
- Fix taxonomy in activitypub direct messages
|
||||||
|
- Fix syntax error in diaspora addon
|
||||||
|
- New e-learning addon flashcards
|
||||||
|
- Remove DNS check for database connection during installation
|
||||||
|
- Implement timestamps for pconfig
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.3 (2018-11-05)
|
||||||
|
- Do not count likes in forum notifications if likes notifications are disabled
|
||||||
|
- Fix typo in spanish translation which broke javascript
|
||||||
|
- Improve linkinfo charset handling and image detection
|
||||||
|
- Fix wrong image resize for some external images
|
||||||
|
- Move blueimp upload lib to composer and update to version 9.25
|
||||||
|
- Remove primary/clone counts from admin summary until we have a mechanism to update the fixed counts
|
||||||
|
- Fix html2markdown() and re-enable previously failing tests
|
||||||
|
- Improve look of oembed content for Hubzilla links
|
||||||
|
- Fix forum notifications count not correct
|
||||||
|
- Fix gallery addon which broke mod apps in some situations
|
||||||
|
- Fix wiki_list widget not working on every page respectively level
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.2 (2018-10-29)
|
||||||
|
- Merge unmerged changes from dev into master
|
||||||
|
- Fix issues with forum handling in mod network and ping
|
||||||
|
- Fix delivery chain linkage messed up if original post was edited
|
||||||
|
- Fix issues with the experimental queue worker
|
||||||
|
- Fix call to image source {1} from html template
|
||||||
|
- Group stream filters by threaded and unthreaded default view
|
||||||
|
- Show only unseen forum messages when clicking on forum notification
|
||||||
|
- Improve editor contact autocomplete performance
|
||||||
|
- Convert non UTF-8 content on link embeding
|
||||||
|
- Make textcomplete return up to 100 items
|
||||||
|
- Look for for matches in the entire string when suggesting emojis
|
||||||
|
- Add [summary] bbcode to autocomplete list
|
||||||
|
- Update blueimp_upload to version 9.23
|
||||||
|
- Update spanish strings
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- Cart: don't allow items to be added unless user is logged into the Grid.
|
||||||
|
- Pubcrawl: simplify asencode_activity() addressing to reflect upcoming changes in mastodon 2.6
|
||||||
|
- Rendezvous: Update rendezvous_group.tpl to fix broken Bootstrap library reference
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8.1 (2018-10-21)
|
||||||
|
- Fix issue with too long navbar banners
|
||||||
|
- Fix menu item edit link
|
||||||
|
- Fix issue with jquery file upload
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.8 (2018-10-19)
|
||||||
|
- Re-implement basic build test via gitlab-ci
|
||||||
|
- Rework wiki encoding/decoding
|
||||||
|
- Implement improved worker (experimental - off by default)
|
||||||
|
- Rework hubzilla settings infrastructure
|
||||||
|
- Port the features to stand-alone apps
|
||||||
|
- Add app_destroy hook
|
||||||
|
- Improve mod network search
|
||||||
|
- Extend app_install() to allow installing by app name
|
||||||
|
- Remove tech levels
|
||||||
|
- Hide channel creation form when at or over service_class['limit_identities']
|
||||||
|
- Rename groups and group_members tables for MySQL 8 compatibility
|
||||||
|
- Improve checks for image magick and pdo at setup
|
||||||
|
- Allow a second url in apd files for settings
|
||||||
|
- Add contact autocomplete to mod photo comments
|
||||||
|
- Add hook to allow addons to filter the list returned by app_list
|
||||||
|
- Do not sync channel moved field
|
||||||
|
- Add attach_delete hook
|
||||||
|
- Catch errors in template rendering
|
||||||
|
- Provide a noscript_content switch for mod channel and display
|
||||||
|
- Install and update bootstrap via composer
|
||||||
|
- Improve cover-photo handling
|
||||||
|
- Improve notification handling on small screens
|
||||||
|
- Detect and automatically repair duplicate plugin hook scenarios
|
||||||
|
- Add dreport_process hook
|
||||||
|
- Redirect stdout/stderr on cron command
|
||||||
|
- Update composer libs and add ramsey/uuid
|
||||||
|
- Add hook to extend conv_item cog dropdown menu
|
||||||
|
- Trigger the query options off of the active module rather than passed parameters in first_post_date()
|
||||||
|
- Tweak archive widget for articles
|
||||||
|
- Add api_not_found hook
|
||||||
|
- Ignore deleted hublocs in zot finger
|
||||||
|
- Don't use "checkjs" with an associated page reload - wrap a static copy of the content in noscript tags instead
|
||||||
|
- Add possibility to override helpfiles
|
||||||
|
- Add support for overriding the default template location and individual templates via .htconfig.php
|
||||||
|
- Add table support to markdown
|
||||||
|
- Make channel_remove less memory hungry
|
||||||
|
- Prevent json-ld bombing
|
||||||
|
- Turn off browser autocomplete on channel sources creation
|
||||||
|
- Add alter_pdl hook
|
||||||
|
- Add ability for addons to create .pdl files and load them automatically
|
||||||
|
- Sanitise vcard fields
|
||||||
|
- Don't sync system apps
|
||||||
|
|
||||||
|
|
||||||
|
Bugfixes
|
||||||
|
- Fix issue with timeago plurals
|
||||||
|
- Fix issue with HTTP signatures
|
||||||
|
- Fix issues with channel import
|
||||||
|
- Fix double linebreaks in viewsrc output
|
||||||
|
- Fix jsonld signature issue (library is using sha1, spec requires sha256)
|
||||||
|
- Fix bookmarks not syncing between clones
|
||||||
|
- Fix combined view getting lost when deleting first message in pm thread
|
||||||
|
- Fix authors unable to comment on posts they authored when owned by others in certain circumstances
|
||||||
|
- Fix syschannel included in total channels count
|
||||||
|
- Fix html-to-markdown adds a backslash infront of a hash after each new line
|
||||||
|
- Fix profile likes dropdown
|
||||||
|
- Fix tags corruption when editing posts
|
||||||
|
- Fix duplicate info() messages
|
||||||
|
- Fix zid leaking to nonzot sites if markdown is enabled
|
||||||
|
- Fix app delete issue with base installed apps and app photo being reloaded uneccessarily
|
||||||
|
- Fix app update and ownership issues
|
||||||
|
|
||||||
|
Addons
|
||||||
|
- Upgrade Info: new addon to inform channel owners about system upgrades
|
||||||
|
- Superblock: fix issue with not removeable channels
|
||||||
|
- Cart: fix subscription table not created on install
|
||||||
|
- Hsse: new addon - a WYSIWYG editor for certain modules
|
||||||
|
- Rainbowtag: convert to app infrastructure
|
||||||
|
- Superblock: convert to app infrastructure
|
||||||
|
- Send ZID: convert to app infrastructure
|
||||||
|
- Adultphotoflag: move setting to mod photos
|
||||||
|
- GNU-Social: convert to app infrastructure
|
||||||
|
- Pubcrawl: convert to app infrastructure
|
||||||
|
- Startpage: convert to app infrastructure
|
||||||
|
- Wppost: convert to app infrastructure
|
||||||
|
- Diaspora: convert to app infrastructure
|
||||||
|
- Mdpost: move setting to editor settings
|
||||||
|
- Cart: convert to app infrastructure
|
||||||
|
- Cart: reflect renaming of groups table
|
||||||
|
- Authchoose: convert to app infrastructure
|
||||||
|
- Channelreputation: new addon - reputation system for community channels (forums, etc.)
|
||||||
|
- Diaspora: fix commenting on diaspora reshares
|
||||||
|
- Gallery: convert to app infrastructure
|
||||||
|
- Nsfw: convert to app infrastructure
|
||||||
|
- Diaspora: change top level retraction type from StatusMessage to Post
|
||||||
|
- Delivery Notice: new addon - display delivery status information at the top of items
|
||||||
|
- Diaspora: exclude xchan_networks rss, anon and unknown from the query to make the results more reliable
|
||||||
|
- Diaspora: provide xchan_url if we have no xchan_addr for mentions
|
||||||
|
- Diaspora: fix x-social-relay tags converted to associative array
|
||||||
|
- Twitter API: improvements for the twidere client
|
||||||
|
- Pubcrawl: partial support for inbound AP events
|
||||||
|
- Pubcrawl: add support for image objects
|
||||||
|
- Gallery: provide a way to direct link to a photo album gallery
|
||||||
|
- Pubcrawl: improve can_comment_on_post handler
|
||||||
|
- Pubcrawl: implement pleroma quirks regarding follow activities
|
||||||
|
- Cart: add ability to create catalog entries for physical and/or manually fulfilled items
|
||||||
|
- Cart: add subscriptions submodule
|
||||||
|
|
||||||
|
|
||||||
|
Hubzilla 3.6 (2018-07-25)
|
||||||
- Update jquery.timeago library
|
- Update jquery.timeago library
|
||||||
- Implement Hookable CSP
|
- Implement Hookable CSP
|
||||||
- ActivityStreams: accept header changes to support plume
|
- ActivityStreams: accept header changes to support plume
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
Copyright (c) 2010-2018 the Hubzilla Community
|
Copyright (c) 2019 Hubzilla Community
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
@@ -8,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
THE SOFTWARE.
|
SOFTWARE.
|
||||||
|
|||||||
@@ -25,5 +25,8 @@ Hubzilla is completely decentralised and open source, for you modify or adapt to
|
|||||||
|
|
||||||
The Hubzilla community consists of passionate volunteers creating an open source commons of decentralised services which are highly integrated and can rival the feature set of large centralised providers. We do our best to provide ethical software which places you in control of your online communications and privacy expectations.
|
The Hubzilla community consists of passionate volunteers creating an open source commons of decentralised services which are highly integrated and can rival the feature set of large centralised providers. We do our best to provide ethical software which places you in control of your online communications and privacy expectations.
|
||||||
|
|
||||||
|
Build status master branch:
|
||||||
|
[](https://framagit.org/hubzilla/core/badges/master/build.svg)
|
||||||
|
|
||||||
[](https://travis-ci.org/redmatrix/hubzilla)
|
Build status dev branch:
|
||||||
|
[](https://framagit.org/hubzilla/core/badges/dev/build.svg)
|
||||||
|
|||||||
@@ -88,4 +88,4 @@ class PermissionLimits {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php /** @file */
|
||||||
|
|
||||||
|
namespace Zotlabs\Daemon;
|
||||||
|
|
||||||
|
|
||||||
|
class Cache_embeds {
|
||||||
|
|
||||||
|
static public function run($argc,$argv) {
|
||||||
|
|
||||||
|
if(! $argc == 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$c = q("select body from item where id = %d ",
|
||||||
|
dbesc(intval($argv[1]))
|
||||||
|
);
|
||||||
|
|
||||||
|
if(! $c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$item = $c[0];
|
||||||
|
|
||||||
|
// bbcode conversion by default processes embeds that aren't already cached.
|
||||||
|
// Ignore the returned html output.
|
||||||
|
|
||||||
|
bbcode($item['body']);
|
||||||
|
}
|
||||||
|
}
|
||||||
+26
-3
@@ -60,7 +60,7 @@ class Cron {
|
|||||||
drop_item($rr['id'],false,(($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
|
drop_item($rr['id'],false,(($rr['item_wall']) ? DROPITEM_PHASE1 : DROPITEM_NORMAL));
|
||||||
if($rr['item_wall']) {
|
if($rr['item_wall']) {
|
||||||
// The notifier isn't normally invoked unless item_drop is interactive.
|
// The notifier isn't normally invoked unless item_drop is interactive.
|
||||||
Zotlabs\Daemon\Master::Summon( [ 'Notifier', 'drop', $rr['id'] ] );
|
Master::Summon( [ 'Notifier', 'drop', $rr['id'] ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +94,29 @@ class Cron {
|
|||||||
@time_sleep_until(microtime(true) + (float) $interval);
|
@time_sleep_until(microtime(true) + (float) $interval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean expired photos from cache
|
||||||
|
|
||||||
|
$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||||
|
intval(PHOTO_CACHE),
|
||||||
|
db_utcnow(),
|
||||||
|
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s",
|
||||||
|
intval(PHOTO_CACHE),
|
||||||
|
db_utcnow(),
|
||||||
|
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||||
|
);
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$file = dbunescbin($rr['content']);
|
||||||
|
if(is_file($file)) {
|
||||||
|
@unlink($file);
|
||||||
|
@rmdir(dirname($file));
|
||||||
|
logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// publish any applicable items that were set to be published in the future
|
// publish any applicable items that were set to be published in the future
|
||||||
// (time travel posts). Restrict to items that have come of age in the last
|
// (time travel posts). Restrict to items that have come of age in the last
|
||||||
@@ -164,7 +187,7 @@ class Cron {
|
|||||||
if($r) {
|
if($r) {
|
||||||
require_once('include/photo/photo_driver.php');
|
require_once('include/photo/photo_driver.php');
|
||||||
foreach($r as $rr) {
|
foreach($r as $rr) {
|
||||||
$photos = import_xchan_photo($rr['xchan_photo_l'],$rr['xchan_hash']);
|
$photos = import_xchan_photo($rr['xchan_photo_l'], $rr['xchan_hash'], false, true);
|
||||||
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
|
$x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_mimetype = '%s'
|
||||||
where xchan_hash = '%s'",
|
where xchan_hash = '%s'",
|
||||||
dbesc($photos[0]),
|
dbesc($photos[0]),
|
||||||
@@ -191,7 +214,7 @@ class Cron {
|
|||||||
$restart = true;
|
$restart = true;
|
||||||
$generation = intval($argv[2]);
|
$generation = intval($argv[2]);
|
||||||
if(! $generation)
|
if(! $generation)
|
||||||
killme();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
reload_plugins();
|
reload_plugins();
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ class Cron_daily {
|
|||||||
db_utcnow(), db_quoteinterval('1 YEAR')
|
db_utcnow(), db_quoteinterval('1 YEAR')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Clean up emdedded content cache
|
||||||
|
q("DELETE FROM cache WHERE updated < %s - INTERVAL %s",
|
||||||
|
db_utcnow(),
|
||||||
|
db_quoteinterval(get_config('system','active_expire_days', '30') . ' DAY')
|
||||||
|
);
|
||||||
|
|
||||||
//update statistics in config
|
//update statistics in config
|
||||||
require_once('include/statistics_fns.php');
|
require_once('include/statistics_fns.php');
|
||||||
@@ -85,6 +90,7 @@ class Cron_daily {
|
|||||||
Master::Summon(array('Cli_suggest'));
|
Master::Summon(array('Cli_suggest'));
|
||||||
|
|
||||||
remove_obsolete_hublocs();
|
remove_obsolete_hublocs();
|
||||||
|
z6_discover();
|
||||||
|
|
||||||
call_hooks('cron_daily',datetime_convert());
|
call_hooks('cron_daily',datetime_convert());
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class CurlAuth {
|
|||||||
static public function run($argc,$argv) {
|
static public function run($argc,$argv) {
|
||||||
|
|
||||||
if($argc != 2)
|
if($argc != 2)
|
||||||
killme();
|
return;
|
||||||
|
|
||||||
\App::$session->start();
|
\App::$session->start();
|
||||||
|
|
||||||
@@ -50,6 +50,6 @@ class CurlAuth {
|
|||||||
|
|
||||||
file_put_contents($c,$x);
|
file_put_contents($c,$x);
|
||||||
|
|
||||||
killme();
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Daemon;
|
namespace Zotlabs\Daemon;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\DReport;
|
||||||
|
|
||||||
require_once('include/zot.php');
|
require_once('include/zot.php');
|
||||||
require_once('include/queue_fn.php');
|
require_once('include/queue_fn.php');
|
||||||
|
|
||||||
@@ -58,11 +60,12 @@ class Deliver {
|
|||||||
|
|
||||||
foreach($dresult as $xx) {
|
foreach($dresult as $xx) {
|
||||||
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
if(is_array($xx) && array_key_exists('message_id',$xx)) {
|
||||||
if(delivery_report_is_storable($xx)) {
|
if(DReport::is_storable($xx)) {
|
||||||
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s','%s','%s','%s','%s' ) ",
|
q("insert into dreport ( dreport_mid, dreport_site, dreport_recip, dreport_name, dreport_result, dreport_time, dreport_xchan ) values ( '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ",
|
||||||
dbesc($xx['message_id']),
|
dbesc($xx['message_id']),
|
||||||
dbesc($xx['location']),
|
dbesc($xx['location']),
|
||||||
dbesc($xx['recipient']),
|
dbesc($xx['recipient']),
|
||||||
|
dbesc(($xx['name']) ? $xx['name'] : EMPTY_STR),
|
||||||
dbesc($xx['status']),
|
dbesc($xx['status']),
|
||||||
dbesc(datetime_convert($xx['date'])),
|
dbesc(datetime_convert($xx['date'])),
|
||||||
dbesc($xx['sender'])
|
dbesc($xx['sender'])
|
||||||
|
|||||||
@@ -3,14 +3,13 @@
|
|||||||
namespace Zotlabs\Daemon;
|
namespace Zotlabs\Daemon;
|
||||||
|
|
||||||
if(array_search( __file__ , get_included_files()) === 0) {
|
if(array_search( __file__ , get_included_files()) === 0) {
|
||||||
|
|
||||||
require_once('include/cli_startup.php');
|
require_once('include/cli_startup.php');
|
||||||
array_shift($argv);
|
array_shift($argv);
|
||||||
$argc = count($argv);
|
$argc = count($argv);
|
||||||
|
|
||||||
if($argc)
|
if($argc)
|
||||||
Master::Release($argc,$argv);
|
Master::Release($argc,$argv);
|
||||||
killme();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -18,13 +17,43 @@ if(array_search( __file__ , get_included_files()) === 0) {
|
|||||||
class Master {
|
class Master {
|
||||||
|
|
||||||
static public function Summon($arr) {
|
static public function Summon($arr) {
|
||||||
proc_run('php','Zotlabs/Daemon/Master.php',$arr);
|
$hookinfo = [
|
||||||
|
'argv'=>$arr
|
||||||
|
];
|
||||||
|
|
||||||
|
call_hooks ('daemon_master_summon',$hookinfo);
|
||||||
|
|
||||||
|
$arr = $hookinfo['argv'];
|
||||||
|
$argc = count($arr);
|
||||||
|
|
||||||
|
if ((!is_array($arr) || (count($arr) < 1))) {
|
||||||
|
logger("Summon handled by hook.",LOGGER_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$phpbin = get_config('system','phpbin','php');
|
||||||
|
proc_run($phpbin,'Zotlabs/Daemon/Master.php',$arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static public function Release($argc,$argv) {
|
static public function Release($argc,$argv) {
|
||||||
cli_startup();
|
cli_startup();
|
||||||
logger('Master: release: ' . print_r($argv,true), LOGGER_ALL,LOG_DEBUG);
|
|
||||||
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
$hookinfo = [
|
||||||
$cls::run($argc,$argv);
|
'argv'=>$argv
|
||||||
}
|
];
|
||||||
|
|
||||||
|
call_hooks ('daemon_master_release',$hookinfo);
|
||||||
|
|
||||||
|
$argv = $hookinfo['argv'];
|
||||||
|
$argc = count($argv);
|
||||||
|
|
||||||
|
if ((!is_array($argv) || (count($argv) < 1))) {
|
||||||
|
logger("Release handled by hook.",LOGGER_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger('Master: release: ' . json_encode($argv), LOGGER_ALL,LOG_DEBUG);
|
||||||
|
$cls = '\\Zotlabs\\Daemon\\' . $argv[0];
|
||||||
|
$cls::run($argc,$argv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+91
-18
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Daemon;
|
namespace Zotlabs\Daemon;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Libzot;
|
||||||
|
|
||||||
require_once('include/queue_fn.php');
|
require_once('include/queue_fn.php');
|
||||||
require_once('include/html2plain.php');
|
require_once('include/html2plain.php');
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
@@ -283,8 +285,21 @@ class Notifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
|
if(! in_array(intval($target_item['item_type']), [ ITEM_TYPE_POST ] )) {
|
||||||
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
$hookinfo=[
|
||||||
return;
|
'targetitem'=>$target_item,
|
||||||
|
'deliver'=>false
|
||||||
|
];
|
||||||
|
if (intval($target_item['item_type'] == ITEM_TYPE_CUSTOM)) {
|
||||||
|
call_hooks('customitem_deliver',$hookinfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$hookinfo['deliver']) {
|
||||||
|
logger('notifier: target item not forwardable: type ' . $target_item['item_type'], LOGGER_DEBUG);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$target_item = $hookinfo['targetitem'];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
// Check for non published items, but allow an exclusion for transmitting hidden file activities
|
||||||
@@ -344,7 +359,16 @@ class Notifier {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
$encoded_item = encode_item($target_item);
|
$encoded_item = encode_item($target_item);
|
||||||
|
|
||||||
|
// activitystreams version
|
||||||
|
$m = get_iconfig($target_item,'activitystreams','signed_data');
|
||||||
|
if($m) {
|
||||||
|
$activity = json_decode($m,true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$activity = \Zotlabs\Lib\Activity::encode_activity($target_item);
|
||||||
|
}
|
||||||
|
|
||||||
// Send comments to the owner to re-deliver to everybody in the conversation
|
// Send comments to the owner to re-deliver to everybody in the conversation
|
||||||
// We only do this if the item in question originated on this site. This prevents looping.
|
// We only do this if the item in question originated on this site. This prevents looping.
|
||||||
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
|
// To clarify, a site accepting a new comment is responsible for sending it to the owner for relay.
|
||||||
@@ -401,6 +425,12 @@ class Notifier {
|
|||||||
$private = false;
|
$private = false;
|
||||||
$recipients = collect_recipients($parent_item,$private);
|
$recipients = collect_recipients($parent_item,$private);
|
||||||
|
|
||||||
|
|
||||||
|
if ($top_level_post) {
|
||||||
|
// remove clones who will receive the post via sync
|
||||||
|
$recipients = array_diff($recipients, [ $target_item['owner_xchan'] ]);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME add any additional recipients such as mentions, etc.
|
// FIXME add any additional recipients such as mentions, etc.
|
||||||
|
|
||||||
// don't send deletions onward for other people's stuff
|
// don't send deletions onward for other people's stuff
|
||||||
@@ -423,6 +453,8 @@ class Notifier {
|
|||||||
$x['body'] = 'private';
|
$x['body'] = 'private';
|
||||||
logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
|
logger('notifier: encoded item: ' . print_r($x,true), LOGGER_DATA, LOG_DEBUG);
|
||||||
|
|
||||||
|
//logger('notifier: encoded activity: ' . print_r($activity,true), LOGGER_DATA, LOG_DEBUG);
|
||||||
|
|
||||||
stringify_array_elms($recipients);
|
stringify_array_elms($recipients);
|
||||||
if(! $recipients) {
|
if(! $recipients) {
|
||||||
logger('no recipients');
|
logger('no recipients');
|
||||||
@@ -433,7 +465,7 @@ class Notifier {
|
|||||||
|
|
||||||
$env_recips = (($private) ? array() : null);
|
$env_recips = (($private) ? array() : null);
|
||||||
|
|
||||||
$details = q("select xchan_hash, xchan_instance_url, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
$details = q("select xchan_hash, xchan_network, xchan_addr, xchan_guid, xchan_guid_sig from xchan where xchan_hash in (" . protect_sprintf(implode(',',$recipients)) . ")");
|
||||||
|
|
||||||
|
|
||||||
$recip_list = array();
|
$recip_list = array();
|
||||||
@@ -559,7 +591,9 @@ class Notifier {
|
|||||||
|
|
||||||
foreach($dhubs as $hub) {
|
foreach($dhubs as $hub) {
|
||||||
|
|
||||||
if($hub['hubloc_network'] !== 'zot') {
|
logger('notifier_hub: ' . $hub['hubloc_url'],LOGGER_DEBUG);
|
||||||
|
|
||||||
|
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
|
||||||
$narr = [
|
$narr = [
|
||||||
'channel' => $channel,
|
'channel' => $channel,
|
||||||
'upstream' => $upstream,
|
'upstream' => $upstream,
|
||||||
@@ -608,20 +642,32 @@ class Notifier {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default: zot protocol
|
if(! in_array($hub['hubloc_network'], [ 'zot','zot6' ])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not change this to a uuid as long as we have traditional zot servers
|
||||||
|
// in the loop. The signature verification step can't handle dashes in the
|
||||||
|
// hashes.
|
||||||
|
|
||||||
|
$hash = random_string(48);
|
||||||
|
|
||||||
$hash = random_string();
|
|
||||||
$packet = null;
|
$packet = null;
|
||||||
$pmsg = '';
|
$pmsg = '';
|
||||||
|
|
||||||
if($packet_type === 'refresh' || $packet_type === 'purge') {
|
if($packet_type === 'refresh' || $packet_type === 'purge') {
|
||||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
if($hub['hubloc_network'] === 'zot6') {
|
||||||
|
$packet = Libzot::build_packet($channel, $packet_type, ids_to_array($packet_recips,'hash'));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if($packet_type === 'keychange') {
|
if($packet_type === 'keychange' && $hub['hubloc_network'] === 'zot') {
|
||||||
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
|
$pmsg = get_pconfig($channel['channel_id'],'system','keychange');
|
||||||
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
$packet = zot_build_packet($channel,$packet_type,(($packet_recips) ? $packet_recips : null));
|
||||||
}
|
}
|
||||||
elseif($packet_type === 'request') {
|
elseif($packet_type === 'request' && $hub['hubloc_network'] === 'zot') {
|
||||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||||
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
$packet = zot_build_packet($channel,$packet_type,$env,$hub['hubloc_sitekey'],$hub['site_crypto'],
|
||||||
$hash, array('message_id' => $request_message_id)
|
$hash, array('message_id' => $request_message_id)
|
||||||
@@ -634,6 +680,7 @@ class Notifier {
|
|||||||
'account_id' => $channel['channel_account_id'],
|
'account_id' => $channel['channel_account_id'],
|
||||||
'channel_id' => $channel['channel_id'],
|
'channel_id' => $channel['channel_id'],
|
||||||
'posturl' => $hub['hubloc_callback'],
|
'posturl' => $hub['hubloc_callback'],
|
||||||
|
'driver' => $hub['hubloc_network'],
|
||||||
'notify' => $packet,
|
'notify' => $packet,
|
||||||
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
'msg' => (($pmsg) ? json_encode($pmsg) : '')
|
||||||
));
|
));
|
||||||
@@ -641,18 +688,43 @@ class Notifier {
|
|||||||
else {
|
else {
|
||||||
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
$env = (($hub_env && $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']]) ? $hub_env[$hub['hubloc_host'] . $hub['hubloc_sitekey']] : '');
|
||||||
|
|
||||||
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
|
|
||||||
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
|
||||||
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
|
|
||||||
// to trigger dequeue'ing
|
|
||||||
|
|
||||||
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
|
if($hub['hubloc_network'] === 'zot6') {
|
||||||
if($z6) {
|
$zenv = [];
|
||||||
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
if($env) {
|
||||||
|
foreach($env as $e) {
|
||||||
|
$zenv[] = $e['hash'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$packet_type = (($upstream || $uplink) ? 'response' : 'activity');
|
||||||
|
|
||||||
|
// block zot private reshares from zot6, as this could cause a number of privacy issues
|
||||||
|
// due to parenting differences between the reshare implementations. In zot a reshare is
|
||||||
|
// a standalone parent activity and in zot6 it is a followup/child of the original activity.
|
||||||
|
// For public reshares, some comments to the reshare on the zot fork will not make it to zot6
|
||||||
|
// due to these different message models. This cannot be prevented at this time.
|
||||||
|
|
||||||
|
if($packet_type === 'activity' && $activity['type'] === 'Announce' && intval($target_item['item_private'])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$packet = Libzot::build_packet($channel,$packet_type,$zenv,$activity,'activitystreams',(($private) ? $hub['hubloc_sitekey'] : null),$hub['site_crypto']);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
// currently zot6 delivery is only performed on normal items and not sync items or mail or anything else
|
||||||
|
// Eventually we will do this for all deliveries, but for now ensure this is precisely what we are dealing
|
||||||
|
// with before switching to zot6 as the primary zot6 handler checks for the existence of a message delivery report
|
||||||
|
// to trigger dequeue'ing
|
||||||
|
|
||||||
|
$z6 = (($encoded_item && $encoded_item['type'] === 'activity' && (! array_key_exists('allow_cid',$encoded_item))) ? true : false);
|
||||||
|
if($z6) {
|
||||||
|
$packet = zot6_build_packet($channel,'notify',$env, json_encode($encoded_item), (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$packet = zot_build_packet($channel,'notify',$env, (($private) ? $hub['hubloc_sitekey'] : null), $hub['site_crypto'],$hash);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
queue_insert(
|
queue_insert(
|
||||||
@@ -661,6 +733,7 @@ class Notifier {
|
|||||||
'account_id' => $target_item['aid'],
|
'account_id' => $target_item['aid'],
|
||||||
'channel_id' => $target_item['uid'],
|
'channel_id' => $target_item['uid'],
|
||||||
'posturl' => $hub['hubloc_callback'],
|
'posturl' => $hub['hubloc_callback'],
|
||||||
|
'driver' => $hub['hubloc_network'],
|
||||||
'notify' => $packet,
|
'notify' => $packet,
|
||||||
'msg' => json_encode($encoded_item)
|
'msg' => json_encode($encoded_item)
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -61,15 +61,17 @@ class Onepoll {
|
|||||||
|
|
||||||
if($contact['xchan_network'] === 'rss') {
|
if($contact['xchan_network'] === 'rss') {
|
||||||
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
|
logger('onepoll: processing feed ' . $contact['xchan_name'], LOGGER_DEBUG);
|
||||||
handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
$alive = handle_feed($importer['channel_id'],$contact_id,$contact['xchan_hash']);
|
||||||
q("update abook set abook_connected = '%s' where abook_id = %d",
|
if ($alive) {
|
||||||
dbesc(datetime_convert()),
|
q("update abook set abook_connected = '%s' where abook_id = %d",
|
||||||
intval($contact['abook_id'])
|
dbesc(datetime_convert()),
|
||||||
);
|
intval($contact['abook_id'])
|
||||||
|
);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($contact['xchan_network'] !== 'zot')
|
if(! in_array($contact['xchan_network'],['zot','zot6']))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// update permissions
|
// update permissions
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class Poller {
|
|||||||
$restart = true;
|
$restart = true;
|
||||||
$generation = intval($argv[2]);
|
$generation = intval($argv[2]);
|
||||||
if(! $generation)
|
if(! $generation)
|
||||||
killme();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($argc > 1) && intval($argv[1])) {
|
if(($argc > 1) && intval($argv[1])) {
|
||||||
@@ -110,7 +110,7 @@ class Poller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if($contact['xchan_network'] !== 'zot')
|
if(! in_array($contact['xchan_network'],['zot','zot6']))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if($c == $t) {
|
if($c == $t) {
|
||||||
@@ -199,6 +199,7 @@ class Poller {
|
|||||||
set_config('system','lastpoll',datetime_convert());
|
set_config('system','lastpoll',datetime_convert());
|
||||||
|
|
||||||
//All done - clear the lockfile
|
//All done - clear the lockfile
|
||||||
|
|
||||||
@unlink($lockfile);
|
@unlink($lockfile);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ class Queue {
|
|||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
require_once('include/bbcode.php');
|
require_once('include/bbcode.php');
|
||||||
|
|
||||||
|
|
||||||
if($argc > 1)
|
if($argc > 1)
|
||||||
$queue_id = $argv[1];
|
$queue_id = $argv[1];
|
||||||
else
|
else
|
||||||
@@ -61,10 +60,20 @@ class Queue {
|
|||||||
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
// or just prior to this query based on recent and long-term delivery history. If we have good reason to believe
|
||||||
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
|
// the site is permanently down, there's no reason to attempt delivery at all, or at most not more than once
|
||||||
// or twice a day.
|
// or twice a day.
|
||||||
|
|
||||||
$r = q("SELECT * FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s ",
|
$sqlrandfunc = db_getfunc('rand');
|
||||||
|
|
||||||
|
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||||
db_utcnow()
|
db_utcnow()
|
||||||
);
|
);
|
||||||
|
while ($r) {
|
||||||
|
foreach($r as $rv) {
|
||||||
|
queue_deliver($rv);
|
||||||
|
}
|
||||||
|
$r = q("SELECT *,$sqlrandfunc as rn FROM outq WHERE outq_delivered = 0 and outq_scheduled < %s order by rn limit 1",
|
||||||
|
db_utcnow()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(! $r)
|
if(! $r)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Extend;
|
||||||
|
|
||||||
|
|
||||||
|
class Route {
|
||||||
|
|
||||||
|
static function register($file,$modname) {
|
||||||
|
$rt = self::get();
|
||||||
|
$rt[] = [ $file, $modname ];
|
||||||
|
self::set($rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unregister($file,$modname) {
|
||||||
|
$rt = self::get();
|
||||||
|
if($rt) {
|
||||||
|
$n = [];
|
||||||
|
foreach($rt as $r) {
|
||||||
|
if($r[0] !== $file && $r[1] !== $modname) {
|
||||||
|
$n[] = $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::set($n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unregister_by_file($file) {
|
||||||
|
$rt = self::get();
|
||||||
|
if($rt) {
|
||||||
|
$n = [];
|
||||||
|
foreach($rt as $r) {
|
||||||
|
if($r[0] !== $file) {
|
||||||
|
$n[] = $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::set($n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function get() {
|
||||||
|
return get_config('system','routes',[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function set($r) {
|
||||||
|
return set_config('system','routes',$r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Extend;
|
||||||
|
|
||||||
|
|
||||||
|
class Widget {
|
||||||
|
|
||||||
|
static function register($file,$widget) {
|
||||||
|
$rt = self::get();
|
||||||
|
$rt[] = [ $file, $widget ];
|
||||||
|
self::set($rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unregister($file,$widget) {
|
||||||
|
$rt = self::get();
|
||||||
|
if($rt) {
|
||||||
|
$n = [];
|
||||||
|
foreach($rt as $r) {
|
||||||
|
if($r[0] !== $file && $r[1] !== $widget) {
|
||||||
|
$n[] = $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::set($n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unregister_by_file($file) {
|
||||||
|
$rt = self::get();
|
||||||
|
if($rt) {
|
||||||
|
$n = [];
|
||||||
|
foreach($rt as $r) {
|
||||||
|
if($r[0] !== $file) {
|
||||||
|
$n[] = $r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self::set($n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function get() {
|
||||||
|
return get_config('system','widgets',[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function set($r) {
|
||||||
|
return set_config('system','widgets',$r);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ namespace Zotlabs\Identity;
|
|||||||
|
|
||||||
class OAuth2Server extends \OAuth2\Server {
|
class OAuth2Server extends \OAuth2\Server {
|
||||||
|
|
||||||
public function __construct(OAuth2Storage $storage, $config = []) {
|
public function __construct(OAuth2Storage $storage, $config = null) {
|
||||||
|
|
||||||
if(! is_array($config)) {
|
if(! is_array($config)) {
|
||||||
$config = [
|
$config = [
|
||||||
@@ -19,7 +19,8 @@ class OAuth2Server extends \OAuth2\Server {
|
|||||||
$this->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));
|
$this->addGrantType(new \OAuth2\GrantType\ClientCredentials($storage));
|
||||||
|
|
||||||
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
|
// Add the "Authorization Code" grant type (this is where the oauth magic happens)
|
||||||
$this->addGrantType(new \OAuth2\GrantType\AuthorizationCode($storage));
|
// Need to use OpenID\GrantType to return id_token (see:https://github.com/bshaffer/oauth2-server-php/issues/443)
|
||||||
|
$this->addGrantType(new \OAuth2\OpenID\GrantType\AuthorizationCode($storage));
|
||||||
|
|
||||||
$keyStorage = new \OAuth2\Storage\Memory( [
|
$keyStorage = new \OAuth2\Storage\Memory( [
|
||||||
'keys' => [
|
'keys' => [
|
||||||
|
|||||||
@@ -50,20 +50,78 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
|||||||
public function getUser($username)
|
public function getUser($username)
|
||||||
{
|
{
|
||||||
|
|
||||||
$x = channelx_by_nick($username);
|
$x = channelx_by_n($username);
|
||||||
if(! $x) {
|
if(! $x) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$a = q("select * from account where account_id = %d",
|
||||||
|
intval($x['channel_account_id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$n = explode(' ', $x['channel_name']);
|
||||||
|
|
||||||
return( [
|
return( [
|
||||||
'username' => $x['channel_address'],
|
'webfinger' => channel_reddress($x),
|
||||||
'user_id' => $x['channel_id'],
|
'portable_id' => $x['channel_hash'],
|
||||||
'firstName' => $x['channel_name'],
|
'email' => $a[0]['account_email'],
|
||||||
'lastName' => '',
|
'username' => $x['channel_address'],
|
||||||
'password' => 'NotARealPassword'
|
'user_id' => $x['channel_id'],
|
||||||
|
'name' => $x['channel_name'],
|
||||||
|
'firstName' => ((count($n) > 1) ? $n[1] : $n[0]),
|
||||||
|
'lastName' => ((count($n) > 2) ? $n[count($n) - 1] : ''),
|
||||||
|
'picture' => $x['xchan_photo_l']
|
||||||
] );
|
] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeExists($scope) {
|
||||||
|
// Report that the scope is valid even if it's not.
|
||||||
|
// We will only return a very small subset no matter what.
|
||||||
|
// @TODO: Truly validate the scope
|
||||||
|
// see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
|
||||||
|
// vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/Pdo.php
|
||||||
|
// for more info.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDefaultScope($client_id=null) {
|
||||||
|
// Do not REQUIRE a scope
|
||||||
|
// see vendor/bshaffer/oauth2-server-php/src/OAuth2/Storage/ScopeInterface.php and
|
||||||
|
// for more info.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserClaims ($user_id, $claims) {
|
||||||
|
// Populate the CLAIMS requested (if any).
|
||||||
|
// @TODO: create a more reasonable/comprehensive list.
|
||||||
|
// @TODO: present claims on the AUTHORIZATION screen
|
||||||
|
|
||||||
|
$userClaims = Array();
|
||||||
|
$claims = explode (' ', trim($claims));
|
||||||
|
$validclaims = Array ("name","preferred_username","webfinger","portable_id","email","picture","firstName","lastName");
|
||||||
|
$claimsmap = Array (
|
||||||
|
"webfinger" => 'webfinger',
|
||||||
|
"portable_id" => 'portable_id',
|
||||||
|
"name" => 'name',
|
||||||
|
"email" => 'email',
|
||||||
|
"preferred_username" => 'username',
|
||||||
|
"picture" => 'picture',
|
||||||
|
"given_name" => 'firstName',
|
||||||
|
"family_name" => 'lastName'
|
||||||
|
);
|
||||||
|
$userinfo = $this->getUser($user_id);
|
||||||
|
foreach ($validclaims as $validclaim) {
|
||||||
|
if (in_array($validclaim,$claims)) {
|
||||||
|
$claimkey = $claimsmap[$validclaim];
|
||||||
|
$userClaims[$validclaim] = $userinfo[$claimkey];
|
||||||
|
} else {
|
||||||
|
$userClaims[$validclaim] = $validclaim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$userClaims["sub"]=$user_id;
|
||||||
|
return $userClaims;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* plaintext passwords are bad! Override this for your application
|
* plaintext passwords are bad! Override this for your application
|
||||||
*
|
*
|
||||||
@@ -78,4 +136,4 @@ class OAuth2Storage extends \OAuth2\Storage\Pdo {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+163
-31
@@ -7,22 +7,25 @@ namespace Zotlabs\Lib;
|
|||||||
*
|
*
|
||||||
* Parses an ActivityStream JSON string.
|
* Parses an ActivityStream JSON string.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ActivityStreams {
|
class ActivityStreams {
|
||||||
|
|
||||||
public $raw = null;
|
public $raw = null;
|
||||||
public $data;
|
public $data = null;
|
||||||
public $valid = false;
|
public $valid = false;
|
||||||
public $id = '';
|
public $deleted = false;
|
||||||
public $type = '';
|
public $id = '';
|
||||||
public $actor = null;
|
public $parent_id = '';
|
||||||
public $obj = null;
|
public $type = '';
|
||||||
public $tgt = null;
|
public $actor = null;
|
||||||
public $origin = null;
|
public $obj = null;
|
||||||
public $owner = null;
|
public $tgt = null;
|
||||||
public $signer = null;
|
public $origin = null;
|
||||||
public $ldsig = null;
|
public $owner = null;
|
||||||
public $sigok = false;
|
public $signer = null;
|
||||||
public $recips = null;
|
public $ldsig = null;
|
||||||
|
public $sigok = false;
|
||||||
|
public $recips = null;
|
||||||
public $raw_recips = null;
|
public $raw_recips = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -35,16 +38,49 @@ class ActivityStreams {
|
|||||||
function __construct($string) {
|
function __construct($string) {
|
||||||
|
|
||||||
$this->raw = $string;
|
$this->raw = $string;
|
||||||
$this->data = json_decode($string, true);
|
|
||||||
|
if(is_array($string)) {
|
||||||
|
$this->data = $string;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->data = json_decode($string, true);
|
||||||
|
}
|
||||||
|
|
||||||
if($this->data) {
|
if($this->data) {
|
||||||
|
|
||||||
|
// verify and unpack JSalmon signature if present
|
||||||
|
|
||||||
|
if(is_array($this->data) && array_key_exists('signed',$this->data)) {
|
||||||
|
$ret = JSalmon::verify($this->data);
|
||||||
|
$tmp = JSalmon::unpack($this->data['data']);
|
||||||
|
if($ret && $ret['success']) {
|
||||||
|
if($ret['signer']) {
|
||||||
|
$saved = json_encode($this->data,JSON_UNESCAPED_SLASHES);
|
||||||
|
$this->data = $tmp;
|
||||||
|
$this->data['signer'] = $ret['signer'];
|
||||||
|
$this->data['signed_data'] = $saved;
|
||||||
|
if($ret['hubloc']) {
|
||||||
|
$this->data['hubloc'] = $ret['hubloc'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->valid = true;
|
$this->valid = true;
|
||||||
|
|
||||||
|
if(array_key_exists('type',$this->data) && array_key_exists('actor',$this->data) && array_key_exists('object',$this->data)) {
|
||||||
|
if($this->data['type'] === 'Delete' && $this->data['actor'] === $this->data['object']) {
|
||||||
|
$this->deleted = $this->data['actor'];
|
||||||
|
$this->valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($this->is_valid()) {
|
if($this->is_valid()) {
|
||||||
$this->id = $this->get_property_obj('id');
|
$this->id = $this->get_property_obj('id');
|
||||||
$this->type = $this->get_primary_type();
|
$this->type = $this->get_primary_type();
|
||||||
$this->actor = $this->get_compound_property('actor');
|
$this->actor = $this->get_actor('actor','','');
|
||||||
$this->obj = $this->get_compound_property('object');
|
$this->obj = $this->get_compound_property('object');
|
||||||
$this->tgt = $this->get_compound_property('target');
|
$this->tgt = $this->get_compound_property('target');
|
||||||
$this->origin = $this->get_compound_property('origin');
|
$this->origin = $this->get_compound_property('origin');
|
||||||
@@ -53,14 +89,31 @@ class ActivityStreams {
|
|||||||
$this->ldsig = $this->get_compound_property('signature');
|
$this->ldsig = $this->get_compound_property('signature');
|
||||||
if($this->ldsig) {
|
if($this->ldsig) {
|
||||||
$this->signer = $this->get_compound_property('creator',$this->ldsig);
|
$this->signer = $this->get_compound_property('creator',$this->ldsig);
|
||||||
if($this->signer && $this->signer['publicKey'] && $this->signer['publicKey']['publicKeyPem']) {
|
if($this->signer && is_array($this->signer) && array_key_exists('publicKey',$this->signer) && is_array($this->signer['publicKey']) && $this->signer['publicKey']['publicKeyPem']) {
|
||||||
$this->sigok = \Zotlabs\Lib\LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
$this->sigok = LDSignatures::verify($this->data,$this->signer['publicKey']['publicKeyPem']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(($this->type === 'Note') && (! $this->obj)) {
|
if(! $this->obj) {
|
||||||
$this->obj = $this->data;
|
$this->obj = $this->data;
|
||||||
$this->type = 'Create';
|
$this->type = 'Create';
|
||||||
|
if(! $this->actor) {
|
||||||
|
$this->actor = $this->get_actor('attributedTo',$this->obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->obj && is_array($this->obj) && $this->obj['actor'])
|
||||||
|
$this->obj['actor'] = $this->get_actor('actor',$this->obj);
|
||||||
|
if($this->tgt && is_array($this->tgt) && $this->tgt['actor'])
|
||||||
|
$this->tgt['actor'] = $this->get_actor('actor',$this->tgt);
|
||||||
|
|
||||||
|
$this->parent_id = $this->get_property_obj('inReplyTo');
|
||||||
|
|
||||||
|
if((! $this->parent_id) && is_array($this->obj)) {
|
||||||
|
$this->parent_id = $this->obj['inReplyTo'];
|
||||||
|
}
|
||||||
|
if((! $this->parent_id) && is_array($this->obj)) {
|
||||||
|
$this->parent_id = $this->obj['id'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,28 +243,32 @@ class ActivityStreams {
|
|||||||
$base = (($base) ? $base : $this->data);
|
$base = (($base) ? $base : $this->data);
|
||||||
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
$propname = (($prefix) ? $prefix . ':' : '') . $property;
|
||||||
|
|
||||||
|
if(! is_array($base)) {
|
||||||
|
btlogger('not an array: ' . print_r($base,true));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
return ((array_key_exists($propname, $base)) ? $base[$propname] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Fetches a property from an URL.
|
* @brief Fetches a property from an URL.
|
||||||
*
|
*
|
||||||
* @param string $url
|
* @param string $url
|
||||||
* @return NULL|mixed
|
* @return NULL|mixed
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function fetch_property($url) {
|
function fetch_property($url) {
|
||||||
$redirects = 0;
|
return self::fetch($url);
|
||||||
if(! check_siteallowed($url)) {
|
}
|
||||||
logger('blacklisted: ' . $url);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$x = z_fetch_url($url, true, $redirects,
|
static function fetch($url,$channel = null) {
|
||||||
['headers' => [ 'Accept: application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"' ]]);
|
return Activity::fetch($url,$channel);
|
||||||
if($x['success'])
|
}
|
||||||
return json_decode($x['body'], true);
|
|
||||||
|
|
||||||
return null;
|
static function is_an_actor($s) {
|
||||||
|
return(in_array($s,[ 'Application','Group','Organization','Person','Service' ]));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,10 +279,71 @@ class ActivityStreams {
|
|||||||
* @param string $namespace (optional) default empty
|
* @param string $namespace (optional) default empty
|
||||||
* @return NULL|mixed
|
* @return NULL|mixed
|
||||||
*/
|
*/
|
||||||
function get_compound_property($property, $base = '', $namespace = '') {
|
|
||||||
|
function get_actor($property,$base='',$namespace = '') {
|
||||||
$x = $this->get_property_obj($property, $base, $namespace);
|
$x = $this->get_property_obj($property, $base, $namespace);
|
||||||
if($this->is_url($x)) {
|
if($this->is_url($x)) {
|
||||||
$x = $this->fetch_property($x);
|
|
||||||
|
// SECURITY: If we have already stored the actor profile, re-generate it
|
||||||
|
// from cached data - don't refetch it from the network
|
||||||
|
|
||||||
|
$r = q("select * from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_id_url = '%s' limit 1",
|
||||||
|
dbesc($x)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
$y = Activity::encode_person($r[0]);
|
||||||
|
$y['cached'] = true;
|
||||||
|
return $y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$actor = $this->get_compound_property($property,$base,$namespace,true);
|
||||||
|
if(is_array($actor) && self::is_an_actor($actor['type'])) {
|
||||||
|
if(array_key_exists('id',$actor) && (! array_key_exists('inbox',$actor))) {
|
||||||
|
$actor = $this->fetch_property($actor['id']);
|
||||||
|
}
|
||||||
|
return $actor;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param string $property
|
||||||
|
* @param array $base
|
||||||
|
* @param string $namespace (optional) default empty
|
||||||
|
* @param boolean $first (optional) default false, if true and result is a sequential array return only the first element
|
||||||
|
* @return NULL|mixed
|
||||||
|
*/
|
||||||
|
function get_compound_property($property, $base = '', $namespace = '', $first = false) {
|
||||||
|
$x = $this->get_property_obj($property, $base, $namespace);
|
||||||
|
if($this->is_url($x)) {
|
||||||
|
$y = $this->fetch_property($x);
|
||||||
|
if (is_array($y)) {
|
||||||
|
$x = $y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify and unpack JSalmon signature if present
|
||||||
|
|
||||||
|
if(is_array($x) && array_key_exists('signed',$x)) {
|
||||||
|
$ret = JSalmon::verify($x);
|
||||||
|
$tmp = JSalmon::unpack($x['data']);
|
||||||
|
if($ret && $ret['success']) {
|
||||||
|
if($ret['signer']) {
|
||||||
|
$saved = json_encode($x,JSON_UNESCAPED_SLASHES);
|
||||||
|
$x = $tmp;
|
||||||
|
$x['signer'] = $ret['signer'];
|
||||||
|
$x['signed_data'] = $saved;
|
||||||
|
if($ret['hubloc']) {
|
||||||
|
$x['hubloc'] = $ret['hubloc'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($first && is_array($x) && array_key_exists(0,$x)) {
|
||||||
|
return $x[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $x;
|
return $x;
|
||||||
@@ -273,4 +391,18 @@ class ActivityStreams {
|
|||||||
return $x;
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function is_as_request() {
|
||||||
|
|
||||||
|
$x = getBestSupportedMimeType([
|
||||||
|
'application/ld+json;profile="https://www.w3.org/ns/activitystreams"',
|
||||||
|
'application/activity+json',
|
||||||
|
'application/ld+json;profile="http://www.w3.org/ns/activitystreams"'
|
||||||
|
]);
|
||||||
|
|
||||||
|
return(($x) ? true : false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,16 @@ class Api_router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function find($path) {
|
static function find($path) {
|
||||||
if(array_key_exists($path,self::$routes))
|
if (array_key_exists($path,self::$routes)) {
|
||||||
return self::$routes[$path];
|
return self::$routes[$path];
|
||||||
|
}
|
||||||
|
|
||||||
|
$with_params = dirname($path) . '/[id]';
|
||||||
|
|
||||||
|
if (array_key_exists($with_params,self::$routes)) {
|
||||||
|
return self::$routes[$with_params];
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+428
-168
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,10 @@ class Cache {
|
|||||||
|
|
||||||
$hash = hash('whirlpool',$key);
|
$hash = hash('whirlpool',$key);
|
||||||
|
|
||||||
$r = q("SELECT v FROM cache WHERE k = '%s' limit 1",
|
$r = q("SELECT v FROM cache WHERE k = '%s' AND updated > %s - INTERVAL %s LIMIT 1",
|
||||||
dbesc($hash)
|
dbesc($hash),
|
||||||
|
db_utcnow(),
|
||||||
|
db_quoteinterval(get_config('system','object_cache_days', '30') . ' DAY')
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($r)
|
if ($r)
|
||||||
@@ -40,12 +42,5 @@ class Cache {
|
|||||||
dbesc(datetime_convert()));
|
dbesc(datetime_convert()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static function clear() {
|
|
||||||
q("DELETE FROM cache WHERE updated < '%s'",
|
|
||||||
dbesc(datetime_convert('UTC','UTC',"now - 30 days")));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,15 @@ class DB_Upgrade {
|
|||||||
|
|
||||||
|
|
||||||
$c = new $cls();
|
$c = new $cls();
|
||||||
|
|
||||||
$retval = $c->run();
|
$retval = $c->run();
|
||||||
|
|
||||||
if($retval != UPDATE_SUCCESS) {
|
if($retval != UPDATE_SUCCESS) {
|
||||||
|
|
||||||
|
|
||||||
|
$source = t('Source code of failed update: ') . "\n\n" . @file_get_contents('Zotlabs/Update/' . $s . '.php');
|
||||||
|
|
||||||
|
|
||||||
// Prevent sending hundreds of thousands of emails by creating
|
// Prevent sending hundreds of thousands of emails by creating
|
||||||
// a lockfile.
|
// a lockfile.
|
||||||
|
|
||||||
@@ -86,7 +91,9 @@ class DB_Upgrade {
|
|||||||
'$sitename' => \App::$config['system']['sitename'],
|
'$sitename' => \App::$config['system']['sitename'],
|
||||||
'$siteurl' => z_root(),
|
'$siteurl' => z_root(),
|
||||||
'$update' => $x,
|
'$update' => $x,
|
||||||
'$error' => sprintf( t('Update %s failed. See error logs.'), $x)
|
'$error' => sprintf( t('Update %s failed. See error logs.'), $x),
|
||||||
|
'$baseurl' => z_root(),
|
||||||
|
'$source' => $source
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|||||||
+94
-2
@@ -14,6 +14,7 @@ class DReport {
|
|||||||
$this->location = $location;
|
$this->location = $location;
|
||||||
$this->sender = $sender;
|
$this->sender = $sender;
|
||||||
$this->recipient = $recipient;
|
$this->recipient = $recipient;
|
||||||
|
$this->name = EMPTY_STR;
|
||||||
$this->message_id = $message_id;
|
$this->message_id = $message_id;
|
||||||
$this->status = $status;
|
$this->status = $status;
|
||||||
$this->date = datetime_convert();
|
$this->date = datetime_convert();
|
||||||
@@ -24,8 +25,8 @@ class DReport {
|
|||||||
$this->date = datetime_convert();
|
$this->date = datetime_convert();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addto_recipient($name) {
|
function set_name($name) {
|
||||||
$this->recipient = $this->recipient . ' ' . $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addto_update($status) {
|
function addto_update($status) {
|
||||||
@@ -37,6 +38,7 @@ class DReport {
|
|||||||
$this->location = $arr['location'];
|
$this->location = $arr['location'];
|
||||||
$this->sender = $arr['sender'];
|
$this->sender = $arr['sender'];
|
||||||
$this->recipient = $arr['recipient'];
|
$this->recipient = $arr['recipient'];
|
||||||
|
$this->name = $arr['name'];
|
||||||
$this->message_id = $arr['message_id'];
|
$this->message_id = $arr['message_id'];
|
||||||
$this->status = $arr['status'];
|
$this->status = $arr['status'];
|
||||||
$this->date = $arr['date'];
|
$this->date = $arr['date'];
|
||||||
@@ -47,9 +49,99 @@ class DReport {
|
|||||||
'location' => $this->location,
|
'location' => $this->location,
|
||||||
'sender' => $this->sender,
|
'sender' => $this->sender,
|
||||||
'recipient' => $this->recipient,
|
'recipient' => $this->recipient,
|
||||||
|
'name' => $this->name,
|
||||||
'message_id' => $this->message_id,
|
'message_id' => $this->message_id,
|
||||||
'status' => $this->status,
|
'status' => $this->status,
|
||||||
'date' => $this->date
|
'date' => $this->date
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief decide whether to store a returned delivery report
|
||||||
|
*
|
||||||
|
* @param array $dr
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function is_storable($dr) {
|
||||||
|
|
||||||
|
if(get_config('system', 'disable_dreport'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hooks dreport_is_storable
|
||||||
|
* Called before storing a dreport record to determine whether to store it.
|
||||||
|
* * \e array
|
||||||
|
*/
|
||||||
|
|
||||||
|
call_hooks('dreport_is_storable', $dr);
|
||||||
|
|
||||||
|
// let plugins accept or reject - if neither, continue on
|
||||||
|
if(array_key_exists('accept',$dr) && intval($dr['accept']))
|
||||||
|
return true;
|
||||||
|
if(array_key_exists('reject',$dr) && intval($dr['reject']))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(! ($dr['sender']))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Is the sender one of our channels?
|
||||||
|
|
||||||
|
$c = q("select channel_id from channel where channel_hash = '%s' or channel_portable_id = '%s' limit 1",
|
||||||
|
dbesc($dr['sender']),
|
||||||
|
dbesc($dr['sender'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if(! $c)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// legacy zot recipients add a space and their name to the xchan. remove it if true.
|
||||||
|
|
||||||
|
$legacy_recipient = strpos($dr['recipient'], ' ');
|
||||||
|
if($legacy_recipient !== false) {
|
||||||
|
$legacy_recipient_parts = explode(' ', $dr['recipient'], 2);
|
||||||
|
$rxchan = $legacy_recipient_parts[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$rxchan = $dr['recipient'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// is the recipient one of our connections, or do we want to store every report?
|
||||||
|
|
||||||
|
$pcf = get_pconfig($c[0]['channel_id'],'system','dreport_store_all');
|
||||||
|
if($pcf)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// We always add ourself as a recipient to private and relayed posts
|
||||||
|
// So if a remote site says they can't find us, that's no big surprise
|
||||||
|
// and just creates a lot of extra report noise
|
||||||
|
|
||||||
|
if(($dr['location'] !== z_root()) && ($dr['sender'] === $rxchan) && ($dr['status'] === 'recipient not found'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// If you have a private post with a recipient list, every single site is going to report
|
||||||
|
// back a failed delivery for anybody on that list that isn't local to them. We're only
|
||||||
|
// concerned about this if we have a local hubloc record which says we expected them to
|
||||||
|
// have a channel on that site.
|
||||||
|
|
||||||
|
$r = q("select hubloc_id from hubloc where hubloc_hash = '%s' and hubloc_url = '%s'",
|
||||||
|
dbesc($rxchan),
|
||||||
|
dbesc($dr['location'])
|
||||||
|
);
|
||||||
|
if((! $r) && ($dr['status'] === 'recipient_not_found'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$r = q("select abook_id from abook where abook_xchan = '%s' and abook_channel = %d limit 1",
|
||||||
|
dbesc($rxchan),
|
||||||
|
intval($c[0]['channel_id'])
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-17
@@ -754,9 +754,9 @@ class Enotify {
|
|||||||
// generate a multipart/alternative message header
|
// generate a multipart/alternative message header
|
||||||
$messageHeader =
|
$messageHeader =
|
||||||
$params['additionalMailHeader'] .
|
$params['additionalMailHeader'] .
|
||||||
"From: $fromName <{$params['fromEmail']}>\n" .
|
"From: $fromName <{$params['fromEmail']}>" . PHP_EOL .
|
||||||
"Reply-To: $fromName <{$params['replyTo']}>\n" .
|
"Reply-To: $fromName <{$params['replyTo']}>" . PHP_EOL .
|
||||||
"MIME-Version: 1.0\n" .
|
"MIME-Version: 1.0" . PHP_EOL .
|
||||||
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
|
"Content-Type: multipart/alternative; boundary=\"{$mimeBoundary}\"";
|
||||||
|
|
||||||
// assemble the final multipart message body with the text and html types included
|
// assemble the final multipart message body with the text and html types included
|
||||||
@@ -764,15 +764,15 @@ class Enotify {
|
|||||||
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
|
$htmlBody = chunk_split(base64_encode($params['htmlVersion']));
|
||||||
|
|
||||||
$multipartMessageBody =
|
$multipartMessageBody =
|
||||||
"--" . $mimeBoundary . "\n" . // plain text section
|
"--" . $mimeBoundary . PHP_EOL . // plain text section
|
||||||
"Content-Type: text/plain; charset=UTF-8\n" .
|
"Content-Type: text/plain; charset=UTF-8" . PHP_EOL .
|
||||||
"Content-Transfer-Encoding: base64\n\n" .
|
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||||
$textBody . "\n" .
|
$textBody . PHP_EOL .
|
||||||
"--" . $mimeBoundary . "\n" . // text/html section
|
"--" . $mimeBoundary . PHP_EOL . // text/html section
|
||||||
"Content-Type: text/html; charset=UTF-8\n" .
|
"Content-Type: text/html; charset=UTF-8" . PHP_EOL .
|
||||||
"Content-Transfer-Encoding: base64\n\n" .
|
"Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL .
|
||||||
$htmlBody . "\n" .
|
$htmlBody . PHP_EOL .
|
||||||
"--" . $mimeBoundary . "--\n"; // message ending
|
"--" . $mimeBoundary . "--" . PHP_EOL; // message ending
|
||||||
|
|
||||||
// send the message
|
// send the message
|
||||||
$res = mail(
|
$res = mail(
|
||||||
@@ -807,6 +807,11 @@ class Enotify {
|
|||||||
$itemem_text = (($item['item_thread_top'])
|
$itemem_text = (($item['item_thread_top'])
|
||||||
? t('created a new post')
|
? t('created a new post')
|
||||||
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
|
: sprintf( t('commented on %s\'s post'), $item['owner']['xchan_name']));
|
||||||
|
|
||||||
|
if($item['verb'] === ACTIVITY_SHARE) {
|
||||||
|
$itemem_text = sprintf( t('repeated %s\'s post'), $item['author']['xchan_name']);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$edit = false;
|
$edit = false;
|
||||||
@@ -825,19 +830,32 @@ class Enotify {
|
|||||||
|
|
||||||
// convert this logic into a json array just like the system notifications
|
// convert this logic into a json array just like the system notifications
|
||||||
|
|
||||||
return array(
|
$who = (($item['verb'] === ACTIVITY_SHARE) ? 'owner' : 'author');
|
||||||
|
|
||||||
|
$x = array(
|
||||||
'notify_link' => $item['llink'],
|
'notify_link' => $item['llink'],
|
||||||
'name' => $item['author']['xchan_name'],
|
'name' => $item[$who]['xchan_name'],
|
||||||
'url' => $item['author']['xchan_url'],
|
'addr' => (($item[$who]['xchan_addr']) ? $item[$who]['xchan_addr'] : $item[$who]['xchan_url']),
|
||||||
'photo' => $item['author']['xchan_photo_s'],
|
'url' => $item[$who]['xchan_url'],
|
||||||
|
'photo' => $item[$who]['xchan_photo_s'],
|
||||||
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
|
'when' => relative_date(($edit)? $item['edited'] : $item['created']),
|
||||||
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
'class' => (intval($item['item_unseen']) ? 'notify-unseen' : 'notify-seen'),
|
||||||
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
'b64mid' => ((in_array($item['verb'], [ACTIVITY_LIKE, ACTIVITY_DISLIKE])) ? 'b64.' . base64url_encode($item['thr_parent']) : 'b64.' . base64url_encode($item['mid'])),
|
||||||
'notify_id' => 'undefined',
|
'notify_id' => 'undefined',
|
||||||
'thread_top' => (($item['item_thread_top']) ? true : false),
|
'thread_top' => (($item['item_thread_top']) ? true : false),
|
||||||
'message' => strip_tags(bbcode($itemem_text))
|
'message' => strip_tags(bbcode($itemem_text)),
|
||||||
|
// these are for the superblock addon
|
||||||
|
'hash' => $item[$who]['xchan_hash'],
|
||||||
|
'uid' => local_channel(),
|
||||||
|
'display' => true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
call_hooks('enotify_format',$x);
|
||||||
|
if(! $x['display']) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $x;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,405 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Libsync;
|
||||||
|
|
||||||
|
|
||||||
|
class Group {
|
||||||
|
|
||||||
|
static function add($uid,$name,$public = 0) {
|
||||||
|
|
||||||
|
$ret = false;
|
||||||
|
if(x($uid) && x($name)) {
|
||||||
|
$r = self::byname($uid,$name); // check for dups
|
||||||
|
if($r !== false) {
|
||||||
|
|
||||||
|
// This could be a problem.
|
||||||
|
// Let's assume we've just created a group which we once deleted
|
||||||
|
// all the old members are gone, but the group remains so we don't break any security
|
||||||
|
// access lists. What we're doing here is reviving the dead group, but old content which
|
||||||
|
// was restricted to this group may now be seen by the new group members.
|
||||||
|
|
||||||
|
$z = q("SELECT * FROM pgrp WHERE id = %d LIMIT 1",
|
||||||
|
intval($r)
|
||||||
|
);
|
||||||
|
if(($z) && $z[0]['deleted']) {
|
||||||
|
q('UPDATE pgrp SET deleted = 0 WHERE id = %d', intval($z[0]['id']));
|
||||||
|
notice( t('A deleted group with this name was revived. Existing item permissions <strong>may</strong> apply to this group and any future members. If this is not what you intended, please create another group with a different name.') . EOL);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
$dups = false;
|
||||||
|
$hash = random_string(32) . str_replace(['<','>'],['.','.'], $name);
|
||||||
|
|
||||||
|
$r = q("SELECT id FROM pgrp WHERE hash = '%s' LIMIT 1", dbesc($hash));
|
||||||
|
if($r)
|
||||||
|
$dups = true;
|
||||||
|
} while($dups == true);
|
||||||
|
|
||||||
|
|
||||||
|
$r = q("INSERT INTO pgrp ( hash, uid, visible, gname )
|
||||||
|
VALUES( '%s', %d, %d, '%s' ) ",
|
||||||
|
dbesc($hash),
|
||||||
|
intval($uid),
|
||||||
|
intval($public),
|
||||||
|
dbesc($name)
|
||||||
|
);
|
||||||
|
$ret = $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
Libsync::build_sync_packet($uid,null,true);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function remove($uid,$name) {
|
||||||
|
$ret = false;
|
||||||
|
if(x($uid) && x($name)) {
|
||||||
|
$r = q("SELECT id, hash FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||||
|
intval($uid),
|
||||||
|
dbesc($name)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
$group_id = $r[0]['id'];
|
||||||
|
$group_hash = $r[0]['hash'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! $group_id)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// remove group from default posting lists
|
||||||
|
$r = q("SELECT channel_default_group, channel_allow_gid, channel_deny_gid FROM channel WHERE channel_id = %d LIMIT 1",
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
$user_info = $r[0];
|
||||||
|
$change = false;
|
||||||
|
|
||||||
|
if($user_info['channel_default_group'] == $group_hash) {
|
||||||
|
$user_info['channel_default_group'] = '';
|
||||||
|
$change = true;
|
||||||
|
}
|
||||||
|
if(strpos($user_info['channel_allow_gid'], '<' . $group_hash . '>') !== false) {
|
||||||
|
$user_info['channel_allow_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_allow_gid']);
|
||||||
|
$change = true;
|
||||||
|
}
|
||||||
|
if(strpos($user_info['channel_deny_gid'], '<' . $group_hash . '>') !== false) {
|
||||||
|
$user_info['channel_deny_gid'] = str_replace('<' . $group_hash . '>', '', $user_info['channel_deny_gid']);
|
||||||
|
$change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($change) {
|
||||||
|
q("UPDATE channel SET channel_default_group = '%s', channel_allow_gid = '%s', channel_deny_gid = '%s'
|
||||||
|
WHERE channel_id = %d",
|
||||||
|
intval($user_info['channel_default_group']),
|
||||||
|
dbesc($user_info['channel_allow_gid']),
|
||||||
|
dbesc($user_info['channel_deny_gid']),
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove all members
|
||||||
|
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d ",
|
||||||
|
intval($uid),
|
||||||
|
intval($group_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
// remove group
|
||||||
|
$r = q("UPDATE pgrp SET deleted = 1 WHERE uid = %d AND gname = '%s'",
|
||||||
|
intval($uid),
|
||||||
|
dbesc($name)
|
||||||
|
);
|
||||||
|
|
||||||
|
$ret = $r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Libsync::build_sync_packet($uid,null,true);
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function byname($uid,$name) {
|
||||||
|
if((! $uid) || (! strlen($name)))
|
||||||
|
return false;
|
||||||
|
$r = q("SELECT * FROM pgrp WHERE uid = %d AND gname = '%s' LIMIT 1",
|
||||||
|
intval($uid),
|
||||||
|
dbesc($name)
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
return $r[0]['id'];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function rec_byhash($uid,$hash) {
|
||||||
|
if((! $uid) || (! strlen($hash)))
|
||||||
|
return false;
|
||||||
|
$r = q("SELECT * FROM pgrp WHERE uid = %d AND hash = '%s' LIMIT 1",
|
||||||
|
intval($uid),
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
return $r[0];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function member_remove($uid,$name,$member) {
|
||||||
|
$gid = self::byname($uid,$name);
|
||||||
|
if(! $gid)
|
||||||
|
return false;
|
||||||
|
if(! ( $uid && $gid && $member))
|
||||||
|
return false;
|
||||||
|
$r = q("DELETE FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' ",
|
||||||
|
intval($uid),
|
||||||
|
intval($gid),
|
||||||
|
dbesc($member)
|
||||||
|
);
|
||||||
|
|
||||||
|
Libsync::build_sync_packet($uid,null,true);
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function member_add($uid,$name,$member,$gid = 0) {
|
||||||
|
if(! $gid)
|
||||||
|
$gid = self::byname($uid,$name);
|
||||||
|
if((! $gid) || (! $uid) || (! $member))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$r = q("SELECT * FROM pgrp_member WHERE uid = %d AND gid = %d AND xchan = '%s' LIMIT 1",
|
||||||
|
intval($uid),
|
||||||
|
intval($gid),
|
||||||
|
dbesc($member)
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
return true; // You might question this, but
|
||||||
|
// we indicate success because the group member was in fact created
|
||||||
|
// -- It was just created at another time
|
||||||
|
if(! $r)
|
||||||
|
$r = q("INSERT INTO pgrp_member (uid, gid, xchan)
|
||||||
|
VALUES( %d, %d, '%s' ) ",
|
||||||
|
intval($uid),
|
||||||
|
intval($gid),
|
||||||
|
dbesc($member)
|
||||||
|
);
|
||||||
|
|
||||||
|
Libsync::build_sync_packet($uid,null,true);
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function members($gid) {
|
||||||
|
$ret = array();
|
||||||
|
if(intval($gid)) {
|
||||||
|
$r = q("SELECT * FROM pgrp_member
|
||||||
|
LEFT JOIN abook ON abook_xchan = pgrp_member.xchan left join xchan on xchan_hash = abook_xchan
|
||||||
|
WHERE gid = %d AND abook_channel = %d and pgrp_member.uid = %d and xchan_deleted = 0 and abook_self = 0 and abook_blocked = 0 and abook_pending = 0 ORDER BY xchan_name ASC ",
|
||||||
|
intval($gid),
|
||||||
|
intval(local_channel()),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
$ret = $r;
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function members_xchan($gid) {
|
||||||
|
$ret = [];
|
||||||
|
if(intval($gid)) {
|
||||||
|
$r = q("SELECT xchan FROM pgrp_member WHERE gid = %d AND uid = %d",
|
||||||
|
intval($gid),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$ret[] = $rr['xchan'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function members_profile_xchan($uid,$gid) {
|
||||||
|
$ret = [];
|
||||||
|
|
||||||
|
if(intval($gid)) {
|
||||||
|
$r = q("SELECT abook_xchan as xchan from abook left join profile on abook_profile = profile_guid where profile.id = %d and profile.uid = %d",
|
||||||
|
intval($gid),
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$ret[] = $rr['xchan'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static function select($uid,$group = '') {
|
||||||
|
|
||||||
|
$grps = [];
|
||||||
|
$o = '';
|
||||||
|
|
||||||
|
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
$grps[] = array('name' => '', 'hash' => '0', 'selected' => '');
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$grps[] = array('name' => $rr['gname'], 'id' => $rr['hash'], 'selected' => (($group == $rr['hash']) ? 'true' : ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
logger('select: ' . print_r($grps,true), LOGGER_DATA);
|
||||||
|
|
||||||
|
$o = replace_macros(get_markup_template('group_selection.tpl'), array(
|
||||||
|
'$label' => t('Add new connections to this privacy group'),
|
||||||
|
'$groups' => $grps
|
||||||
|
));
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static function widget($every="connections",$each="group",$edit = false, $group_id = 0, $cid = '',$mode = 1) {
|
||||||
|
|
||||||
|
$o = '';
|
||||||
|
|
||||||
|
if(! (local_channel() && feature_enabled(local_channel(),'groups'))) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$groups = array();
|
||||||
|
|
||||||
|
$r = q("SELECT * FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||||
|
intval($_SESSION['uid'])
|
||||||
|
);
|
||||||
|
$member_of = array();
|
||||||
|
if($cid) {
|
||||||
|
$member_of = self::containing(local_channel(),$cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$selected = (($group_id == $rr['id']) ? ' group-selected' : '');
|
||||||
|
|
||||||
|
if ($edit) {
|
||||||
|
$groupedit = [ 'href' => "group/".$rr['id'], 'title' => t('edit') ];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$groupedit = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$groups[] = [
|
||||||
|
'id' => $rr['id'],
|
||||||
|
'enc_cid' => base64url_encode($cid),
|
||||||
|
'cid' => $cid,
|
||||||
|
'text' => $rr['gname'],
|
||||||
|
'selected' => $selected,
|
||||||
|
'href' => (($mode == 0) ? $each.'?f=&gid='.$rr['id'] : $each."/".$rr['id']) . ((x($_GET,'new')) ? '&new=' . $_GET['new'] : '') . ((x($_GET,'order')) ? '&order=' . $_GET['order'] : ''),
|
||||||
|
'edit' => $groupedit,
|
||||||
|
'ismember' => in_array($rr['id'],$member_of),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$tpl = get_markup_template("group_side.tpl");
|
||||||
|
$o = replace_macros($tpl, array(
|
||||||
|
'$title' => t('Privacy Groups'),
|
||||||
|
'$edittext' => t('Edit group'),
|
||||||
|
'$createtext' => t('Add privacy group'),
|
||||||
|
'$ungrouped' => (($every === 'contacts') ? t('Channels not in any privacy group') : ''),
|
||||||
|
'$groups' => $groups,
|
||||||
|
'$add' => t('add'),
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function expand($g) {
|
||||||
|
if(! (is_array($g) && count($g)))
|
||||||
|
return array();
|
||||||
|
|
||||||
|
$ret = [];
|
||||||
|
$x = [];
|
||||||
|
|
||||||
|
// private profile linked virtual groups
|
||||||
|
|
||||||
|
foreach($g as $gv) {
|
||||||
|
if(substr($gv,0,3) === 'vp.') {
|
||||||
|
$profile_hash = substr($gv,3);
|
||||||
|
if($profile_hash) {
|
||||||
|
$r = q("select abook_xchan from abook where abook_profile = '%s'",
|
||||||
|
dbesc($profile_hash)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rv) {
|
||||||
|
$ret[] = $rv['abook_xchan'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$x[] = $gv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($x) {
|
||||||
|
stringify_array_elms($x,true);
|
||||||
|
$groups = implode(',', $x);
|
||||||
|
if($groups) {
|
||||||
|
$r = q("SELECT xchan FROM pgrp_member WHERE gid IN ( select id from pgrp where hash in ( $groups ))");
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr) {
|
||||||
|
$ret[] = $rr['xchan'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function member_of($c) {
|
||||||
|
$r = q("SELECT pgrp.gname, pgrp.id FROM pgrp LEFT JOIN pgrp_member ON pgrp_member.gid = pgrp.id WHERE pgrp_member.xchan = '%s' AND pgrp.deleted = 0 ORDER BY pgrp.gname ASC ",
|
||||||
|
dbesc($c)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $r;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static function containing($uid,$c) {
|
||||||
|
|
||||||
|
$r = q("SELECT gid FROM pgrp_member WHERE uid = %d AND pgrp_member.xchan = '%s' ",
|
||||||
|
intval($uid),
|
||||||
|
dbesc($c)
|
||||||
|
);
|
||||||
|
|
||||||
|
$ret = array();
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr)
|
||||||
|
$ret[] = $rr['gid'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
-8
@@ -2,15 +2,13 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Lib;
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
class JSalmon {
|
class JSalmon {
|
||||||
|
|
||||||
static function sign($data,$key_id,$key) {
|
static function sign($data,$key_id,$key,$data_type = 'application/x-zot+json') {
|
||||||
|
|
||||||
$arr = $data;
|
$data = base64url_encode(json_encode($data,true),true); // strip padding
|
||||||
$data = json_encode($data,JSON_UNESCAPED_SLASHES);
|
|
||||||
$data = base64url_encode($data, false); // do not strip padding
|
|
||||||
$data_type = 'application/x-zot+json';
|
|
||||||
$encoding = 'base64url';
|
$encoding = 'base64url';
|
||||||
$algorithm = 'RSA-SHA256';
|
$algorithm = 'RSA-SHA256';
|
||||||
|
|
||||||
@@ -18,9 +16,9 @@ class JSalmon {
|
|||||||
|
|
||||||
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
// precomputed base64url encoding of data_type, encoding, algorithm concatenated with periods
|
||||||
|
|
||||||
$precomputed = '.' . base64url_encode($data_type,false) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng==';
|
$precomputed = '.' . base64url_encode($data_type,true) . '.YmFzZTY0dXJs.UlNBLVNIQTI1Ng';
|
||||||
|
|
||||||
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), false);
|
$signature = base64url_encode(rsa_sign($data . $precomputed, $key), true);
|
||||||
|
|
||||||
return ([
|
return ([
|
||||||
'signed' => true,
|
'signed' => true,
|
||||||
@@ -30,9 +28,45 @@ class JSalmon {
|
|||||||
'alg' => $algorithm,
|
'alg' => $algorithm,
|
||||||
'sigs' => [
|
'sigs' => [
|
||||||
'value' => $signature,
|
'value' => $signature,
|
||||||
'key_id' => base64url_encode($key_id)
|
'key_id' => base64url_encode($key_id, true)
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function verify($x) {
|
||||||
|
|
||||||
|
logger('verify');
|
||||||
|
$ret = [ 'results' => [] ];
|
||||||
|
|
||||||
|
if(! is_array($x)) {
|
||||||
|
return $false;
|
||||||
|
}
|
||||||
|
if(! ( array_key_exists('signed',$x) && $x['signed'])) {
|
||||||
|
return $false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$signed_data = preg_replace('/\s+/','',$x['data']) . '.'
|
||||||
|
. base64url_encode($x['data_type'],true) . '.'
|
||||||
|
. base64url_encode($x['encoding'],true) . '.'
|
||||||
|
. base64url_encode($x['alg'],true);
|
||||||
|
|
||||||
|
$key = HTTPSig::get_key(EMPTY_STR,base64url_decode($x['sigs']['key_id']));
|
||||||
|
logger('key: ' . print_r($key,true));
|
||||||
|
if($key['portable_id'] && $key['public_key']) {
|
||||||
|
if(rsa_verify($signed_data,base64url_decode($x['sigs']['value']),$key['public_key'])) {
|
||||||
|
logger('verified');
|
||||||
|
$ret = [ 'success' => true, 'signer' => $key['portable_id'], 'hubloc' => $key['hubloc'] ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static function unpack($data) {
|
||||||
|
return json_decode(base64url_decode($data),true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -29,8 +29,8 @@ class LDSignatures {
|
|||||||
$options = [
|
$options = [
|
||||||
'type' => 'RsaSignature2017',
|
'type' => 'RsaSignature2017',
|
||||||
'nonce' => random_string(64),
|
'nonce' => random_string(64),
|
||||||
'creator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
'creator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||||
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\Th:i:s\Z')
|
'created' => datetime_convert('UTC','UTC', 'now', 'Y-m-d\TH:i:s\Z')
|
||||||
];
|
];
|
||||||
|
|
||||||
$ohash = self::hash(self::signable_options($options));
|
$ohash = self::hash(self::signable_options($options));
|
||||||
@@ -124,7 +124,7 @@ class LDSignatures {
|
|||||||
'meDataType' => $data_type,
|
'meDataType' => $data_type,
|
||||||
'meEncoding' => $encoding,
|
'meEncoding' => $encoding,
|
||||||
'meAlgorithm' => $algorithm,
|
'meAlgorithm' => $algorithm,
|
||||||
'meCreator' => z_root() . '/channel/' . $channel['channel_address'] . '/public_key_pem',
|
'meCreator' => z_root() . '/channel/' . $channel['channel_address'],
|
||||||
'meSignatureValue' => $signature
|
'meSignatureValue' => $signature
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -132,4 +132,4 @@ class LDSignatures {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,654 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Libzot;
|
||||||
|
|
||||||
|
require_once('include/permissions.php');
|
||||||
|
|
||||||
|
|
||||||
|
class Libzotdir {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param int $dirmode
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function find_upstream_directory($dirmode) {
|
||||||
|
global $DIRECTORY_FALLBACK_SERVERS;
|
||||||
|
|
||||||
|
$preferred = get_config('system','directory_server');
|
||||||
|
|
||||||
|
// Thwart attempts to use a private directory
|
||||||
|
|
||||||
|
if(($preferred) && ($preferred != z_root())) {
|
||||||
|
$r = q("select * from site where site_url = '%s' limit 1",
|
||||||
|
dbesc($preferred)
|
||||||
|
);
|
||||||
|
if(($r) && ($r[0]['site_flags'] & DIRECTORY_MODE_STANDALONE)) {
|
||||||
|
$preferred = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (! $preferred) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No directory has yet been set. For most sites, pick one at random
|
||||||
|
* from our list of directory servers. However, if we're a directory
|
||||||
|
* server ourself, point at the local instance
|
||||||
|
* We will then set this value so this should only ever happen once.
|
||||||
|
* Ideally there will be an admin setting to change to a different
|
||||||
|
* directory server if you don't like our choice or if circumstances change.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$dirmode = intval(get_config('system','directory_mode'));
|
||||||
|
if ($dirmode == DIRECTORY_MODE_NORMAL) {
|
||||||
|
$toss = mt_rand(0,count($DIRECTORY_FALLBACK_SERVERS));
|
||||||
|
$preferred = $DIRECTORY_FALLBACK_SERVERS[$toss];
|
||||||
|
if(! $preferred) {
|
||||||
|
$preferred = DIRECTORY_FALLBACK_MASTER;
|
||||||
|
}
|
||||||
|
set_config('system','directory_server',$preferred);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
set_config('system','directory_server',z_root());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($preferred) {
|
||||||
|
return [ 'url' => $preferred ];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directories may come and go over time. We will need to check that our
|
||||||
|
* directory server is still valid occasionally, and reset to something that
|
||||||
|
* is if our directory has gone offline for any reason
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function check_upstream_directory() {
|
||||||
|
|
||||||
|
$directory = get_config('system', 'directory_server');
|
||||||
|
|
||||||
|
// it's possible there is no directory server configured and the local hub is being used.
|
||||||
|
// If so, default to preserving the absence of a specific server setting.
|
||||||
|
|
||||||
|
$isadir = true;
|
||||||
|
|
||||||
|
if ($directory) {
|
||||||
|
$j = Zotfinger::exec($directory);
|
||||||
|
if(array_path_exists('data/directory_mode',$j)) {
|
||||||
|
if ($j['data']['directory_mode'] === 'normal') {
|
||||||
|
$isadir = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $isadir)
|
||||||
|
set_config('system', 'directory_server', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function get_directory_setting($observer, $setting) {
|
||||||
|
|
||||||
|
if ($observer)
|
||||||
|
$ret = get_xconfig($observer, 'directory', $setting);
|
||||||
|
else
|
||||||
|
$ret = ((array_key_exists($setting,$_SESSION)) ? intval($_SESSION[$setting]) : false);
|
||||||
|
|
||||||
|
if($ret === false)
|
||||||
|
$ret = get_config('directory', $setting);
|
||||||
|
|
||||||
|
|
||||||
|
// 'safemode' is the default if there is no observer or no established preference.
|
||||||
|
|
||||||
|
if($setting === 'safemode' && $ret === false)
|
||||||
|
$ret = 1;
|
||||||
|
|
||||||
|
if($setting === 'globaldir' && intval(get_config('system','localdir_hide')))
|
||||||
|
$ret = 1;
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called by the directory_sort widget.
|
||||||
|
*/
|
||||||
|
static function dir_sort_links() {
|
||||||
|
|
||||||
|
$safe_mode = 1;
|
||||||
|
|
||||||
|
$observer = get_observer_hash();
|
||||||
|
|
||||||
|
$safe_mode = self::get_directory_setting($observer, 'safemode');
|
||||||
|
$globaldir = self::get_directory_setting($observer, 'globaldir');
|
||||||
|
$pubforums = self::get_directory_setting($observer, 'pubforums');
|
||||||
|
|
||||||
|
$hide_local = intval(get_config('system','localdir_hide'));
|
||||||
|
if($hide_local)
|
||||||
|
$globaldir = 1;
|
||||||
|
|
||||||
|
|
||||||
|
// Build urls without order and pubforums so it's easy to tack on the changed value
|
||||||
|
// Probably there's an easier way to do this
|
||||||
|
|
||||||
|
$directory_sort_order = get_config('system','directory_sort_order');
|
||||||
|
if(! $directory_sort_order)
|
||||||
|
$directory_sort_order = 'date';
|
||||||
|
|
||||||
|
$current_order = (($_REQUEST['order']) ? $_REQUEST['order'] : $directory_sort_order);
|
||||||
|
$suggest = (($_REQUEST['suggest']) ? '&suggest=' . $_REQUEST['suggest'] : '');
|
||||||
|
|
||||||
|
$url = 'directory?f=';
|
||||||
|
|
||||||
|
$tmp = array_merge($_GET,$_POST);
|
||||||
|
unset($tmp['suggest']);
|
||||||
|
unset($tmp['pubforums']);
|
||||||
|
unset($tmp['global']);
|
||||||
|
unset($tmp['safe']);
|
||||||
|
unset($tmp['q']);
|
||||||
|
unset($tmp['f']);
|
||||||
|
$forumsurl = $url . http_build_query($tmp) . $suggest;
|
||||||
|
|
||||||
|
$o = replace_macros(get_markup_template('dir_sort_links.tpl'), [
|
||||||
|
'$header' => t('Directory Options'),
|
||||||
|
'$forumsurl' => $forumsurl,
|
||||||
|
'$safemode' => array('safemode', t('Safe Mode'),$safe_mode,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&safe="+(this.checked ? 1 : 0)\''),
|
||||||
|
'$pubforums' => array('pubforums', t('Public Forums Only'),$pubforums,'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&pubforums="+(this.checked ? 1 : 0)\''),
|
||||||
|
'$hide_local' => $hide_local,
|
||||||
|
'$globaldir' => array('globaldir', t('This Website Only'), 1-intval($globaldir),'',array(t('No'), t('Yes')),' onchange=\'window.location.href="' . $forumsurl . '&global="+(this.checked ? 0 : 1)\''),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks the directory mode of this hub.
|
||||||
|
*
|
||||||
|
* Checks the directory mode of this hub to see if it is some form of directory server. If it is,
|
||||||
|
* get the directory realm of this hub. Fetch a list of all other directory servers in this realm and request
|
||||||
|
* a directory sync packet. This will contain both directory updates and new ratings. Store these all in the DB.
|
||||||
|
* In the case of updates, we will query each of them asynchronously from a poller task. Ratings are stored
|
||||||
|
* directly if the rater's signature matches.
|
||||||
|
*
|
||||||
|
* @param int $dirmode;
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function sync_directories($dirmode) {
|
||||||
|
|
||||||
|
if ($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_NORMAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
$realm = get_directory_realm();
|
||||||
|
if ($realm == DIRECTORY_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' and site_type = %d ",
|
||||||
|
intval(DIRECTORY_MODE_PRIMARY|DIRECTORY_MODE_SECONDARY),
|
||||||
|
dbesc(z_root()),
|
||||||
|
dbesc(protect_sprintf('%' . $realm . '%')),
|
||||||
|
intval(SITE_TYPE_ZOT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are no directory servers, setup the fallback master
|
||||||
|
/** @FIXME What to do if we're in a different realm? */
|
||||||
|
|
||||||
|
if ((! $r) && (z_root() != DIRECTORY_FALLBACK_MASTER)) {
|
||||||
|
|
||||||
|
$x = site_store_lowlevel(
|
||||||
|
[
|
||||||
|
'site_url' => DIRECTORY_FALLBACK_MASTER,
|
||||||
|
'site_flags' => DIRECTORY_MODE_PRIMARY,
|
||||||
|
'site_update' => NULL_DATE,
|
||||||
|
'site_directory' => DIRECTORY_FALLBACK_MASTER . '/dirsearch',
|
||||||
|
'site_realm' => DIRECTORY_REALM,
|
||||||
|
'site_valid' => 1,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
$r = q("select * from site where site_flags in (%d, %d) and site_url != '%s' and site_type = %d ",
|
||||||
|
intval(DIRECTORY_MODE_PRIMARY),
|
||||||
|
intval(DIRECTORY_MODE_SECONDARY),
|
||||||
|
dbesc(z_root()),
|
||||||
|
intval(SITE_TYPE_ZOT)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (! $r)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach ($r as $rr) {
|
||||||
|
if (! $rr['site_directory'])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
logger('sync directories: ' . $rr['site_directory']);
|
||||||
|
|
||||||
|
// for brand new directory servers, only load the last couple of days.
|
||||||
|
// It will take about a month for a new directory to obtain the full current repertoire of channels.
|
||||||
|
/** @FIXME Go back and pick up earlier ratings if this is a new directory server. These do not get refreshed. */
|
||||||
|
|
||||||
|
$token = get_config('system','realm_token');
|
||||||
|
|
||||||
|
$syncdate = (($rr['site_sync'] <= NULL_DATE) ? datetime_convert('UTC','UTC','now - 2 days') : $rr['site_sync']);
|
||||||
|
$x = z_fetch_url($rr['site_directory'] . '?f=&sync=' . urlencode($syncdate) . (($token) ? '&t=' . $token : ''));
|
||||||
|
|
||||||
|
if (! $x['success'])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$j = json_decode($x['body'],true);
|
||||||
|
if (!($j['transactions']) || ($j['ratings']))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
q("update site set site_sync = '%s' where site_url = '%s'",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc($rr['site_url'])
|
||||||
|
);
|
||||||
|
|
||||||
|
logger('sync_directories: ' . $rr['site_url'] . ': ' . print_r($j,true), LOGGER_DATA);
|
||||||
|
|
||||||
|
if (is_array($j['transactions']) && count($j['transactions'])) {
|
||||||
|
foreach ($j['transactions'] as $t) {
|
||||||
|
$r = q("select * from updates where ud_guid = '%s' limit 1",
|
||||||
|
dbesc($t['transaction_id'])
|
||||||
|
);
|
||||||
|
if($r)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$ud_flags = 0;
|
||||||
|
if (is_array($t['flags']) && in_array('deleted',$t['flags']))
|
||||||
|
$ud_flags |= UPDATE_FLAGS_DELETED;
|
||||||
|
if (is_array($t['flags']) && in_array('forced',$t['flags']))
|
||||||
|
$ud_flags |= UPDATE_FLAGS_FORCED;
|
||||||
|
|
||||||
|
$z = q("insert into updates ( ud_hash, ud_guid, ud_date, ud_flags, ud_addr )
|
||||||
|
values ( '%s', '%s', '%s', %d, '%s' ) ",
|
||||||
|
dbesc($t['hash']),
|
||||||
|
dbesc($t['transaction_id']),
|
||||||
|
dbesc($t['timestamp']),
|
||||||
|
intval($ud_flags),
|
||||||
|
dbesc($t['address'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* Given an update record, probe the channel, grab a zot-info packet and refresh/sync the data.
|
||||||
|
*
|
||||||
|
* Ignore updating records marked as deleted.
|
||||||
|
*
|
||||||
|
* If successful, sets ud_last in the DB to the current datetime for this
|
||||||
|
* reddress/webbie.
|
||||||
|
*
|
||||||
|
* @param array $ud Entry from update table
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function update_directory_entry($ud) {
|
||||||
|
|
||||||
|
logger('update_directory_entry: ' . print_r($ud,true), LOGGER_DATA);
|
||||||
|
|
||||||
|
if ($ud['ud_addr'] && (! ($ud['ud_flags'] & UPDATE_FLAGS_DELETED))) {
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
$href = \Zotlabs\Lib\Webfinger::zot_url(punify($ud['ud_addr']));
|
||||||
|
if($href) {
|
||||||
|
$zf = \Zotlabs\Lib\Zotfinger::exec($href);
|
||||||
|
}
|
||||||
|
if(is_array($zf) && array_path_exists('signature/signer',$zf) && $zf['signature']['signer'] === $href && intval($zf['signature']['header_valid'])) {
|
||||||
|
$xc = Libzot::import_xchan($zf['data'], 0, $ud);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
q("update updates set ud_last = '%s' where ud_addr = '%s'",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc($ud['ud_addr'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Push local channel updates to a local directory server.
|
||||||
|
*
|
||||||
|
* This is called from include/directory.php if a profile is to be pushed to the
|
||||||
|
* directory and the local hub in this case is any kind of directory server.
|
||||||
|
*
|
||||||
|
* @param int $uid
|
||||||
|
* @param boolean $force
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function local_dir_update($uid, $force) {
|
||||||
|
|
||||||
|
|
||||||
|
logger('local_dir_update: uid: ' . $uid, LOGGER_DEBUG);
|
||||||
|
|
||||||
|
$p = q("select channel.channel_hash, channel_address, channel_timezone, profile.* from profile left join channel on channel_id = uid where uid = %d and is_default = 1",
|
||||||
|
intval($uid)
|
||||||
|
);
|
||||||
|
|
||||||
|
$profile = array();
|
||||||
|
$profile['encoding'] = 'zot';
|
||||||
|
|
||||||
|
if ($p) {
|
||||||
|
$hash = $p[0]['channel_hash'];
|
||||||
|
|
||||||
|
$profile['description'] = $p[0]['pdesc'];
|
||||||
|
$profile['birthday'] = $p[0]['dob'];
|
||||||
|
if ($age = age($p[0]['dob'],$p[0]['channel_timezone'],''))
|
||||||
|
$profile['age'] = $age;
|
||||||
|
|
||||||
|
$profile['gender'] = $p[0]['gender'];
|
||||||
|
$profile['marital'] = $p[0]['marital'];
|
||||||
|
$profile['sexual'] = $p[0]['sexual'];
|
||||||
|
$profile['locale'] = $p[0]['locality'];
|
||||||
|
$profile['region'] = $p[0]['region'];
|
||||||
|
$profile['postcode'] = $p[0]['postal_code'];
|
||||||
|
$profile['country'] = $p[0]['country_name'];
|
||||||
|
$profile['about'] = $p[0]['about'];
|
||||||
|
$profile['homepage'] = $p[0]['homepage'];
|
||||||
|
$profile['hometown'] = $p[0]['hometown'];
|
||||||
|
|
||||||
|
if ($p[0]['keywords']) {
|
||||||
|
$tags = array();
|
||||||
|
$k = explode(' ', $p[0]['keywords']);
|
||||||
|
if ($k)
|
||||||
|
foreach ($k as $kk)
|
||||||
|
if (trim($kk))
|
||||||
|
$tags[] = trim($kk);
|
||||||
|
|
||||||
|
if ($tags)
|
||||||
|
$profile['keywords'] = $tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
$hidden = (1 - intval($p[0]['publish']));
|
||||||
|
|
||||||
|
logger('hidden: ' . $hidden);
|
||||||
|
|
||||||
|
$r = q("select xchan_hidden from xchan where xchan_hash = '%s' limit 1",
|
||||||
|
dbesc($p[0]['channel_hash'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if(intval($r[0]['xchan_hidden']) != $hidden) {
|
||||||
|
$r = q("update xchan set xchan_hidden = %d where xchan_hash = '%s'",
|
||||||
|
intval($hidden),
|
||||||
|
dbesc($p[0]['channel_hash'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$arr = [ 'channel_id' => $uid, 'hash' => $hash, 'profile' => $profile ];
|
||||||
|
call_hooks('local_dir_update', $arr);
|
||||||
|
|
||||||
|
$address = channel_reddress($p[0]);
|
||||||
|
|
||||||
|
if (perm_is_allowed($uid, '', 'view_profile')) {
|
||||||
|
self::import_directory_profile($hash, $arr['profile'], $address, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// they may have made it private
|
||||||
|
$r = q("delete from xprof where xprof_hash = '%s'",
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
$r = q("delete from xtag where xtag_hash = '%s'",
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$ud_hash = random_string() . '@' . \App::get_hostname();
|
||||||
|
self::update_modtime($hash, $ud_hash, channel_reddress($p[0]),(($force) ? UPDATE_FLAGS_FORCED : UPDATE_FLAGS_UPDATED));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Imports a directory profile.
|
||||||
|
*
|
||||||
|
* @param string $hash
|
||||||
|
* @param array $profile
|
||||||
|
* @param string $addr
|
||||||
|
* @param number $ud_flags (optional) UPDATE_FLAGS_UPDATED
|
||||||
|
* @param number $suppress_update (optional) default 0
|
||||||
|
* @return boolean $updated if something changed
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function import_directory_profile($hash, $profile, $addr, $ud_flags = UPDATE_FLAGS_UPDATED, $suppress_update = 0) {
|
||||||
|
|
||||||
|
logger('import_directory_profile', LOGGER_DEBUG);
|
||||||
|
if (! $hash)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$arr = array();
|
||||||
|
|
||||||
|
$arr['xprof_hash'] = $hash;
|
||||||
|
$arr['xprof_dob'] = (($profile['birthday'] === '0000-00-00') ? $profile['birthday'] : datetime_convert('','',$profile['birthday'],'Y-m-d')); // !!!! check this for 0000 year
|
||||||
|
$arr['xprof_age'] = (($profile['age']) ? intval($profile['age']) : 0);
|
||||||
|
$arr['xprof_desc'] = (($profile['description']) ? htmlspecialchars($profile['description'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_gender'] = (($profile['gender']) ? htmlspecialchars($profile['gender'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_marital'] = (($profile['marital']) ? htmlspecialchars($profile['marital'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_sexual'] = (($profile['sexual']) ? htmlspecialchars($profile['sexual'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_locale'] = (($profile['locale']) ? htmlspecialchars($profile['locale'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_region'] = (($profile['region']) ? htmlspecialchars($profile['region'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_postcode'] = (($profile['postcode']) ? htmlspecialchars($profile['postcode'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_country'] = (($profile['country']) ? htmlspecialchars($profile['country'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_about'] = (($profile['about']) ? htmlspecialchars($profile['about'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_homepage'] = (($profile['homepage']) ? htmlspecialchars($profile['homepage'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
$arr['xprof_hometown'] = (($profile['hometown']) ? htmlspecialchars($profile['hometown'], ENT_COMPAT,'UTF-8',false) : '');
|
||||||
|
|
||||||
|
$clean = array();
|
||||||
|
if (array_key_exists('keywords', $profile) and is_array($profile['keywords'])) {
|
||||||
|
self::import_directory_keywords($hash,$profile['keywords']);
|
||||||
|
foreach ($profile['keywords'] as $kw) {
|
||||||
|
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||||
|
$kw = trim($kw, ',');
|
||||||
|
$clean[] = $kw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$arr['xprof_keywords'] = implode(' ',$clean);
|
||||||
|
|
||||||
|
// Self censored, make it so
|
||||||
|
// These are not translated, so the German "erwachsenen" keyword will not censor the directory profile. Only the English form - "adult".
|
||||||
|
|
||||||
|
|
||||||
|
if(in_arrayi('nsfw',$clean) || in_arrayi('adult',$clean)) {
|
||||||
|
q("update xchan set xchan_selfcensored = 1 where xchan_hash = '%s'",
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$r = q("select * from xprof where xprof_hash = '%s' limit 1",
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($arr['xprof_age'] > 150)
|
||||||
|
$arr['xprof_age'] = 150;
|
||||||
|
if ($arr['xprof_age'] < 0)
|
||||||
|
$arr['xprof_age'] = 0;
|
||||||
|
|
||||||
|
if ($r) {
|
||||||
|
$update = false;
|
||||||
|
foreach ($r[0] as $k => $v) {
|
||||||
|
if ((array_key_exists($k,$arr)) && ($arr[$k] != $v)) {
|
||||||
|
logger('import_directory_profile: update ' . $k . ' => ' . $arr[$k]);
|
||||||
|
$update = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($update) {
|
||||||
|
q("update xprof set
|
||||||
|
xprof_desc = '%s',
|
||||||
|
xprof_dob = '%s',
|
||||||
|
xprof_age = %d,
|
||||||
|
xprof_gender = '%s',
|
||||||
|
xprof_marital = '%s',
|
||||||
|
xprof_sexual = '%s',
|
||||||
|
xprof_locale = '%s',
|
||||||
|
xprof_region = '%s',
|
||||||
|
xprof_postcode = '%s',
|
||||||
|
xprof_country = '%s',
|
||||||
|
xprof_about = '%s',
|
||||||
|
xprof_homepage = '%s',
|
||||||
|
xprof_hometown = '%s',
|
||||||
|
xprof_keywords = '%s'
|
||||||
|
where xprof_hash = '%s'",
|
||||||
|
dbesc($arr['xprof_desc']),
|
||||||
|
dbesc($arr['xprof_dob']),
|
||||||
|
intval($arr['xprof_age']),
|
||||||
|
dbesc($arr['xprof_gender']),
|
||||||
|
dbesc($arr['xprof_marital']),
|
||||||
|
dbesc($arr['xprof_sexual']),
|
||||||
|
dbesc($arr['xprof_locale']),
|
||||||
|
dbesc($arr['xprof_region']),
|
||||||
|
dbesc($arr['xprof_postcode']),
|
||||||
|
dbesc($arr['xprof_country']),
|
||||||
|
dbesc($arr['xprof_about']),
|
||||||
|
dbesc($arr['xprof_homepage']),
|
||||||
|
dbesc($arr['xprof_hometown']),
|
||||||
|
dbesc($arr['xprof_keywords']),
|
||||||
|
dbesc($arr['xprof_hash'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$update = true;
|
||||||
|
logger('New profile');
|
||||||
|
q("insert into xprof (xprof_hash, xprof_desc, xprof_dob, xprof_age, xprof_gender, xprof_marital, xprof_sexual, xprof_locale, xprof_region, xprof_postcode, xprof_country, xprof_about, xprof_homepage, xprof_hometown, xprof_keywords) values ('%s', '%s', '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s') ",
|
||||||
|
dbesc($arr['xprof_hash']),
|
||||||
|
dbesc($arr['xprof_desc']),
|
||||||
|
dbesc($arr['xprof_dob']),
|
||||||
|
intval($arr['xprof_age']),
|
||||||
|
dbesc($arr['xprof_gender']),
|
||||||
|
dbesc($arr['xprof_marital']),
|
||||||
|
dbesc($arr['xprof_sexual']),
|
||||||
|
dbesc($arr['xprof_locale']),
|
||||||
|
dbesc($arr['xprof_region']),
|
||||||
|
dbesc($arr['xprof_postcode']),
|
||||||
|
dbesc($arr['xprof_country']),
|
||||||
|
dbesc($arr['xprof_about']),
|
||||||
|
dbesc($arr['xprof_homepage']),
|
||||||
|
dbesc($arr['xprof_hometown']),
|
||||||
|
dbesc($arr['xprof_keywords'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$d = [
|
||||||
|
'xprof' => $arr,
|
||||||
|
'profile' => $profile,
|
||||||
|
'update' => $update
|
||||||
|
];
|
||||||
|
/**
|
||||||
|
* @hooks import_directory_profile
|
||||||
|
* Called when processing delivery of a profile structure from an external source (usually for directory storage).
|
||||||
|
* * \e array \b xprof
|
||||||
|
* * \e array \b profile
|
||||||
|
* * \e boolean \b update
|
||||||
|
*/
|
||||||
|
call_hooks('import_directory_profile', $d);
|
||||||
|
|
||||||
|
if (($d['update']) && (! $suppress_update))
|
||||||
|
self::update_modtime($arr['xprof_hash'],random_string() . '@' . \App::get_hostname(), $addr, $ud_flags);
|
||||||
|
|
||||||
|
return $d['update'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param string $hash An xtag_hash
|
||||||
|
* @param array $keywords
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function import_directory_keywords($hash, $keywords) {
|
||||||
|
|
||||||
|
$existing = array();
|
||||||
|
$r = q("select * from xtag where xtag_hash = '%s' and xtag_flags = 0",
|
||||||
|
dbesc($hash)
|
||||||
|
);
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
foreach($r as $rr)
|
||||||
|
$existing[] = $rr['xtag_term'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$clean = array();
|
||||||
|
foreach($keywords as $kw) {
|
||||||
|
$kw = trim(htmlspecialchars($kw,ENT_COMPAT, 'UTF-8', false));
|
||||||
|
$kw = trim($kw, ',');
|
||||||
|
$clean[] = $kw;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($existing as $x) {
|
||||||
|
if(! in_array($x, $clean))
|
||||||
|
$r = q("delete from xtag where xtag_hash = '%s' and xtag_term = '%s' and xtag_flags = 0",
|
||||||
|
dbesc($hash),
|
||||||
|
dbesc($x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
foreach($clean as $x) {
|
||||||
|
if(! in_array($x, $existing)) {
|
||||||
|
$r = q("insert into xtag ( xtag_hash, xtag_term, xtag_flags) values ( '%s' ,'%s', 0 )",
|
||||||
|
dbesc($hash),
|
||||||
|
dbesc($x)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param string $hash
|
||||||
|
* @param string $guid
|
||||||
|
* @param string $addr
|
||||||
|
* @param int $flags (optional) default 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function update_modtime($hash, $guid, $addr, $flags = 0) {
|
||||||
|
|
||||||
|
$dirmode = intval(get_config('system', 'directory_mode'));
|
||||||
|
|
||||||
|
if($dirmode == DIRECTORY_MODE_NORMAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if($flags) {
|
||||||
|
q("insert into updates (ud_hash, ud_guid, ud_date, ud_flags, ud_addr ) values ( '%s', '%s', '%s', %d, '%s' )",
|
||||||
|
dbesc($hash),
|
||||||
|
dbesc($guid),
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
intval($flags),
|
||||||
|
dbesc($addr)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
q("update updates set ud_flags = ( ud_flags | %d ) where ud_addr = '%s' and not (ud_flags & %d)>0 ",
|
||||||
|
intval(UPDATE_FLAGS_UPDATED),
|
||||||
|
dbesc($addr),
|
||||||
|
intval(UPDATE_FLAGS_UPDATED)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -19,7 +19,7 @@ class MessageFilter {
|
|||||||
|
|
||||||
$lang = null;
|
$lang = null;
|
||||||
|
|
||||||
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false)) {
|
if((strpos($incl,'lang=') !== false) || (strpos($excl,'lang=') !== false) || (strpos($incl,'lang!=') !== false) || (strpos($excl,'lang!=') !== false)) {
|
||||||
$lang = detect_language($text);
|
$lang = detect_language($text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,10 +39,17 @@ class MessageFilter {
|
|||||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
elseif(substr($word,0,1) === '$' && $tags) {
|
||||||
|
foreach($tags as $t)
|
||||||
|
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||||
return false;
|
return false;
|
||||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||||
return false;
|
return false;
|
||||||
|
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||||
|
return false;
|
||||||
elseif(stristr($text,$word) !== false)
|
elseif(stristr($text,$word) !== false)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -60,10 +67,17 @@ class MessageFilter {
|
|||||||
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
if((($t['ttype'] == TERM_HASHTAG) || ($t['ttype'] == TERM_COMMUNITYTAG)) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
elseif(substr($word,0,1) === '$' && $tags) {
|
||||||
|
foreach($tags as $t)
|
||||||
|
if(($t['ttype'] == TERM_CATEGORY) && (($t['term'] === substr($word,1)) || (substr($word,1) === '*')))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
elseif((strpos($word,'/') === 0) && preg_match($word,$text))
|
||||||
return true;
|
return true;
|
||||||
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
elseif((strpos($word,'lang=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,5))) == 0))
|
||||||
return true;
|
return true;
|
||||||
|
elseif((strpos($word,'lang!=') === 0) && ($lang) && (strcasecmp($lang,trim(substr($word,6))) != 0))
|
||||||
|
return true;
|
||||||
elseif(stristr($text,$word) !== false)
|
elseif(stristr($text,$word) !== false)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-17
@@ -26,7 +26,8 @@ class NativeWiki {
|
|||||||
|
|
||||||
$w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
|
$w['rawName'] = get_iconfig($w, 'wiki', 'rawName');
|
||||||
$w['htmlName'] = escape_tags($w['rawName']);
|
$w['htmlName'] = escape_tags($w['rawName']);
|
||||||
$w['urlName'] = urlencode(urlencode($w['rawName']));
|
//$w['urlName'] = urlencode(urlencode($w['rawName']));
|
||||||
|
$w['urlName'] = self::name_encode($w['rawName']);
|
||||||
$w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
|
$w['mimeType'] = get_iconfig($w, 'wiki', 'mimeType');
|
||||||
$w['typelock'] = get_iconfig($w, 'wiki', 'typelock');
|
$w['typelock'] = get_iconfig($w, 'wiki', 'typelock');
|
||||||
$w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock');
|
$w['lockstate'] = (($w['allow_cid'] || $w['allow_gid'] || $w['deny_cid'] || $w['deny_gid']) ? 'lock' : 'unlock');
|
||||||
@@ -39,26 +40,17 @@ class NativeWiki {
|
|||||||
|
|
||||||
function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
function create_wiki($channel, $observer_hash, $wiki, $acl) {
|
||||||
|
|
||||||
// Generate unique resource_id using the same method as item_message_id()
|
$resource_id = new_uuid();
|
||||||
do {
|
$uuid = new_uuid();
|
||||||
$dups = false;
|
|
||||||
$resource_id = random_string();
|
|
||||||
$r = q("SELECT mid FROM item WHERE resource_id = '%s' AND resource_type = '%s' AND uid = %d LIMIT 1",
|
|
||||||
dbesc($resource_id),
|
|
||||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
|
||||||
intval($channel['channel_id'])
|
|
||||||
);
|
|
||||||
if($r)
|
|
||||||
$dups = true;
|
|
||||||
} while($dups == true);
|
|
||||||
|
|
||||||
$ac = $acl->get();
|
$ac = $acl->get();
|
||||||
$mid = item_message_id();
|
$mid = z_root() . '/item/' . $uuid;
|
||||||
|
|
||||||
$arr = array(); // Initialize the array of parameters for the post
|
$arr = array(); // Initialize the array of parameters for the post
|
||||||
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
|
$item_hidden = ((intval($wiki['postVisible']) === 0) ? 1 : 0);
|
||||||
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
|
$wiki_url = z_root() . '/wiki/' . $channel['channel_address'] . '/' . $wiki['urlName'];
|
||||||
$arr['aid'] = $channel['channel_account_id'];
|
$arr['aid'] = $channel['channel_account_id'];
|
||||||
|
$arr['uuid'] = $uuid;
|
||||||
$arr['uid'] = $channel['channel_id'];
|
$arr['uid'] = $channel['channel_id'];
|
||||||
$arr['mid'] = $mid;
|
$arr['mid'] = $mid;
|
||||||
$arr['parent_mid'] = $mid;
|
$arr['parent_mid'] = $mid;
|
||||||
@@ -199,7 +191,7 @@ class NativeWiki {
|
|||||||
return array('item' => null, 'success' => false);
|
return array('item' => null, 'success' => false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$drop = drop_item($item['id'], false, DROPITEM_NORMAL, true);
|
$drop = drop_item($item['id'], false, DROPITEM_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
info( t('Wiki files deleted successfully'));
|
info( t('Wiki files deleted successfully'));
|
||||||
@@ -233,7 +225,8 @@ class NativeWiki {
|
|||||||
'wiki' => $w,
|
'wiki' => $w,
|
||||||
'rawName' => $rawName,
|
'rawName' => $rawName,
|
||||||
'htmlName' => escape_tags($rawName),
|
'htmlName' => escape_tags($rawName),
|
||||||
'urlName' => urlencode(urlencode($rawName)),
|
//'urlName' => urlencode(urlencode($rawName)),
|
||||||
|
'urlName' => self::name_encode($rawName),
|
||||||
'mimeType' => $mimeType,
|
'mimeType' => $mimeType,
|
||||||
'typelock' => $typelock
|
'typelock' => $typelock
|
||||||
);
|
);
|
||||||
@@ -249,7 +242,8 @@ class NativeWiki {
|
|||||||
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
|
WHERE resource_type = '%s' AND iconfig.v = '%s' AND uid = %d
|
||||||
AND item_deleted = 0 $sql_extra limit 1",
|
AND item_deleted = 0 $sql_extra limit 1",
|
||||||
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
dbesc(NWIKI_ITEM_RESOURCE_TYPE),
|
||||||
dbesc(urldecode($urlName)),
|
//dbesc(urldecode($urlName)),
|
||||||
|
dbesc(self::name_decode($urlName)),
|
||||||
intval($uid)
|
intval($uid)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -286,4 +280,32 @@ class NativeWiki {
|
|||||||
return array('read' => true, 'write' => $write, 'success' => true);
|
return array('read' => true, 'write' => $write, 'success' => true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function name_encode ($string) {
|
||||||
|
|
||||||
|
$string = html_entity_decode($string);
|
||||||
|
$encoding = mb_internal_encoding();
|
||||||
|
mb_internal_encoding("UTF-8");
|
||||||
|
$ret = mb_ereg_replace_callback ('[^A-Za-z0-9\-\_\.\~]',function ($char) {
|
||||||
|
$charhex = unpack('H*',$char[0]);
|
||||||
|
$ret = '('.$charhex[1].')';
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
,$string);
|
||||||
|
mb_internal_encoding($encoding);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function name_decode ($string) {
|
||||||
|
|
||||||
|
$encoding = mb_internal_encoding();
|
||||||
|
mb_internal_encoding("UTF-8");
|
||||||
|
$ret = mb_ereg_replace_callback ('(\(([0-9a-f]+)\))',function ($chars) {
|
||||||
|
return pack('H*',$chars[2]);
|
||||||
|
}
|
||||||
|
,$string);
|
||||||
|
mb_internal_encoding($encoding);
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ class NativeWikiPage {
|
|||||||
$pages[] = [
|
$pages[] = [
|
||||||
'resource_id' => $resource_id,
|
'resource_id' => $resource_id,
|
||||||
'title' => escape_tags($title),
|
'title' => escape_tags($title),
|
||||||
'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
|
//'url' => str_replace('%2F','/',urlencode(str_replace('%2F','/',urlencode($title)))),
|
||||||
|
'url' => Zlib\NativeWiki::name_encode($title),
|
||||||
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
|
'link_id' => 'id_' . substr($resource_id, 0, 10) . '_' . $page_item['id']
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -98,7 +99,8 @@ class NativeWikiPage {
|
|||||||
$page = [
|
$page = [
|
||||||
'rawName' => $name,
|
'rawName' => $name,
|
||||||
'htmlName' => escape_tags($name),
|
'htmlName' => escape_tags($name),
|
||||||
'urlName' => urlencode($name),
|
//'urlName' => urlencode($name),
|
||||||
|
'urlName' => Zlib\NativeWiki::name_encode($name)
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -154,7 +156,8 @@ class NativeWikiPage {
|
|||||||
$page = [
|
$page = [
|
||||||
'rawName' => $pageNewName,
|
'rawName' => $pageNewName,
|
||||||
'htmlName' => escape_tags($pageNewName),
|
'htmlName' => escape_tags($pageNewName),
|
||||||
'urlName' => urlencode(escape_tags($pageNewName))
|
//'urlName' => urlencode(escape_tags($pageNewName))
|
||||||
|
'urlName' => Zlib\NativeWiki::name_encode($pageNewName)
|
||||||
];
|
];
|
||||||
|
|
||||||
return [ 'success' => true, 'page' => $page ];
|
return [ 'success' => true, 'page' => $page ];
|
||||||
@@ -365,7 +368,6 @@ class NativeWikiPage {
|
|||||||
|
|
||||||
unset($item['id']);
|
unset($item['id']);
|
||||||
unset($item['author']);
|
unset($item['author']);
|
||||||
|
|
||||||
$item['parent'] = 0;
|
$item['parent'] = 0;
|
||||||
$item['body'] = $content;
|
$item['body'] = $content;
|
||||||
$item['author_xchan'] = $observer_hash;
|
$item['author_xchan'] = $observer_hash;
|
||||||
@@ -527,7 +529,8 @@ class NativeWikiPage {
|
|||||||
$pages = $pageURLs = array();
|
$pages = $pageURLs = array();
|
||||||
foreach ($match[1] as $m) {
|
foreach ($match[1] as $m) {
|
||||||
// TODO: Why do we need to double urlencode for this to work?
|
// TODO: Why do we need to double urlencode for this to work?
|
||||||
$pageURLs[] = urlencode(urlencode(escape_tags($m)));
|
//$pageURLs[] = urlencode(urlencode(escape_tags($m)));
|
||||||
|
$pageURLs[] = Zlib\NativeWiki::name_encode(escape_tags($m));
|
||||||
$pages[] = $m;
|
$pages[] = $m;
|
||||||
}
|
}
|
||||||
$idx = 0;
|
$idx = 0;
|
||||||
@@ -556,7 +559,10 @@ class NativeWikiPage {
|
|||||||
'$pageHistory' => $pageHistory['history'],
|
'$pageHistory' => $pageHistory['history'],
|
||||||
'$permsWrite' => $arr['permsWrite'],
|
'$permsWrite' => $arr['permsWrite'],
|
||||||
'$name_lbl' => t('Name'),
|
'$name_lbl' => t('Name'),
|
||||||
'$msg_label' => t('Message','wiki_history')
|
'$msg_label' => t('Message','wiki_history'),
|
||||||
|
'$date_lbl' => t('Date'),
|
||||||
|
'$revert_btn' => t('Revert'),
|
||||||
|
'$compare_btn' => t('Compare')
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -613,7 +619,7 @@ class NativeWikiPage {
|
|||||||
$s = str_replace('[observer.webname]', '', $s);
|
$s = str_replace('[observer.webname]', '', $s);
|
||||||
$s = str_replace('[observer.photo]', '', $s);
|
$s = str_replace('[observer.photo]', '', $s);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $s;
|
return $s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+93
-16
@@ -57,6 +57,7 @@ class PConfig {
|
|||||||
\App::$config[$uid][$c]['config_loaded'] = true;
|
\App::$config[$uid][$c]['config_loaded'] = true;
|
||||||
}
|
}
|
||||||
\App::$config[$uid][$c][$k] = $rr['v'];
|
\App::$config[$uid][$c][$k] = $rr['v'];
|
||||||
|
\App::$config[$uid][$c]['pcfgud:'.$k] = $rr['updated'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,9 +112,11 @@ class PConfig {
|
|||||||
* The configuration key to set
|
* The configuration key to set
|
||||||
* @param string $value
|
* @param string $value
|
||||||
* The value to store
|
* The value to store
|
||||||
|
* @param string $updated (optional)
|
||||||
|
* The datetime to store
|
||||||
* @return mixed Stored $value or false
|
* @return mixed Stored $value or false
|
||||||
*/
|
*/
|
||||||
static public function Set($uid, $family, $key, $value) {
|
static public function Set($uid, $family, $key, $value, $updated = NULL) {
|
||||||
|
|
||||||
// this catches subtle errors where this function has been called
|
// this catches subtle errors where this function has been called
|
||||||
// with local_channel() when not logged in (which returns false)
|
// with local_channel() when not logged in (which returns false)
|
||||||
@@ -130,29 +133,79 @@ class PConfig {
|
|||||||
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
$dbvalue = ((is_array($value)) ? serialize($value) : $value);
|
||||||
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
$dbvalue = ((is_bool($dbvalue)) ? intval($dbvalue) : $dbvalue);
|
||||||
|
|
||||||
|
$now = datetime_convert();
|
||||||
|
if (! $updated) {
|
||||||
|
//Sometimes things happen fast... very fast.
|
||||||
|
//To make sure legitimate updates aren't rejected
|
||||||
|
//because not enough time has passed. We say our updates
|
||||||
|
//happened just a short time in the past rather than right now.
|
||||||
|
$updated = datetime_convert('UTC','UTC','-2 seconds');
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash = hash('sha256',$family.':'.$key);
|
||||||
|
|
||||||
|
if (self::Get($uid, 'hz_delpconfig', $hash) !== false) {
|
||||||
|
if (self::Get($uid, 'hz_delpconfig', $hash) > $now) {
|
||||||
|
logger('Refusing to update pconfig with outdated info (Item deleted more recently).', LOGGER_NORMAL, LOG_ERR);
|
||||||
|
return self::Get($uid,$family,$key);
|
||||||
|
} else {
|
||||||
|
self::Delete($uid,'hz_delpconfig',$hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(self::Get($uid, $family, $key) === false) {
|
if(self::Get($uid, $family, $key) === false) {
|
||||||
if(! array_key_exists($uid, \App::$config))
|
if(! array_key_exists($uid, \App::$config))
|
||||||
\App::$config[$uid] = array();
|
\App::$config[$uid] = array();
|
||||||
if(! array_key_exists($family, \App::$config[$uid]))
|
if(! array_key_exists($family, \App::$config[$uid]))
|
||||||
\App::$config[$uid][$family] = array();
|
\App::$config[$uid][$family] = array();
|
||||||
|
|
||||||
$ret = q("INSERT INTO pconfig ( uid, cat, k, v ) VALUES ( %d, '%s', '%s', '%s' ) ",
|
|
||||||
|
$ret = q("INSERT INTO pconfig ( uid, cat, k, v, updated ) VALUES ( %d, '%s', '%s', '%s', '%s' ) ",
|
||||||
intval($uid),
|
intval($uid),
|
||||||
dbesc($family),
|
dbesc($family),
|
||||||
dbesc($key),
|
dbesc($key),
|
||||||
dbesc($dbvalue)
|
dbesc($dbvalue),
|
||||||
|
dbesc($updated)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// There is a possible race condition if another process happens
|
||||||
|
// to insert something after this thread has Loaded and now. We should
|
||||||
|
// at least make a note of it if it happens.
|
||||||
|
|
||||||
|
if (!$ret) {
|
||||||
|
logger("Error: Insert to pconfig failed.",LOGGER_NORMAL, LOG_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
$new = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||||
|
|
||||||
$ret = q("UPDATE pconfig SET v = '%s' WHERE uid = %d and cat = '%s' AND k = '%s'",
|
if ($new) {
|
||||||
dbesc($dbvalue),
|
|
||||||
intval($uid),
|
// @NOTE There is still a possible race condition under limited circumstances
|
||||||
dbesc($family),
|
// where a value will be updated by another thread with more current data than
|
||||||
dbesc($key)
|
// we have. At this point there is no easy way to test for it, so we update
|
||||||
);
|
// and hope for the best.
|
||||||
|
|
||||||
|
$ret = q("UPDATE pconfig SET v = '%s', updated = '%s' WHERE uid = %d and cat = '%s' AND k = '%s' ",
|
||||||
|
dbesc($dbvalue),
|
||||||
|
dbesc($updated),
|
||||||
|
intval($uid),
|
||||||
|
dbesc($family),
|
||||||
|
dbesc($key)
|
||||||
|
);
|
||||||
|
|
||||||
|
\App::$config[$uid][$family]['pcfgud:'.$key] = $updated;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
logger('Refusing to update pconfig with outdated info.', LOGGER_NORMAL, LOG_ERR);
|
||||||
|
return self::Get($uid, $family, $key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// keep a separate copy for all variables which were
|
// keep a separate copy for all variables which were
|
||||||
// set in the life of this page. We need this to
|
// set in the life of this page. We need this to
|
||||||
// synchronise channel clones.
|
// synchronise channel clones.
|
||||||
@@ -163,7 +216,11 @@ class PConfig {
|
|||||||
\App::$config[$uid]['transient'][$family] = array();
|
\App::$config[$uid]['transient'][$family] = array();
|
||||||
|
|
||||||
\App::$config[$uid][$family][$key] = $value;
|
\App::$config[$uid][$family][$key] = $value;
|
||||||
\App::$config[$uid]['transient'][$family][$key] = $value;
|
|
||||||
|
if ($new) {
|
||||||
|
\App::$config[$uid]['transient'][$family][$key] = $value;
|
||||||
|
\App::$config[$uid]['transient'][$family]['pcfgud:'.$key] = $updated;
|
||||||
|
}
|
||||||
|
|
||||||
if($ret)
|
if($ret)
|
||||||
return $value;
|
return $value;
|
||||||
@@ -184,20 +241,33 @@ class PConfig {
|
|||||||
* The category of the configuration value
|
* The category of the configuration value
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* The configuration key to delete
|
* The configuration key to delete
|
||||||
* @return mixed
|
* @param string $updated (optional)
|
||||||
|
* The datetime to store
|
||||||
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
static public function Delete($uid, $family, $key) {
|
static public function Delete($uid, $family, $key, $updated = NULL) {
|
||||||
|
|
||||||
if(is_null($uid) || $uid === false)
|
if(is_null($uid) || $uid === false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
$updated = ($updated) ? $updated : datetime_convert('UTC','UTC','-2 seconds');
|
||||||
|
$now = datetime_convert();
|
||||||
|
$newer = (\App::$config[$uid][$family]['pcfgud:'.$key] < $now);
|
||||||
|
|
||||||
|
if (! $newer) {
|
||||||
|
logger('Refusing to delete pconfig with outdated delete request.', LOGGER_NORMAL, LOG_ERR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$ret = false;
|
$ret = false;
|
||||||
|
|
||||||
if(array_key_exists($uid,\App::$config)
|
if (isset(\App::$config[$uid][$family][$key])) {
|
||||||
&& is_array(\App::$config['uid'])
|
|
||||||
&& array_key_exists($family,\App::$config['uid'])
|
|
||||||
&& array_key_exists($key, \App::$config[$uid][$family]))
|
|
||||||
unset(\App::$config[$uid][$family][$key]);
|
unset(\App::$config[$uid][$family][$key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset(\App::$config[$uid][$family]['pcfgud:'.$key])) {
|
||||||
|
unset(\App::$config[$uid][$family]['pcfgud:'.$key]);
|
||||||
|
}
|
||||||
|
|
||||||
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
$ret = q("DELETE FROM pconfig WHERE uid = %d AND cat = '%s' AND k = '%s'",
|
||||||
intval($uid),
|
intval($uid),
|
||||||
@@ -205,6 +275,13 @@ class PConfig {
|
|||||||
dbesc($key)
|
dbesc($key)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Synchronize delete with clones.
|
||||||
|
|
||||||
|
if ($family != 'hz_delpconfig') {
|
||||||
|
$hash = hash('sha256',$family.':'.$key);
|
||||||
|
set_pconfig($uid,'hz_delpconfig',$hash,$updated);
|
||||||
|
}
|
||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,278 @@
|
|||||||
|
<?php /** @file */
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Libzot;
|
||||||
|
|
||||||
|
|
||||||
|
class Queue {
|
||||||
|
|
||||||
|
static function update($id, $add_priority = 0) {
|
||||||
|
|
||||||
|
logger('queue: requeue item ' . $id,LOGGER_DEBUG);
|
||||||
|
$x = q("select outq_created, outq_posturl from outq where outq_hash = '%s' limit 1",
|
||||||
|
dbesc($id)
|
||||||
|
);
|
||||||
|
if(! $x)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
$y = q("select min(outq_created) as earliest from outq where outq_posturl = '%s'",
|
||||||
|
dbesc($x[0]['outq_posturl'])
|
||||||
|
);
|
||||||
|
|
||||||
|
// look for the oldest queue entry with this destination URL. If it's older than a couple of days,
|
||||||
|
// the destination is considered to be down and only scheduled once an hour, regardless of the
|
||||||
|
// age of the current queue item.
|
||||||
|
|
||||||
|
$might_be_down = false;
|
||||||
|
|
||||||
|
if($y)
|
||||||
|
$might_be_down = ((datetime_convert('UTC','UTC',$y[0]['earliest']) < datetime_convert('UTC','UTC','now - 2 days')) ? true : false);
|
||||||
|
|
||||||
|
|
||||||
|
// Set all other records for this destination way into the future.
|
||||||
|
// The queue delivers by destination. We'll keep one queue item for
|
||||||
|
// this destination (this one) with a shorter delivery. If we succeed
|
||||||
|
// once, we'll try to deliver everything for that destination.
|
||||||
|
// The delivery will be set to at most once per hour, and if the
|
||||||
|
// queue item is less than 12 hours old, we'll schedule for fifteen
|
||||||
|
// minutes.
|
||||||
|
|
||||||
|
$r = q("UPDATE outq SET outq_scheduled = '%s' WHERE outq_posturl = '%s'",
|
||||||
|
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
|
||||||
|
dbesc($x[0]['outq_posturl'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$since = datetime_convert('UTC','UTC',$x[0]['outq_created']);
|
||||||
|
|
||||||
|
if(($might_be_down) || ($since < datetime_convert('UTC','UTC','now - 12 hour'))) {
|
||||||
|
$next = datetime_convert('UTC','UTC','now + 1 hour');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$next = datetime_convert('UTC','UTC','now + ' . intval($add_priority) . ' minutes');
|
||||||
|
}
|
||||||
|
|
||||||
|
q("UPDATE outq SET outq_updated = '%s',
|
||||||
|
outq_priority = outq_priority + %d,
|
||||||
|
outq_scheduled = '%s'
|
||||||
|
WHERE outq_hash = '%s'",
|
||||||
|
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
intval($add_priority),
|
||||||
|
dbesc($next),
|
||||||
|
dbesc($id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function remove($id,$channel_id = 0) {
|
||||||
|
logger('queue: remove queue item ' . $id,LOGGER_DEBUG);
|
||||||
|
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||||
|
|
||||||
|
q("DELETE FROM outq WHERE outq_hash = '%s' $sql_extra",
|
||||||
|
dbesc($id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static function remove_by_posturl($posturl) {
|
||||||
|
logger('queue: remove queue posturl ' . $posturl,LOGGER_DEBUG);
|
||||||
|
|
||||||
|
q("DELETE FROM outq WHERE outq_posturl = '%s' ",
|
||||||
|
dbesc($posturl)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static function set_delivered($id,$channel = 0) {
|
||||||
|
logger('queue: set delivered ' . $id,LOGGER_DEBUG);
|
||||||
|
$sql_extra = (($channel_id) ? " and outq_channel = " . intval($channel_id) . " " : '');
|
||||||
|
|
||||||
|
// Set the next scheduled run date so far in the future that it will be expired
|
||||||
|
// long before it ever makes it back into the delivery chain.
|
||||||
|
|
||||||
|
q("update outq set outq_delivered = 1, outq_updated = '%s', outq_scheduled = '%s' where outq_hash = '%s' $sql_extra ",
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc(datetime_convert('UTC','UTC','now + 5 days')),
|
||||||
|
dbesc($id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static function insert($arr) {
|
||||||
|
|
||||||
|
// do not queue anything with no destination
|
||||||
|
|
||||||
|
if(! (array_key_exists('posturl',$arr) && trim($arr['posturl']))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$x = q("insert into outq ( outq_hash, outq_account, outq_channel, outq_driver, outq_posturl, outq_async, outq_priority,
|
||||||
|
outq_created, outq_updated, outq_scheduled, outq_notify, outq_msg )
|
||||||
|
values ( '%s', %d, %d, '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s' )",
|
||||||
|
dbesc($arr['hash']),
|
||||||
|
intval($arr['account_id']),
|
||||||
|
intval($arr['channel_id']),
|
||||||
|
dbesc(($arr['driver']) ? $arr['driver'] : 'zot'),
|
||||||
|
dbesc($arr['posturl']),
|
||||||
|
intval(1),
|
||||||
|
intval(($arr['priority']) ? $arr['priority'] : 0),
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc($arr['notify']),
|
||||||
|
dbesc(($arr['msg']) ? $arr['msg'] : '')
|
||||||
|
);
|
||||||
|
return $x;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static function deliver($outq, $immediate = false) {
|
||||||
|
|
||||||
|
$base = null;
|
||||||
|
$h = parse_url($outq['outq_posturl']);
|
||||||
|
if($h !== false)
|
||||||
|
$base = $h['scheme'] . '://' . $h['host'] . (($h['port']) ? ':' . $h['port'] : '');
|
||||||
|
|
||||||
|
if(($base) && ($base !== z_root()) && ($immediate)) {
|
||||||
|
$y = q("select site_update, site_dead from site where site_url = '%s' ",
|
||||||
|
dbesc($base)
|
||||||
|
);
|
||||||
|
if($y) {
|
||||||
|
if(intval($y[0]['site_dead'])) {
|
||||||
|
self::remove_by_posturl($outq['outq_posturl']);
|
||||||
|
logger('dead site ignored ' . $base);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if($y[0]['site_update'] < datetime_convert('UTC','UTC','now - 1 month')) {
|
||||||
|
self::update($outq['outq_hash'],10);
|
||||||
|
logger('immediate delivery deferred for site ' . $base);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
site_store_lowlevel(
|
||||||
|
[
|
||||||
|
'site_url' => $base,
|
||||||
|
'site_update' => datetime_convert(),
|
||||||
|
'site_dead' => 0,
|
||||||
|
'site_type' => intval(($outq['outq_driver'] === 'post') ? SITE_TYPE_NOTZOT : SITE_TYPE_UNKNOWN),
|
||||||
|
'site_crypto' => ''
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$arr = array('outq' => $outq, 'base' => $base, 'handled' => false, 'immediate' => $immediate);
|
||||||
|
call_hooks('queue_deliver',$arr);
|
||||||
|
if($arr['handled'])
|
||||||
|
return;
|
||||||
|
|
||||||
|
// "post" queue driver - used for diaspora and friendica-over-diaspora communications.
|
||||||
|
|
||||||
|
if($outq['outq_driver'] === 'post') {
|
||||||
|
$result = z_post_url($outq['outq_posturl'],$outq['outq_msg']);
|
||||||
|
if($result['success'] && $result['return_code'] < 300) {
|
||||||
|
logger('deliver: queue post success to ' . $outq['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'",
|
||||||
|
dbesc('accepted for delivery'),
|
||||||
|
dbesc(datetime_convert()),
|
||||||
|
dbesc($outq['outq_hash'])
|
||||||
|
);
|
||||||
|
self::remove($outq['outq_hash']);
|
||||||
|
|
||||||
|
// server is responding - see if anything else is going to this destination and is piled up
|
||||||
|
// and try to send some more. We're relying on the fact that do_delivery() results in an
|
||||||
|
// immediate delivery otherwise we could get into a queue loop.
|
||||||
|
|
||||||
|
if(! $immediate) {
|
||||||
|
$x = q("select outq_hash from outq where outq_posturl = '%s' and outq_delivered = 0",
|
||||||
|
dbesc($outq['outq_posturl'])
|
||||||
|
);
|
||||||
|
|
||||||
|
$piled_up = array();
|
||||||
|
if($x) {
|
||||||
|
foreach($x as $xx) {
|
||||||
|
$piled_up[] = $xx['outq_hash'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if($piled_up) {
|
||||||
|
// call do_delivery() with the force flag
|
||||||
|
do_delivery($piled_up, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger('deliver: queue post returned ' . $result['return_code']
|
||||||
|
. ' from ' . $outq['outq_posturl'],LOGGER_DEBUG);
|
||||||
|
self::update($outq['outq_hash'],10);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// normal zot delivery
|
||||||
|
|
||||||
|
logger('deliver: dest: ' . $outq['outq_posturl'], LOGGER_DEBUG);
|
||||||
|
|
||||||
|
|
||||||
|
if($outq['outq_posturl'] === z_root() . '/zot') {
|
||||||
|
// local delivery
|
||||||
|
$zot = new \Zotlabs\Zot6\Receiver(new \Zotlabs\Zot6\Zot6Handler(),$outq['outq_notify']);
|
||||||
|
$result = $zot->run(true);
|
||||||
|
logger('returned_json: ' . json_encode($result,JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES), LOGGER_DATA);
|
||||||
|
logger('deliver: local zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||||
|
Libzot::process_response($outq['outq_posturl'],[ 'success' => true, 'body' => json_encode($result) ], $outq);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger('remote');
|
||||||
|
$channel = null;
|
||||||
|
|
||||||
|
if($outq['outq_channel']) {
|
||||||
|
$channel = channelx_by_n($outq['outq_channel']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$host_crypto = null;
|
||||||
|
|
||||||
|
if($channel && $base) {
|
||||||
|
$h = q("select hubloc_sitekey, site_crypto from hubloc left join site on hubloc_url = site_url where site_url = '%s' and hubloc_sitekey != '' order by hubloc_id desc limit 1",
|
||||||
|
dbesc($base)
|
||||||
|
);
|
||||||
|
if($h) {
|
||||||
|
$host_crypto = $h[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = $outq['outq_notify'];
|
||||||
|
|
||||||
|
$result = Libzot::zot($outq['outq_posturl'],$msg,$channel,$host_crypto);
|
||||||
|
|
||||||
|
if($result['success']) {
|
||||||
|
logger('deliver: remote zot delivery succeeded to ' . $outq['outq_posturl']);
|
||||||
|
Libzot::process_response($outq['outq_posturl'],$result, $outq);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logger('deliver: remote zot delivery failed to ' . $outq['outq_posturl']);
|
||||||
|
logger('deliver: remote zot delivery fail data: ' . print_r($result,true), LOGGER_DATA);
|
||||||
|
self::update($outq['outq_hash'],10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -54,6 +54,7 @@ class Share {
|
|||||||
if(! $this->item)
|
if(! $this->item)
|
||||||
return $obj;
|
return $obj;
|
||||||
|
|
||||||
|
$obj['asld'] = $this->item['mid'];
|
||||||
$obj['type'] = $this->item['obj_type'];
|
$obj['type'] = $this->item['obj_type'];
|
||||||
$obj['id'] = $this->item['mid'];
|
$obj['id'] = $this->item['mid'];
|
||||||
$obj['content'] = $this->item['body'];
|
$obj['content'] = $this->item['body'];
|
||||||
|
|||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
use DomDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SVGSantiizer
|
||||||
|
*
|
||||||
|
* Whitelist-based PHP SVG sanitizer.
|
||||||
|
*
|
||||||
|
* @link https://github.com/alister-/SVG-Sanitizer}
|
||||||
|
* @author Alister Norris
|
||||||
|
* @copyright Copyright (c) 2013 Alister Norris
|
||||||
|
* @license http://opensource.org/licenses/mit-license.php The MIT License
|
||||||
|
* @package svgsanitizer
|
||||||
|
*/
|
||||||
|
|
||||||
|
class SvgSanitizer {
|
||||||
|
|
||||||
|
private $xmlDoc; // PHP XML DOMDocument
|
||||||
|
|
||||||
|
private $removedattrs = [];
|
||||||
|
|
||||||
|
private static $allowed_functions = [ 'matrix', 'url', 'translate', 'rgb' ];
|
||||||
|
|
||||||
|
// defines the whitelist of elements and attributes allowed.
|
||||||
|
private static $whitelist = [
|
||||||
|
'a' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'href', 'xlink:href', 'xlink:title' ],
|
||||||
|
'circle' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'r', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||||
|
'clipPath' => [ 'class', 'clipPathUnits', 'id' ],
|
||||||
|
'defs' => [ ],
|
||||||
|
'style' => [ 'type' ],
|
||||||
|
'desc' => [ ],
|
||||||
|
'ellipse' => [ 'class', 'clip-path', 'clip-rule', 'cx', 'cy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||||
|
'feGaussianBlur' => [ 'class', 'color-interpolation-filters', 'id', 'requiredFeatures', 'stdDeviation' ],
|
||||||
|
'filter' => [ 'class', 'color-interpolation-filters', 'filterRes', 'filterUnits', 'height', 'id', 'primitiveUnits', 'requiredFeatures', 'width', 'x', 'xlink:href', 'y' ],
|
||||||
|
'foreignObject' => [ 'class', 'font-size', 'height', 'id', 'opacity', 'requiredFeatures', 'style', 'transform', 'width', 'x', 'y' ],
|
||||||
|
'g' => [ 'class', 'clip-path', 'clip-rule', 'id', 'display', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'font-family', 'font-size', 'font-style', 'font-weight', 'text-anchor' ],
|
||||||
|
'image' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'style', 'systemLanguage', 'transform', 'width', 'x', 'xlink:href', 'xlink:title', 'y' ],
|
||||||
|
'line' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'x1', 'x2', 'y1', 'y2' ],
|
||||||
|
'linearGradient' => [ 'class', 'id', 'gradientTransform', 'gradientUnits', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'x1', 'x2', 'xlink:href', 'y1', 'y2' ],
|
||||||
|
'marker' => [ 'id', 'class', 'markerHeight', 'markerUnits', 'markerWidth', 'orient', 'preserveAspectRatio', 'refX', 'refY', 'systemLanguage', 'viewBox' ],
|
||||||
|
'mask' => [ 'class', 'height', 'id', 'maskContentUnits', 'maskUnits', 'width', 'x', 'y' ],
|
||||||
|
'metadata' => [ 'class', 'id' ],
|
||||||
|
'path' => [ 'class', 'clip-path', 'clip-rule', 'd', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||||
|
'pattern' => [ 'class', 'height', 'id', 'patternContentUnits', 'patternTransform', 'patternUnits', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xlink:href', 'y' ],
|
||||||
|
'polygon' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'id', 'class', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||||
|
'polyline' => [ 'class', 'clip-path', 'clip-rule', 'id', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'opacity', 'points', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform' ],
|
||||||
|
'radialGradient' => [ 'class', 'cx', 'cy', 'fx', 'fy', 'gradientTransform', 'gradientUnits', 'id', 'r', 'requiredFeatures', 'spreadMethod', 'systemLanguage', 'xlink:href' ],
|
||||||
|
'rect' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'opacity', 'requiredFeatures', 'rx', 'ry', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'width', 'x', 'y' ],
|
||||||
|
'stop' => [ 'class', 'id', 'offset', 'requiredFeatures', 'stop-color', 'stop-opacity', 'style', 'systemLanguage' ],
|
||||||
|
'svg' => [ 'class', 'clip-path', 'clip-rule', 'filter', 'id', 'height', 'mask', 'preserveAspectRatio', 'requiredFeatures', 'style', 'systemLanguage', 'viewBox', 'width', 'x', 'xmlns', 'xmlns:se', 'xmlns:xlink', 'y' ],
|
||||||
|
'switch' => [ 'class', 'id', 'requiredFeatures', 'systemLanguage' ],
|
||||||
|
'symbol' => [ 'class', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'opacity', 'preserveAspectRatio', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'transform', 'viewBox' ],
|
||||||
|
'text' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'transform', 'x', 'xml:space', 'y' ],
|
||||||
|
'textPath' => [ 'class', 'id', 'method', 'requiredFeatures', 'spacing', 'startOffset', 'style', 'systemLanguage', 'transform', 'xlink:href' ],
|
||||||
|
'title' => [ ],
|
||||||
|
'tspan' => [ 'class', 'clip-path', 'clip-rule', 'dx', 'dy', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'font-family', 'font-size', 'font-style', 'font-weight', 'id', 'mask', 'opacity', 'requiredFeatures', 'rotate', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'systemLanguage', 'text-anchor', 'textLength', 'transform', 'x', 'xml:space', 'y' ],
|
||||||
|
'use' => [ 'class', 'clip-path', 'clip-rule', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'height', 'id', 'mask', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'style', 'transform', 'width', 'x', 'xlink:href', 'y' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->xmlDoc = new DOMDocument('1.0','UTF-8');
|
||||||
|
$this->xmlDoc->preserveWhiteSpace = false;
|
||||||
|
libxml_use_internal_errors(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load XML SVG
|
||||||
|
function load($file) {
|
||||||
|
$this->xmlDoc->load($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadXML($str) {
|
||||||
|
if (! $this->xmlDoc->loadXML($str)) {
|
||||||
|
logger('loadxml: ' . print_r(libxml_get_errors(),true), LOGGER_DEBUG);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sanitize()
|
||||||
|
{
|
||||||
|
// all elements in xml doc
|
||||||
|
$allElements = $this->xmlDoc->getElementsByTagName('*');
|
||||||
|
|
||||||
|
// loop through all elements
|
||||||
|
for($i = 0; $i < $allElements->length; $i++)
|
||||||
|
{
|
||||||
|
$this->removedattrs = [];
|
||||||
|
|
||||||
|
$currentNode = $allElements->item($i);
|
||||||
|
|
||||||
|
// logger('current_node: ' . print_r($currentNode,true));
|
||||||
|
|
||||||
|
// array of allowed attributes in specific element
|
||||||
|
$whitelist_attr_arr = self::$whitelist[$currentNode->tagName];
|
||||||
|
|
||||||
|
// does element exist in whitelist?
|
||||||
|
if(isset($whitelist_attr_arr)) {
|
||||||
|
$total = $currentNode->attributes->length;
|
||||||
|
|
||||||
|
for($x = 0; $x < $total; $x++) {
|
||||||
|
|
||||||
|
// get attributes name
|
||||||
|
$attrName = $currentNode->attributes->item($x)->nodeName;
|
||||||
|
|
||||||
|
// logger('checking: ' . print_r($currentNode->attributes->item($x),true));
|
||||||
|
$matches = false;
|
||||||
|
|
||||||
|
// check if attribute isn't in whitelist
|
||||||
|
if(! in_array($attrName, $whitelist_attr_arr)) {
|
||||||
|
$this->removedattrs[] = $attrName;
|
||||||
|
}
|
||||||
|
// check for disallowed functions
|
||||||
|
elseif (preg_match_all('/([a-zA-Z0-9]+)[\s]*\(/',
|
||||||
|
$currentNode->attributes->item($x)->textContent,$matches,PREG_SET_ORDER)) {
|
||||||
|
if ($attrName === 'text') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
if(! in_array($match[1],self::$allowed_functions)) {
|
||||||
|
logger('queue_remove_function: ' . $match[1],LOGGER_DEBUG);
|
||||||
|
$this->removedattrs[] = $attrName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($this->removedattrs) {
|
||||||
|
foreach ($this->removedattrs as $attr) {
|
||||||
|
$currentNode->removeAttribute($attr);
|
||||||
|
logger('removed: ' . $attr, LOGGER_DEBUG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// else remove element
|
||||||
|
else {
|
||||||
|
logger('remove_node: ' . print_r($currentNode,true));
|
||||||
|
$currentNode->parentNode->removeChild($currentNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSVG() {
|
||||||
|
$this->xmlDoc->formatOutput = true;
|
||||||
|
return($this->xmlDoc->saveXML());
|
||||||
|
}
|
||||||
|
}
|
||||||
+63
-28
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Lib;
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
|
||||||
require_once('include/text.php');
|
require_once('include/text.php');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,6 +38,9 @@ class ThreadItem {
|
|||||||
|
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
|
$this->toplevel = ($this->get_id() == $this->get_data_value('parent'));
|
||||||
|
$this->threaded = get_config('system','thread_allow');
|
||||||
|
|
||||||
|
$observer = \App::get_observer();
|
||||||
|
|
||||||
// Prepare the children
|
// Prepare the children
|
||||||
if($data['children']) {
|
if($data['children']) {
|
||||||
@@ -49,6 +54,7 @@ class ThreadItem {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$child = new ThreadItem($item);
|
$child = new ThreadItem($item);
|
||||||
$this->add_child($child);
|
$this->add_child($child);
|
||||||
}
|
}
|
||||||
@@ -71,7 +77,7 @@ class ThreadItem {
|
|||||||
* _ false on failure
|
* _ false on failure
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public function get_template_data($conv_responses, $thread_level=1) {
|
public function get_template_data($conv_responses, $thread_level=1, $conv_flags = []) {
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
|
|
||||||
@@ -92,10 +98,11 @@ class ThreadItem {
|
|||||||
$conv = $this->get_conversation();
|
$conv = $this->get_conversation();
|
||||||
$observer = $conv->get_observer();
|
$observer = $conv->get_observer();
|
||||||
|
|
||||||
$lock = ((($item['item_private'] == 1) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
$lock = (((intval($item['item_private'])) || (($item['uid'] == local_channel()) && (strlen($item['allow_cid']) || strlen($item['allow_gid'])
|
||||||
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
|
|| strlen($item['deny_cid']) || strlen($item['deny_gid']))))
|
||||||
? t('Private Message')
|
? t('Private Message')
|
||||||
: false);
|
: false);
|
||||||
|
|
||||||
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
$shareable = ((($conv->get_profile_owner() == local_channel() && local_channel()) && ($item['item_private'] != 1)) ? true : false);
|
||||||
|
|
||||||
// allow an exemption for sharing stuff from your private feeds
|
// allow an exemption for sharing stuff from your private feeds
|
||||||
@@ -103,13 +110,26 @@ class ThreadItem {
|
|||||||
$shareable = true;
|
$shareable = true;
|
||||||
|
|
||||||
$privacy_warning = false;
|
$privacy_warning = false;
|
||||||
if(($item['item_private'] == 1) && ($item['owner']['xchan_network'] === 'activitypub')) {
|
if(intval($item['item_private']) && ($item['owner']['xchan_network'] === 'activitypub')) {
|
||||||
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
|
$recips = get_iconfig($item['parent'], 'activitypub', 'recips');
|
||||||
|
|
||||||
if(! in_array($observer['xchan_url'], $recips['to']))
|
if(! in_array($observer['xchan_url'], $recips['to']))
|
||||||
$privacy_warning = true;
|
$privacy_warning = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($lock) {
|
||||||
|
if (($item['mid'] == $item['parent_mid']) && count(get_terms_oftype($item['term'],TERM_FORUM))) {
|
||||||
|
$privacy_warning = true;
|
||||||
|
$conv_flags['parent_privacy_warning'] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$privacy_warning = (isset($conv_flags['parent_privacy_warning'])) ? $conv_flags['parent_privacy_warning'] : $privacy_warning;
|
||||||
|
|
||||||
|
if ($lock && $privacy_warning) {
|
||||||
|
$lock = t('Privacy conflict. Discretion advised.');
|
||||||
|
}
|
||||||
|
|
||||||
$mode = $conv->get_mode();
|
$mode = $conv->get_mode();
|
||||||
|
|
||||||
switch($item['item_type']) {
|
switch($item['item_type']) {
|
||||||
@@ -259,7 +279,7 @@ class ThreadItem {
|
|||||||
$forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
|
$forged = ((($item['sig']) && (! intval($item['item_verified']))) ? t('Message signature incorrect') : '');
|
||||||
$unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
|
$unverified = '' ; // (($this->is_wall_to_wall() && (! intval($item['item_verified']))) ? t('Message cannot be verified') : '');
|
||||||
|
|
||||||
|
$settings = '';
|
||||||
|
|
||||||
// FIXME - check this permission
|
// FIXME - check this permission
|
||||||
if($conv->get_profile_owner() == local_channel()) {
|
if($conv->get_profile_owner() == local_channel()) {
|
||||||
@@ -267,12 +287,14 @@ class ThreadItem {
|
|||||||
'tagit' => t("Add Tag"),
|
'tagit' => t("Add Tag"),
|
||||||
'classtagger' => "",
|
'classtagger' => "",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$settings = t('Conversation Tools');
|
||||||
}
|
}
|
||||||
|
|
||||||
$has_bookmarks = false;
|
$has_bookmarks = false;
|
||||||
if(is_array($item['term'])) {
|
if(Apps::system_app_installed(local_channel(), 'Bookmarks') && is_array($item['term'])) {
|
||||||
foreach($item['term'] as $t) {
|
foreach($item['term'] as $t) {
|
||||||
if((get_account_techlevel() > 0) && ($t['ttype'] == TERM_BOOKMARK))
|
if(($t['ttype'] == TERM_BOOKMARK))
|
||||||
$has_bookmarks = true;
|
$has_bookmarks = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -284,10 +306,18 @@ class ThreadItem {
|
|||||||
if($this->is_commentable() && $observer) {
|
if($this->is_commentable() && $observer) {
|
||||||
$like = array( t("I like this \x28toggle\x29"), t("like"));
|
$like = array( t("I like this \x28toggle\x29"), t("like"));
|
||||||
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
|
$dislike = array( t("I don't like this \x28toggle\x29"), t("dislike"));
|
||||||
|
$reply_to = array( t("Reply on this comment"), t("reply"), t("Reply to"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($shareable)
|
if ($shareable) {
|
||||||
$share = array( t('Share This'), t('share'));
|
// This actually turns out not to be possible in some protocol stacks without opening up hundreds of new issues.
|
||||||
|
// Will allow it only for uri resolvable sources.
|
||||||
|
if(strpos($item['mid'],'http') === 0) {
|
||||||
|
$share = []; //Not yet ready for primetime
|
||||||
|
//$share = array( t('Repeat This'), t('repeat'));
|
||||||
|
}
|
||||||
|
$embed = array( t('Share This'), t('share'));
|
||||||
|
}
|
||||||
|
|
||||||
$dreport = '';
|
$dreport = '';
|
||||||
|
|
||||||
@@ -295,13 +325,14 @@ class ThreadItem {
|
|||||||
if($keep_reports === 0)
|
if($keep_reports === 0)
|
||||||
$keep_reports = 10;
|
$keep_reports = 10;
|
||||||
|
|
||||||
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0)
|
if((! get_config('system','disable_dreport')) && strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC',"now - $keep_reports days")) > 0) {
|
||||||
$dreport = t('Delivery Report');
|
$dreport = t('Delivery Report');
|
||||||
|
$dreport_link = gen_link_id($item['mid']);
|
||||||
|
}
|
||||||
|
|
||||||
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
if(strcmp(datetime_convert('UTC','UTC',$item['created']),datetime_convert('UTC','UTC','now - 12 hours')) > 0)
|
||||||
$is_new = true;
|
$is_new = true;
|
||||||
|
|
||||||
|
|
||||||
localize_item($item);
|
localize_item($item);
|
||||||
|
|
||||||
$body = prepare_body($item,true);
|
$body = prepare_body($item,true);
|
||||||
@@ -312,19 +343,19 @@ class ThreadItem {
|
|||||||
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
|
$owner_address = substr($item['owner']['xchan_addr'],0,strpos($item['owner']['xchan_addr'],'@'));
|
||||||
$viewthread = $item['llink'];
|
$viewthread = $item['llink'];
|
||||||
if($conv->get_mode() === 'channel')
|
if($conv->get_mode() === 'channel')
|
||||||
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode($item['mid']);
|
$viewthread = z_root() . '/channel/' . $owner_address . '?f=&mid=' . urlencode(gen_link_id($item['mid']));
|
||||||
|
|
||||||
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
|
$comment_count_txt = sprintf( tt('%d comment','%d comments',$total_children),$total_children );
|
||||||
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
|
$list_unseen_txt = (($unseen_comments) ? sprintf('%d unseen',$unseen_comments) : '');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$children = $this->get_children();
|
$children = $this->get_children();
|
||||||
|
|
||||||
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
|
$has_tags = (($body['tags'] || $body['categories'] || $body['mentions'] || $body['attachments'] || $body['folders']) ? true : false);
|
||||||
|
|
||||||
|
$dropdown_extras_arr = [ 'item' => $item , 'dropdown_extras' => '' ];
|
||||||
|
call_hooks('dropdown_extras',$dropdown_extras_arr);
|
||||||
|
$dropdown_extras = $dropdown_extras_arr['dropdown_extras'];
|
||||||
|
|
||||||
$tmp_item = array(
|
$tmp_item = array(
|
||||||
'template' => $this->get_template(),
|
'template' => $this->get_template(),
|
||||||
'mode' => $mode,
|
'mode' => $mode,
|
||||||
@@ -339,13 +370,15 @@ class ThreadItem {
|
|||||||
'text' => strip_tags($body['html']),
|
'text' => strip_tags($body['html']),
|
||||||
'id' => $this->get_id(),
|
'id' => $this->get_id(),
|
||||||
'mid' => $item['mid'],
|
'mid' => $item['mid'],
|
||||||
|
'parent' => $item['parent'],
|
||||||
|
'author_id' => (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url']),
|
||||||
'isevent' => $isevent,
|
'isevent' => $isevent,
|
||||||
'attend' => $attend,
|
'attend' => $attend,
|
||||||
'consensus' => $consensus,
|
'consensus' => $consensus,
|
||||||
'conlabels' => $conlabels,
|
'conlabels' => $conlabels,
|
||||||
'canvote' => $canvote,
|
'canvote' => $canvote,
|
||||||
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, $item['author']['xchan_addr']),
|
'linktitle' => sprintf( t('View %s\'s profile - %s'), $profile_name, (($item['author']['xchan_addr']) ? $item['author']['xchan_addr'] : $item['author']['xchan_url'])),
|
||||||
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), $item['owner']['xchan_addr']),
|
'olinktitle' => sprintf( t('View %s\'s profile - %s'), $this->get_owner_name(), (($item['owner']['xchan_addr']) ? $item['owner']['xchan_addr'] : $item['owner']['xchan_url'])),
|
||||||
'llink' => $item['llink'],
|
'llink' => $item['llink'],
|
||||||
'viewthread' => $viewthread,
|
'viewthread' => $viewthread,
|
||||||
'to' => t('to'),
|
'to' => t('to'),
|
||||||
@@ -356,6 +389,7 @@ class ThreadItem {
|
|||||||
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
|
'thread_action_menu' => thread_action_menu($item,$conv->get_mode()),
|
||||||
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
|
'thread_author_menu' => thread_author_menu($item,$conv->get_mode()),
|
||||||
'dreport' => $dreport,
|
'dreport' => $dreport,
|
||||||
|
'dreport_link' => $dreport_link,
|
||||||
'name' => $profile_name,
|
'name' => $profile_name,
|
||||||
'thumb' => $profile_avatar,
|
'thumb' => $profile_avatar,
|
||||||
'osparkle' => $osparkle,
|
'osparkle' => $osparkle,
|
||||||
@@ -390,22 +424,25 @@ class ThreadItem {
|
|||||||
'has_tags' => $has_tags,
|
'has_tags' => $has_tags,
|
||||||
'reactions' => $this->reactions,
|
'reactions' => $this->reactions,
|
||||||
// Item toolbar buttons
|
// Item toolbar buttons
|
||||||
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
'emojis' => (($this->is_toplevel() && $this->is_commentable() && $observer && feature_enabled($conv->get_profile_owner(),'emojis')) ? '1' : ''),
|
||||||
'like' => $like,
|
'like' => $like,
|
||||||
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
|
'dislike' => ((feature_enabled($conv->get_profile_owner(),'dislike')) ? $dislike : ''),
|
||||||
|
'reply_to' => (((! $this->is_toplevel()) && feature_enabled($conv->get_profile_owner(),'reply_to')) ? $reply_to : ''),
|
||||||
|
'top_hint' => t("Go to previous comment"),
|
||||||
'share' => $share,
|
'share' => $share,
|
||||||
|
'embed' => $embed,
|
||||||
'rawmid' => $item['mid'],
|
'rawmid' => $item['mid'],
|
||||||
'plink' => get_plink($item),
|
'plink' => get_plink($item),
|
||||||
'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
|
'edpost' => $edpost, // ((feature_enabled($conv->get_profile_owner(),'edit_posts')) ? $edpost : ''),
|
||||||
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts')) ? $star : ''),
|
'star' => ((feature_enabled($conv->get_profile_owner(),'star_posts') && ($item['item_type'] == ITEM_TYPE_POST)) ? $star : ''),
|
||||||
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
|
'tagger' => ((feature_enabled($conv->get_profile_owner(),'commtag')) ? $tagger : ''),
|
||||||
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing')) ? $filer : ''),
|
'filer' => ((feature_enabled($conv->get_profile_owner(),'filing') && ($item['item_type'] == ITEM_TYPE_POST)) ? $filer : ''),
|
||||||
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
|
'bookmark' => (($conv->get_profile_owner() == local_channel() && local_channel() && $has_bookmarks) ? t('Save Bookmarks') : ''),
|
||||||
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
|
'addtocal' => (($has_event) ? t('Add to Calendar') : ''),
|
||||||
'drop' => $drop,
|
'drop' => $drop,
|
||||||
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
|
'multidrop' => ((feature_enabled($conv->get_profile_owner(),'multi_delete')) ? $multidrop : ''),
|
||||||
|
'dropdown_extras' => $dropdown_extras,
|
||||||
// end toolbar buttons
|
// end toolbar buttons
|
||||||
|
|
||||||
'unseen_comments' => $unseen_comments,
|
'unseen_comments' => $unseen_comments,
|
||||||
'comment_count' => $total_children,
|
'comment_count' => $total_children,
|
||||||
'comment_count_txt' => $comment_count_txt,
|
'comment_count_txt' => $comment_count_txt,
|
||||||
@@ -431,7 +468,9 @@ class ThreadItem {
|
|||||||
'preview_lbl' => t('This is an unsaved preview'),
|
'preview_lbl' => t('This is an unsaved preview'),
|
||||||
'wait' => t('Please wait'),
|
'wait' => t('Please wait'),
|
||||||
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
'submid' => str_replace(['+','='], ['',''], base64_encode($item['mid'])),
|
||||||
'thread_level' => $thread_level
|
'thread_level' => $thread_level,
|
||||||
|
'settings' => $settings,
|
||||||
|
'thr_parent' => (($item['parent_mid'] != $item['thr_parent']) ? $item['thr_parent'] : '')
|
||||||
);
|
);
|
||||||
|
|
||||||
$arr = array('item' => $item, 'output' => $tmp_item);
|
$arr = array('item' => $item, 'output' => $tmp_item);
|
||||||
@@ -454,7 +493,7 @@ class ThreadItem {
|
|||||||
|
|
||||||
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
|
if(($this->get_display_mode() === 'normal') && ($nb_children > 0)) {
|
||||||
foreach($children as $child) {
|
foreach($children as $child) {
|
||||||
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1);
|
$result['children'][] = $child->get_template_data($conv_responses, $thread_level + 1,$conv_flags);
|
||||||
}
|
}
|
||||||
// Collapse
|
// Collapse
|
||||||
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
|
if(($nb_children > $visible_comments) || ($thread_level > 1)) {
|
||||||
@@ -739,8 +778,6 @@ class ThreadItem {
|
|||||||
call_hooks('comment_buttons',$arr);
|
call_hooks('comment_buttons',$arr);
|
||||||
$comment_buttons = $arr['comment_buttons'];
|
$comment_buttons = $arr['comment_buttons'];
|
||||||
|
|
||||||
$feature_auto_save_draft = ((feature_enabled($conv->get_profile_owner(), 'auto_save_draft')) ? "true" : "false");
|
|
||||||
|
|
||||||
$comment_box = replace_macros($template,array(
|
$comment_box = replace_macros($template,array(
|
||||||
'$return_path' => '',
|
'$return_path' => '',
|
||||||
'$threaded' => $this->is_threaded(),
|
'$threaded' => $this->is_threaded(),
|
||||||
@@ -775,8 +812,7 @@ class ThreadItem {
|
|||||||
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
|
'$anoncomments' => ((($conv->get_mode() === 'channel' || $conv->get_mode() === 'display') && perm_is_allowed($conv->get_profile_owner(),'','post_comments')) ? true : false),
|
||||||
'$anonname' => [ 'anonname', t('Your full name (required)') ],
|
'$anonname' => [ 'anonname', t('Your full name (required)') ],
|
||||||
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
|
'$anonmail' => [ 'anonmail', t('Your email address (required)') ],
|
||||||
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ],
|
'$anonurl' => [ 'anonurl', t('Your website URL (optional)') ]
|
||||||
'$auto_save_draft' => $feature_auto_save_draft,
|
|
||||||
));
|
));
|
||||||
|
|
||||||
return $comment_box;
|
return $comment_box;
|
||||||
@@ -831,4 +867,3 @@ class ThreadItem {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
class ThreadListener {
|
||||||
|
|
||||||
|
static public function store($target_id,$portable_id,$ltype = 0) {
|
||||||
|
$x = self::fetch($target_id,$portable_id,$ltype = 0);
|
||||||
|
if(! $x) {
|
||||||
|
$r = q("insert into listeners ( target_id, portable_id, ltype ) values ( '%s', '%s' , %d ) ",
|
||||||
|
dbesc($target_id),
|
||||||
|
dbesc($portable_id),
|
||||||
|
intval($ltype)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function fetch($target_id,$portable_id,$ltype = 0) {
|
||||||
|
$x = q("select * from listeners where target_id = '%s' and portable_id = '%s' and ltype = %d limit 1",
|
||||||
|
dbesc($target_id),
|
||||||
|
dbesc($portable_id),
|
||||||
|
intval($ltype)
|
||||||
|
);
|
||||||
|
if($x) {
|
||||||
|
return $x[0];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function fetch_by_target($target_id,$ltype = 0) {
|
||||||
|
$x = q("select * from listeners where target_id = '%s' and ltype = %d",
|
||||||
|
dbesc($target_id),
|
||||||
|
intval($ltype)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function delete_by_target($target_id, $ltype = 0) {
|
||||||
|
return q("delete from listeners where target_id = '%s' and ltype = %d",
|
||||||
|
dbesc($target_id),
|
||||||
|
intval($ltype)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function delete_by_pid($portable_id, $ltype = 0) {
|
||||||
|
return q("delete from listeners where portable_id = '%s' and ltype = %d",
|
||||||
|
dbesc($portable_id),
|
||||||
|
intval($ltype)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -196,7 +196,6 @@ class ThreadStream {
|
|||||||
$item->set_commentable(false);
|
$item->set_commentable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once('include/channel.php');
|
|
||||||
|
|
||||||
$item->set_conversation($this);
|
$item->set_conversation($this);
|
||||||
$this->threads[] = $item;
|
$this->threads[] = $item;
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Fetch and return a webfinger for a resource
|
||||||
|
*
|
||||||
|
* @param string $resource - The resource
|
||||||
|
* @return boolean|string false or associative array from result JSON
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Webfinger {
|
||||||
|
|
||||||
|
static private $server = EMPTY_STR;
|
||||||
|
static private $resource = EMPTY_STR;
|
||||||
|
|
||||||
|
static function exec($resource) {
|
||||||
|
|
||||||
|
if(! $resource) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::parse_resource($resource);
|
||||||
|
|
||||||
|
if(! ( self::$server && self::$resource)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! check_siteallowed(self::$server)) {
|
||||||
|
logger('blacklisted: ' . self::$server);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
btlogger('fetching resource: ' . self::$resource . ' from ' . self::$server, LOGGER_DEBUG, LOG_INFO);
|
||||||
|
|
||||||
|
$url = 'https://' . self::$server . '/.well-known/webfinger?f=&resource=' . self::$resource ;
|
||||||
|
|
||||||
|
$counter = 0;
|
||||||
|
$s = z_fetch_url($url, false, $counter, [ 'headers' => [ 'Accept: application/jrd+json, */*' ] ]);
|
||||||
|
|
||||||
|
if($s['success']) {
|
||||||
|
$j = json_decode($s['body'], true);
|
||||||
|
return($j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function parse_resource($resource) {
|
||||||
|
|
||||||
|
self::$resource = urlencode($resource);
|
||||||
|
|
||||||
|
if(strpos($resource,'http') === 0) {
|
||||||
|
$m = parse_url($resource);
|
||||||
|
if($m) {
|
||||||
|
if($m['scheme'] !== 'https') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self::$server = $m['host'] . (($m['port']) ? ':' . $m['port'] : '');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif(strpos($resource,'tag:') === 0) {
|
||||||
|
$arr = explode(':',$resource); // split the tag
|
||||||
|
$h = explode(',',$arr[1]); // split the host,date
|
||||||
|
self::$server = $h[0];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$x = explode('@',$resource);
|
||||||
|
$username = $x[0];
|
||||||
|
if(count($x) > 1) {
|
||||||
|
self::$server = $x[1];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(strpos($resource,'acct:') !== 0) {
|
||||||
|
self::$resource = urlencode('acct:' . $resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fetch a webfinger resource and return a zot6 discovery url if present
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static function zot_url($resource) {
|
||||||
|
|
||||||
|
$arr = self::exec($resource);
|
||||||
|
|
||||||
|
if(is_array($arr) && array_key_exists('links',$arr)) {
|
||||||
|
foreach($arr['links'] as $link) {
|
||||||
|
if(array_key_exists('rel',$link) && $link['rel'] === PROTOCOL_ZOT6) {
|
||||||
|
if(array_key_exists('href',$link) && $link['href'] !== EMPTY_STR) {
|
||||||
|
return $link['href'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
|
|
||||||
|
class ZotURL {
|
||||||
|
|
||||||
|
static public function fetch($url,$channel) {
|
||||||
|
|
||||||
|
$ret = [ 'success' => false ];
|
||||||
|
|
||||||
|
if(strpos($url,'x-zot:') !== 0) {
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(! $url) {
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
$portable_url = substr($url,6);
|
||||||
|
$u = explode('/',$portable_url);
|
||||||
|
$portable_id = $u[0];
|
||||||
|
|
||||||
|
$hosts = self::lookup($portable_id);
|
||||||
|
|
||||||
|
if(! $hosts) {
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($hosts as $h) {
|
||||||
|
$newurl = $h . '/id/' . $portable_url;
|
||||||
|
|
||||||
|
$m = parse_url($newurl);
|
||||||
|
|
||||||
|
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||||
|
|
||||||
|
if($channel && $m) {
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Accept' => 'application/x-zot+json',
|
||||||
|
'Content-Type' => 'application/x-zot+json',
|
||||||
|
'X-Zot-Token' => random_string(),
|
||||||
|
'Digest' => HTTPSig::generate_digest_header($data),
|
||||||
|
'Host' => $m['host'],
|
||||||
|
'(request-target)' => 'post ' . get_request_string($newurl)
|
||||||
|
];
|
||||||
|
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$h = [ 'Accept: application/x-zot+json' ];
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
$redirects = 0;
|
||||||
|
$x = z_post_url($newurl,$data,$redirects, [ 'headers' => $h ] );
|
||||||
|
if($x['success']) {
|
||||||
|
return $x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static public function is_zoturl($url) {
|
||||||
|
|
||||||
|
if(strpos($url,'x-zot:') === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static public function lookup($portable_id) {
|
||||||
|
|
||||||
|
$r = q("select * from hubloc left join site on hubloc_url = site_url where hubloc_hash = '%s' and site_dead = 0 order by hubloc_primary desc",
|
||||||
|
dbesc($portable_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
if(! $r) {
|
||||||
|
// extend to network lookup
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return ids_to_array($r,'hubloc_url');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Lib;
|
||||||
|
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
|
class Zotfinger {
|
||||||
|
|
||||||
|
static function exec($resource,$channel = null) {
|
||||||
|
|
||||||
|
if(! $resource) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$m = parse_url($resource);
|
||||||
|
|
||||||
|
$data = json_encode([ 'zot_token' => random_string() ]);
|
||||||
|
|
||||||
|
if($channel && $m) {
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Accept' => 'application/x-zot+json',
|
||||||
|
'Content-Type' => 'application/x-zot+json',
|
||||||
|
'X-Zot-Token' => random_string(),
|
||||||
|
'Digest' => HTTPSig::generate_digest_header($data),
|
||||||
|
'Host' => $m['host'],
|
||||||
|
'(request-target)' => 'post ' . get_request_string($resource)
|
||||||
|
];
|
||||||
|
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel),false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$h = [ 'Accept: application/x-zot+json' ];
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
|
||||||
|
$redirects = 0;
|
||||||
|
$x = z_post_url($resource,$data,$redirects, [ 'headers' => $h ] );
|
||||||
|
|
||||||
|
logger('fetch: ' . print_r($x,true));
|
||||||
|
|
||||||
|
if($x['success']) {
|
||||||
|
|
||||||
|
$result['signature'] = HTTPSig::verify($x);
|
||||||
|
|
||||||
|
$result['data'] = json_decode($x['body'],true);
|
||||||
|
|
||||||
|
if($result['data'] && is_array($result['data']) && array_key_exists('encrypted',$result['data']) && $result['data']['encrypted']) {
|
||||||
|
$result['data'] = json_decode(crypto_unencapsulate($result['data'],get_config('system','prvkey')),true);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger('decrypted: ' . print_r($result,true));
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+12
-11
@@ -81,9 +81,10 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
if($search) {
|
if($search) {
|
||||||
$sql_extra = " AND groups.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
|
$sql_extra = " AND pgrp.gname LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " ";
|
||||||
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
$sql_extra2 = "AND ( xchan_name LIKE " . protect_sprintf( "'%" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'%" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
||||||
|
$sql_extra2_xchan = "AND ( xchan_name LIKE " . protect_sprintf( "'" . dbesc($search) . "%'" ) . " OR xchan_addr LIKE " . protect_sprintf( "'" . dbesc(punify($search)) . ((strpos($search,'@') === false) ? "%@%'" : "%'")) . ") ";
|
||||||
|
|
||||||
// This horrible mess is needed because position also returns 0 if nothing is found.
|
// This horrible mess is needed because position also returns 0 if nothing is found.
|
||||||
// Would be MUCH easier if it instead returned a very large value
|
// Would be MUCH easier if it instead returned a very large value
|
||||||
// Otherwise we could just
|
// Otherwise we could just
|
||||||
@@ -128,13 +129,13 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
// Normal privacy groups
|
// Normal privacy groups
|
||||||
|
|
||||||
$r = q("SELECT groups.id, groups.hash, groups.gname
|
$r = q("SELECT pgrp.id, pgrp.hash, pgrp.gname
|
||||||
FROM groups, group_member
|
FROM pgrp, pgrp_member
|
||||||
WHERE groups.deleted = 0 AND groups.uid = %d
|
WHERE pgrp.deleted = 0 AND pgrp.uid = %d
|
||||||
AND group_member.gid = groups.id
|
AND pgrp_member.gid = pgrp.id
|
||||||
$sql_extra
|
$sql_extra
|
||||||
GROUP BY groups.id
|
GROUP BY pgrp.id
|
||||||
ORDER BY groups.gname
|
ORDER BY pgrp.gname
|
||||||
LIMIT %d OFFSET %d",
|
LIMIT %d OFFSET %d",
|
||||||
intval(local_channel()),
|
intval(local_channel()),
|
||||||
intval($count),
|
intval($count),
|
||||||
@@ -165,7 +166,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||||||
if($extra_channels) {
|
if($extra_channels) {
|
||||||
foreach($extra_channels as $channel) {
|
foreach($extra_channels as $channel) {
|
||||||
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) {
|
if(perm_is_allowed(intval($channel), get_observer_hash(),'view_contacts')) {
|
||||||
if($extra_channel_sql)
|
if($extra_channels_sql)
|
||||||
$extra_channels_sql .= ',';
|
$extra_channels_sql .= ',';
|
||||||
$extra_channels_sql .= intval($channel);
|
$extra_channels_sql .= intval($channel);
|
||||||
}
|
}
|
||||||
@@ -226,7 +227,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||||||
else { // Visitors
|
else { // Visitors
|
||||||
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
$r = q("SELECT xchan_hash as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||||
FROM xchan left join xlink on xlink_link = xchan_hash
|
FROM xchan left join xlink on xlink_link = xchan_hash
|
||||||
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2 order by $order_extra2 xchan_name asc" ,
|
WHERE xlink_xchan = '%s' AND xchan_deleted = 0 $sql_extra2_xchan order by $order_extra2 xchan_name asc" ,
|
||||||
dbesc(get_observer_hash())
|
dbesc(get_observer_hash())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -270,7 +271,7 @@ class Acl extends \Zotlabs\Web\Controller {
|
|||||||
if((count($r) < 100) && $type == 'c') {
|
if((count($r) < 100) && $type == 'c') {
|
||||||
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
$r2 = q("SELECT substr(xchan_hash,1,18) as id, xchan_hash as hash, xchan_name as name, xchan_photo_s as micro, xchan_url as url, xchan_addr as nick, 0 as abook_their_perms, 0 as abook_flags, 0 as abook_self
|
||||||
FROM xchan
|
FROM xchan
|
||||||
WHERE xchan_deleted = 0 and not xchan_network in ('rss','anon','unknown') $sql_extra2 order by $order_extra2 xchan_name asc"
|
WHERE xchan_deleted = 0 and not xchan_network in ('rss','anon','unknown') $sql_extra2_xchan order by $order_extra2 xchan_name asc"
|
||||||
);
|
);
|
||||||
if($r2) {
|
if($r2) {
|
||||||
$r = array_merge($r,$r2);
|
$r = array_merge($r,$r2);
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class Admin extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
// list total user accounts, expirations etc.
|
// list total user accounts, expirations etc.
|
||||||
$accounts = array();
|
$accounts = array();
|
||||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
$r = q("SELECT COUNT(CASE WHEN account_id > 0 THEN 1 ELSE NULL END) AS total, COUNT(CASE WHEN account_expires > %s THEN 1 ELSE NULL END) AS expiring, COUNT(CASE WHEN account_expires < %s AND account_expires > '%s' THEN 1 ELSE NULL END) AS expired, COUNT(CASE WHEN (account_flags & %d)>0 THEN 1 ELSE NULL END) AS blocked FROM account",
|
||||||
db_utcnow(),
|
db_utcnow(),
|
||||||
db_utcnow(),
|
db_utcnow(),
|
||||||
dbesc(NULL_DATE),
|
dbesc(NULL_DATE),
|
||||||
@@ -109,11 +109,9 @@ class Admin extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
// available channels, primary and clones
|
// available channels, primary and clones
|
||||||
$channels = array();
|
$channels = array();
|
||||||
$r = q("SELECT COUNT(*) AS total, COUNT(CASE WHEN channel_primary = 1 THEN 1 ELSE NULL END) AS main, COUNT(CASE WHEN channel_primary = 0 THEN 1 ELSE NULL END) AS clones FROM channel WHERE channel_removed = 0");
|
$r = q("SELECT COUNT(*) AS total FROM channel WHERE channel_removed = 0 and channel_system = 0");
|
||||||
if ($r) {
|
if ($r) {
|
||||||
$channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']);
|
$channels['total'] = array('label' => t('Channels'), 'val' => $r[0]['total']);
|
||||||
$channels['main'] = array('label' => t('Primary'), 'val' => $r[0]['main']);
|
|
||||||
$channels['clones'] = array('label' => t('Clones'), 'val' => $r[0]['clones']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can do better, but this is a quick queue status
|
// We can do better, but this is a quick queue status
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Account_edit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$service_class = trim($_REQUEST['service_class']);
|
$service_class = trim($_REQUEST['service_class']);
|
||||||
$account_level = intval(trim($_REQUEST['account_level']));
|
$account_level = 5;
|
||||||
$account_language = trim($_REQUEST['account_language']);
|
$account_language = trim($_REQUEST['account_language']);
|
||||||
|
|
||||||
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
|
$r = q("update account set account_service_class = '%s', account_level = %d, account_language = '%s'
|
||||||
@@ -68,7 +68,6 @@ class Account_edit {
|
|||||||
'$title' => t('Account Edit'),
|
'$title' => t('Account Edit'),
|
||||||
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],
|
'$pass1' => [ 'pass1', t('New Password'), ' ','' ],
|
||||||
'$pass2' => [ 'pass2', t('New Password again'), ' ','' ],
|
'$pass2' => [ 'pass2', t('New Password again'), ' ','' ],
|
||||||
'$account_level' => [ 'account_level', t('Technical skill level'), $x[0]['account_level'], '', \Zotlabs\Lib\Techlevels::levels() ],
|
|
||||||
'$account_language' => [ 'account_language' , t('Account language (for emails)'), $x[0]['account_language'], '', language_list() ],
|
'$account_language' => [ 'account_language' , t('Account language (for emails)'), $x[0]['account_language'], '', language_list() ],
|
||||||
'$service_class' => [ 'service_class', t('Service class'), $x[0]['account_service_class'], '' ],
|
'$service_class' => [ 'service_class', t('Service class'), $x[0]['account_service_class'], '' ],
|
||||||
'$submit' => t('Submit'),
|
'$submit' => t('Submit'),
|
||||||
@@ -81,4 +80,4 @@ class Account_edit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Module\Admin;
|
namespace Zotlabs\Module\Admin;
|
||||||
|
|
||||||
|
use App;
|
||||||
use \Zotlabs\Storage\GitRepo;
|
use \Zotlabs\Storage\GitRepo;
|
||||||
use \Michelf\MarkdownExtra;
|
use \Michelf\MarkdownExtra;
|
||||||
|
|
||||||
@@ -253,14 +254,14 @@ class Addons {
|
|||||||
* Single plugin
|
* Single plugin
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (\App::$argc == 3){
|
if (App::$argc == 3){
|
||||||
$plugin = \App::$argv[2];
|
$plugin = App::$argv[2];
|
||||||
if (!is_file("addon/$plugin/$plugin.php")){
|
if (!is_file("addon/$plugin/$plugin.php")){
|
||||||
notice( t("Item not found.") );
|
notice( t("Item not found.") );
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$enabled = in_array($plugin,\App::$plugins);
|
$enabled = in_array($plugin,App::$plugins);
|
||||||
$info = get_plugin_info($plugin);
|
$info = get_plugin_info($plugin);
|
||||||
$x = check_plugin_versions($info);
|
$x = check_plugin_versions($info);
|
||||||
|
|
||||||
@@ -268,11 +269,11 @@ class Addons {
|
|||||||
|
|
||||||
if($enabled && ! $x) {
|
if($enabled && ! $x) {
|
||||||
$enabled = false;
|
$enabled = false;
|
||||||
$idz = array_search($plugin, \App::$plugins);
|
$idz = array_search($plugin, App::$plugins);
|
||||||
if ($idz !== false) {
|
if ($idz !== false) {
|
||||||
unset(\App::$plugins[$idz]);
|
unset(App::$plugins[$idz]);
|
||||||
uninstall_plugin($plugin);
|
uninstall_plugin($plugin);
|
||||||
set_config("system","addon", implode(", ",\App::$plugins));
|
set_config("system","addon", implode(", ",App::$plugins));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['disabled'] = 1-intval($x);
|
$info['disabled'] = 1-intval($x);
|
||||||
@@ -281,19 +282,19 @@ class Addons {
|
|||||||
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
check_form_security_token_redirectOnErr('/admin/addons', 'admin_addons', 't');
|
||||||
$pinstalled = false;
|
$pinstalled = false;
|
||||||
// Toggle plugin status
|
// Toggle plugin status
|
||||||
$idx = array_search($plugin, \App::$plugins);
|
$idx = array_search($plugin, App::$plugins);
|
||||||
if ($idx !== false){
|
if ($idx !== false){
|
||||||
unset(\App::$plugins[$idx]);
|
unset(App::$plugins[$idx]);
|
||||||
uninstall_plugin($plugin);
|
uninstall_plugin($plugin);
|
||||||
$pinstalled = false;
|
$pinstalled = false;
|
||||||
info( sprintf( t("Plugin %s disabled."), $plugin ) );
|
info( sprintf( t("Plugin %s disabled."), $plugin ) );
|
||||||
} else {
|
} else {
|
||||||
\App::$plugins[] = $plugin;
|
App::$plugins[] = $plugin;
|
||||||
install_plugin($plugin);
|
install_plugin($plugin);
|
||||||
$pinstalled = true;
|
$pinstalled = true;
|
||||||
info( sprintf( t("Plugin %s enabled."), $plugin ) );
|
info( sprintf( t("Plugin %s enabled."), $plugin ) );
|
||||||
}
|
}
|
||||||
set_config("system","addon", implode(", ",\App::$plugins));
|
set_config("system","addon", implode(", ",App::$plugins));
|
||||||
|
|
||||||
if($pinstalled) {
|
if($pinstalled) {
|
||||||
@require_once("addon/$plugin/$plugin.php");
|
@require_once("addon/$plugin/$plugin.php");
|
||||||
@@ -305,7 +306,7 @@ class Addons {
|
|||||||
|
|
||||||
// display plugin details
|
// display plugin details
|
||||||
|
|
||||||
if (in_array($plugin, \App::$plugins)){
|
if (in_array($plugin, App::$plugins)){
|
||||||
$status = 'on';
|
$status = 'on';
|
||||||
$action = t('Disable');
|
$action = t('Disable');
|
||||||
} else {
|
} else {
|
||||||
@@ -375,20 +376,23 @@ class Addons {
|
|||||||
if($files) {
|
if($files) {
|
||||||
foreach($files as $file) {
|
foreach($files as $file) {
|
||||||
if (is_dir($file)){
|
if (is_dir($file)){
|
||||||
|
if($file == 'addon/addon_common/')
|
||||||
|
continue;
|
||||||
|
|
||||||
list($tmp, $id) = array_map('trim', explode('/', $file));
|
list($tmp, $id) = array_map('trim', explode('/', $file));
|
||||||
$info = get_plugin_info($id);
|
$info = get_plugin_info($id);
|
||||||
$enabled = in_array($id,\App::$plugins);
|
$enabled = in_array($id,App::$plugins);
|
||||||
$x = check_plugin_versions($info);
|
$x = check_plugin_versions($info);
|
||||||
|
|
||||||
// disable plugins which are installed but incompatible versions
|
// disable plugins which are installed but incompatible versions
|
||||||
|
|
||||||
if($enabled && ! $x) {
|
if($enabled && ! $x) {
|
||||||
$enabled = false;
|
$enabled = false;
|
||||||
$idz = array_search($id, \App::$plugins);
|
$idz = array_search($id, App::$plugins);
|
||||||
if ($idz !== false) {
|
if ($idz !== false) {
|
||||||
unset(\App::$plugins[$idz]);
|
unset(App::$plugins[$idz]);
|
||||||
uninstall_plugin($id);
|
uninstall_plugin($id);
|
||||||
set_config("system","addon", implode(", ",\App::$plugins));
|
set_config("system","addon", implode(", ",App::$plugins));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$info['disabled'] = 1-intval($x);
|
$info['disabled'] = 1-intval($x);
|
||||||
@@ -476,4 +480,4 @@ class Addons {
|
|||||||
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
|
return(strcmp(strtolower($a[2]['name']),strtolower($b[2]['name'])));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,47 @@ class Dbsync {
|
|||||||
info( t('Update has been marked successful') . EOL);
|
info( t('Update has been marked successful') . EOL);
|
||||||
goaway(z_root() . '/admin/dbsync');
|
goaway(z_root() . '/admin/dbsync');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(argc() > 3 && intval(argv(3)) && argv(2) === 'verify') {
|
||||||
|
|
||||||
|
$s = '_' . intval(argv(3));
|
||||||
|
$cls = '\\Zotlabs\Update\\' . $s ;
|
||||||
|
if(class_exists($cls)) {
|
||||||
|
$c = new $cls();
|
||||||
|
if(method_exists($c,'verify')) {
|
||||||
|
$retval = $c->verify();
|
||||||
|
if($retval === UPDATE_FAILED) {
|
||||||
|
$o .= sprintf( t('Verification of update %s failed. Check system logs.'), $s);
|
||||||
|
}
|
||||||
|
elseif($retval === UPDATE_SUCCESS) {
|
||||||
|
$o .= sprintf( t('Update %s was successfully applied.'), $s);
|
||||||
|
set_config('database',$s, 'success');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$o .= sprintf( t('Verifying update %s did not return a status. Unknown if it succeeded.'), $s);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$o .= sprintf( t('Update %s does not contain a verification function.'), $s );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$o .= sprintf( t('Update function %s could not be found.'), $s);
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// remove the old style config if it exists
|
||||||
|
del_config('database', 'update_r' . intval(argv(3)));
|
||||||
|
set_config('database', '_' . intval(argv(3)), 'success');
|
||||||
|
if(intval(get_config('system','db_version')) < intval(argv(3)))
|
||||||
|
set_config('system','db_version',intval(argv(3)));
|
||||||
|
info( t('Update has been marked successful') . EOL);
|
||||||
|
goaway(z_root() . '/admin/dbsync');
|
||||||
|
}
|
||||||
|
|
||||||
if(argc() > 2 && intval(argv(2))) {
|
if(argc() > 2 && intval(argv(2))) {
|
||||||
$x = intval(argv(2));
|
$x = intval(argv(2));
|
||||||
$s = '_' . $x;
|
$s = '_' . $x;
|
||||||
@@ -28,14 +68,14 @@ class Dbsync {
|
|||||||
$c = new $cls();
|
$c = new $cls();
|
||||||
$retval = $c->run();
|
$retval = $c->run();
|
||||||
if($retval === UPDATE_FAILED) {
|
if($retval === UPDATE_FAILED) {
|
||||||
$o .= sprintf( t('Executing %s failed. Check system logs.'), $s);
|
$o .= sprintf( t('Executing update procedure %s failed. Check system logs.'), $s);
|
||||||
}
|
}
|
||||||
elseif($retval === UPDATE_SUCCESS) {
|
elseif($retval === UPDATE_SUCCESS) {
|
||||||
$o .= sprintf( t('Update %s was successfully applied.'), $s);
|
$o .= sprintf( t('Update %s was successfully applied.'), $s);
|
||||||
set_config('database',$s, 'success');
|
set_config('database',$s, 'success');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$o .= sprintf( t('Update %s did not return a status. Unknown if it succeeded.'), $s);
|
$o .= sprintf( t('Update %s did not return a status. It cannot be determined if it was successful.'), $s);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$o .= sprintf( t('Update function %s could not be found.'), $s);
|
$o .= sprintf( t('Update function %s could not be found.'), $s);
|
||||||
@@ -59,6 +99,7 @@ class Dbsync {
|
|||||||
'$banner' => t('Failed Updates'),
|
'$banner' => t('Failed Updates'),
|
||||||
'$desc' => '',
|
'$desc' => '',
|
||||||
'$mark' => t('Mark success (if update was manually applied)'),
|
'$mark' => t('Mark success (if update was manually applied)'),
|
||||||
|
'$verify' => t('Attempt to verify this update if a verification procedure exists'),
|
||||||
'$apply' => t('Attempt to execute this update step automatically'),
|
'$apply' => t('Attempt to execute this update step automatically'),
|
||||||
'$failed' => $failed
|
'$failed' => $failed
|
||||||
));
|
));
|
||||||
|
|||||||
@@ -43,6 +43,12 @@ class Security {
|
|||||||
|
|
||||||
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
|
$be = $this->trim_array_elems(explode("\n",$_POST['embed_deny']));
|
||||||
set_config('system','embed_deny',$be);
|
set_config('system','embed_deny',$be);
|
||||||
|
|
||||||
|
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
||||||
|
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
||||||
|
|
||||||
|
$inline_pdf = ((x($_POST,'inline_pdf')) ? intval($_POST['inline_pdf']) : 0);
|
||||||
|
set_config('system', 'inline_pdf' , $inline_pdf);
|
||||||
|
|
||||||
$ts = ((x($_POST,'transport_security')) ? True : False);
|
$ts = ((x($_POST,'transport_security')) ? True : False);
|
||||||
set_config('system','transport_security_header',$ts);
|
set_config('system','transport_security_header',$ts);
|
||||||
@@ -86,7 +92,7 @@ class Security {
|
|||||||
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
|
$embedhelp2 = t("The recommended setting is to only allow unfiltered HTML from the following sites:");
|
||||||
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
|
$embedhelp3 = t("https://youtube.com/<br />https://www.youtube.com/<br />https://youtu.be/<br />https://vimeo.com/<br />https://soundcloud.com/<br />");
|
||||||
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
|
$embedhelp4 = t("All other embedded content will be filtered, <strong>unless</strong> embedded content from that site is explicitly blocked.");
|
||||||
|
|
||||||
$t = get_markup_template('admin_security.tpl');
|
$t = get_markup_template('admin_security.tpl');
|
||||||
return replace_macros($t, array(
|
return replace_macros($t, array(
|
||||||
'$title' => t('Administration'),
|
'$title' => t('Administration'),
|
||||||
@@ -106,7 +112,9 @@ class Security {
|
|||||||
'$embed_sslonly' => array('embed_sslonly',t('Only allow embeds from secure (SSL) websites and links.'), intval(get_config('system','embed_sslonly')),''),
|
'$embed_sslonly' => array('embed_sslonly',t('Only allow embeds from secure (SSL) websites and links.'), intval(get_config('system','embed_sslonly')),''),
|
||||||
'$embed_allow' => array('embed_allow', t('Allow unfiltered embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. By default embedded content is filtered.')),
|
'$embed_allow' => array('embed_allow', t('Allow unfiltered embedded HTML content only from these domains'), $whiteembeds_str, t('One site per line. By default embedded content is filtered.')),
|
||||||
'$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
|
'$embed_deny' => array('embed_deny', t('Block embedded HTML from these domains'), $blackembeds_str, ''),
|
||||||
|
'$thumbnail_security' => [ 'thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.") ],
|
||||||
|
'$inline_pdf' => [ 'inline_pdf', t("Allow embedded (inline) PDF files"), get_config('system','inline_pdf',0), '' ],
|
||||||
|
|
||||||
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
|
// '$embed_coop' => array('embed_coop', t('Cooperative embed security'), $embed_coop, t('Enable to share embed security with other compatible sites/hubs')),
|
||||||
|
|
||||||
'$submit' => t('Submit')
|
'$submit' => t('Submit')
|
||||||
@@ -128,4 +136,4 @@ class Security {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,19 +72,13 @@ class Site {
|
|||||||
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
|
$maxloadavg = ((x($_POST,'maxloadavg')) ? intval(trim($_POST['maxloadavg'])) : 50);
|
||||||
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
$feed_contacts = ((x($_POST,'feed_contacts')) ? intval($_POST['feed_contacts']) : 0);
|
||||||
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
$verify_email = ((x($_POST,'verify_email')) ? 1 : 0);
|
||||||
$techlevel_lock = ((x($_POST,'techlock')) ? intval($_POST['techlock']) : 0);
|
|
||||||
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
$imagick_path = ((x($_POST,'imagick_path')) ? trim($_POST['imagick_path']) : '');
|
||||||
$thumbnail_security = ((x($_POST,'thumbnail_security')) ? intval($_POST['thumbnail_security']) : 0);
|
|
||||||
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
|
$force_queue = ((intval($_POST['force_queue']) > 0) ? intval($_POST['force_queue']) : 3000);
|
||||||
$pub_incl = escape_tags(trim($_POST['pub_incl']));
|
$pub_incl = escape_tags(trim($_POST['pub_incl']));
|
||||||
$pub_excl = escape_tags(trim($_POST['pub_excl']));
|
$pub_excl = escape_tags(trim($_POST['pub_excl']));
|
||||||
|
|
||||||
$permissions_role = escape_tags(trim($_POST['permissions_role']));
|
$permissions_role = escape_tags(trim($_POST['permissions_role']));
|
||||||
|
|
||||||
$techlevel = null;
|
|
||||||
if(array_key_exists('techlevel', $_POST))
|
|
||||||
$techlevel = intval($_POST['techlevel']);
|
|
||||||
|
|
||||||
set_config('system', 'feed_contacts', $feed_contacts);
|
set_config('system', 'feed_contacts', $feed_contacts);
|
||||||
set_config('system', 'delivery_interval', $delivery_interval);
|
set_config('system', 'delivery_interval', $delivery_interval);
|
||||||
set_config('system', 'delivery_batch_count', $delivery_batch_count);
|
set_config('system', 'delivery_batch_count', $delivery_batch_count);
|
||||||
@@ -105,17 +99,10 @@ class Site {
|
|||||||
set_config('system', 'from_email', $from_email);
|
set_config('system', 'from_email', $from_email);
|
||||||
set_config('system', 'from_email_name' , $from_email_name);
|
set_config('system', 'from_email_name' , $from_email_name);
|
||||||
set_config('system', 'imagick_convert_path' , $imagick_path);
|
set_config('system', 'imagick_convert_path' , $imagick_path);
|
||||||
set_config('system', 'thumbnail_security' , $thumbnail_security);
|
|
||||||
set_config('system', 'default_permissions_role', $permissions_role);
|
set_config('system', 'default_permissions_role', $permissions_role);
|
||||||
set_config('system', 'pubstream_incl',$pub_incl);
|
set_config('system', 'pubstream_incl',$pub_incl);
|
||||||
set_config('system', 'pubstream_excl',$pub_excl);
|
set_config('system', 'pubstream_excl',$pub_excl);
|
||||||
|
|
||||||
set_config('system', 'techlevel_lock', $techlevel_lock);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(! is_null($techlevel))
|
|
||||||
set_config('system', 'techlevel', $techlevel);
|
|
||||||
|
|
||||||
if($directory_server)
|
if($directory_server)
|
||||||
set_config('system','directory_server',$directory_server);
|
set_config('system','directory_server',$directory_server);
|
||||||
@@ -130,7 +117,7 @@ class Site {
|
|||||||
del_config('system', 'admininfo');
|
del_config('system', 'admininfo');
|
||||||
} else {
|
} else {
|
||||||
require_once('include/text.php');
|
require_once('include/text.php');
|
||||||
linkify_tags($a, $admininfo, local_channel());
|
linkify_tags($admininfo, local_channel());
|
||||||
set_config('system', 'admininfo', $admininfo);
|
set_config('system', 'admininfo', $admininfo);
|
||||||
}
|
}
|
||||||
set_config('system','siteinfo',$siteinfo);
|
set_config('system','siteinfo',$siteinfo);
|
||||||
@@ -284,15 +271,6 @@ class Site {
|
|||||||
// now invert the logic for the setting.
|
// now invert the logic for the setting.
|
||||||
$discover_tab = (1 - $discover_tab);
|
$discover_tab = (1 - $discover_tab);
|
||||||
|
|
||||||
$techlevels = [
|
|
||||||
'0' => t('Beginner/Basic'),
|
|
||||||
'1' => t('Novice - not skilled but willing to learn'),
|
|
||||||
'2' => t('Intermediate - somewhat comfortable'),
|
|
||||||
'3' => t('Advanced - very comfortable'),
|
|
||||||
'4' => t('Expert - I can write computer code'),
|
|
||||||
'5' => t('Wizard - I probably know more than you do')
|
|
||||||
];
|
|
||||||
|
|
||||||
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
$perm_roles = \Zotlabs\Access\PermissionRoles::roles();
|
||||||
$default_role = get_config('system','default_permissions_role','social');
|
$default_role = get_config('system','default_permissions_role','social');
|
||||||
|
|
||||||
@@ -316,10 +294,6 @@ class Site {
|
|||||||
// name, label, value, help string, extra data...
|
// name, label, value, help string, extra data...
|
||||||
'$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''),
|
'$sitename' => array('sitename', t("Site name"), htmlspecialchars(get_config('system','sitename'), ENT_QUOTES, 'UTF-8'),''),
|
||||||
|
|
||||||
'$techlevel' => [ 'techlevel', t('Site default technical skill level'), get_config('system','techlevel'), t('Used to provide a member experience matched to technical comfort level'), $techlevels ],
|
|
||||||
|
|
||||||
'$techlock' => [ 'techlock', t('Lock the technical skill level setting'), get_config('system','techlevel_lock'), t('Members can set their own technical comfort level by default') ],
|
|
||||||
|
|
||||||
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
|
'$banner' => array('banner', t("Banner/Logo"), $banner, t('Unfiltered HTML/CSS/JS is allowed')),
|
||||||
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
|
'$admininfo' => array('admininfo', t("Administrator Information"), $admininfo, t("Contact information for site administrators. Displayed on siteinfo page. BBCode can be used here")),
|
||||||
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
|
'$siteinfo' => array('siteinfo', t('Site Information'), get_config('system','siteinfo'), t("Publicly visible description of this site. Displayed on siteinfo page. BBCode can be used here")),
|
||||||
@@ -332,10 +306,10 @@ class Site {
|
|||||||
'$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
|
'$register_policy' => array('register_policy', t("Does this site allow new member registration?"), get_config('system','register_policy'), "", $register_choices),
|
||||||
'$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
|
'$invite_only' => array('invite_only', t("Invitation only"), get_config('system','invitation_only'), t("Only allow new member registrations with an invitation code. Above register policy must be set to Yes.")),
|
||||||
'$minimum_age' => array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")),
|
'$minimum_age' => array('minimum_age', t("Minimum age"), (x(get_config('system','minimum_age'))?get_config('system','minimum_age'):13), t("Minimum age (in years) for who may register on this site.")),
|
||||||
'$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), "This is displayed on the public server site list.", $access_choices),
|
'$access_policy' => array('access_policy', t("Which best describes the types of account offered by this hub?"), get_config('system','access_policy'), t("This is displayed on the public server site list."), $access_choices),
|
||||||
'$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
|
'$register_text' => array('register_text', t("Register text"), htmlspecialchars(get_config('system','register_text'), ENT_QUOTES, 'UTF-8'), t("Will be displayed prominently on the registration page.")),
|
||||||
'$role' => $role,
|
'$role' => $role,
|
||||||
'$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'public' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
|
'$frontpage' => array('frontpage', t("Site homepage to show visitors (default: login box)"), get_config('system','frontpage'), t("example: 'pubstream' to show public stream, 'page/sys/home' to show a system webpage called 'home' or 'include:home.html' to include a file.")),
|
||||||
'$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
|
'$mirror_frontpage' => array('mirror_frontpage', t("Preserve site homepage URL"), get_config('system','mirror_frontpage'), t('Present the site homepage in a frame at the original location instead of redirecting')),
|
||||||
'$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
|
'$abandon_days' => array('abandon_days', t('Accounts abandoned after x days'), get_config('system','account_abandon_days'), t('Will not waste system resources polling external sites for abandonded accounts. Enter 0 for no time limit.')),
|
||||||
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
|
'$allowed_sites' => array('allowed_sites', t("Allowed friend domains"), get_config('system','allowed_sites'), t("Comma separated list of domains which are allowed to establish friendships with this site. Wildcards are accepted. Empty to allow any domains")),
|
||||||
@@ -365,7 +339,6 @@ class Site {
|
|||||||
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
|
'$force_queue' => array('force_queue', t("Queue Threshold"), get_config('system','force_queue_threshold',3000), t("Always defer immediate delivery if queue contains more than this number of entries.")),
|
||||||
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
'$poll_interval' => array('poll_interval', t("Poll interval"), (x(get_config('system','poll_interval'))?get_config('system','poll_interval'):2), t("Delay background polling processes by this many seconds to reduce system load. If 0, use delivery interval.")),
|
||||||
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
'$imagick_path' => array('imagick_path', t("Path to ImageMagick convert program"), get_config('system','imagick_convert_path'), t("If set, use this program to generate photo thumbnails for huge images ( > 4000 pixels in either dimension), otherwise memory exhaustion may occur. Example: /usr/bin/convert")),
|
||||||
'$thumbnail_security' => array('thumbnail_security', t("Allow SVG thumbnails in file browser"), get_config('system','thumbnail_security',0), t("WARNING: SVG images may contain malicious code.")),
|
|
||||||
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
'$maxloadavg' => array('maxloadavg', t("Maximum Load Average"), ((intval(get_config('system','maxloadavg')) > 0)?get_config('system','maxloadavg'):50), t("Maximum system load before delivery and poll processes are deferred - default 50.")),
|
||||||
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
'$default_expire_days' => array('default_expire_days', t('Expiration period in days for imported (grid/network) content'), intval(get_config('system','default_expire_days')), t('0 for no expiration of imported content')),
|
||||||
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
|
'$active_expire_days' => array('active_expire_days', t('Do not expire any posts which have comments less than this many days ago'), intval(get_config('system','active_expire_days',7)), ''),
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Lib\Libsync;
|
||||||
|
|
||||||
|
class Affinity extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
|
function post() {
|
||||||
|
|
||||||
|
if(! local_channel())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(),'Affinity Tool'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
check_form_security_token_redirectOnErr('affinity', 'affinity');
|
||||||
|
|
||||||
|
$cmax = intval($_POST['affinity_cmax']);
|
||||||
|
if($cmax < 0 || $cmax > 99)
|
||||||
|
$cmax = 99;
|
||||||
|
|
||||||
|
$cmin = intval($_POST['affinity_cmin']);
|
||||||
|
if($cmin < 0 || $cmin > 99)
|
||||||
|
$cmin = 0;
|
||||||
|
|
||||||
|
$lock = intval($_POST['affinity_lock']);
|
||||||
|
|
||||||
|
set_pconfig(local_channel(),'affinity','cmin',$cmin);
|
||||||
|
set_pconfig(local_channel(),'affinity','cmax',$cmax);
|
||||||
|
set_pconfig(local_channel(),'affinity','lock',$lock);
|
||||||
|
|
||||||
|
info( t('Affinity Tool settings updated.') . EOL);
|
||||||
|
|
||||||
|
Libsync::build_sync_packet();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
|
||||||
|
if(! local_channel())
|
||||||
|
return;
|
||||||
|
|
||||||
|
$desc = t('This app presents a slider control in your connection editor and also on your network page. The slider represents your degree of friendship (affinity) with each connection. It allows you to zoom in or out and display conversations from only your closest friends or everybody in your stream.');
|
||||||
|
if(! Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Affinity Tool App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= $desc;
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
$text = t('The numbers below represent the minimum and maximum slider default positions for your network/stream page as a percentage.');
|
||||||
|
|
||||||
|
$content = '<div class="section-content-info-wrapper">' . $text . '</div>';
|
||||||
|
|
||||||
|
$cmax = intval(get_pconfig(local_channel(),'affinity','cmax'));
|
||||||
|
$cmax = (($cmax) ? $cmax : 99);
|
||||||
|
$content .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||||
|
'$field' => array('affinity_cmax', t('Default maximum affinity level'), $cmax, t('0-99 default 99'))
|
||||||
|
));
|
||||||
|
|
||||||
|
$cmin = intval(get_pconfig(local_channel(),'affinity','cmin'));
|
||||||
|
$cmin = (($cmin) ? $cmin : 0);
|
||||||
|
$content .= replace_macros(get_markup_template('field_input.tpl'), array(
|
||||||
|
'$field' => array('affinity_cmin', t('Default minimum affinity level'), $cmin, t('0-99 - default 0'))
|
||||||
|
));
|
||||||
|
|
||||||
|
$lock = intval(get_pconfig(local_channel(),'affinity','lock',1));
|
||||||
|
|
||||||
|
$content .= replace_macros(get_markup_template('field_checkbox.tpl'), array(
|
||||||
|
'$field' => array('affinity_lock', t('Persistent affinity levels'), $lock, t('If disabled the max and min levels will be reset to default after page reload'), ['No','Yes'])
|
||||||
|
));
|
||||||
|
|
||||||
|
$tpl = get_markup_template("settings_addon.tpl");
|
||||||
|
|
||||||
|
$o = replace_macros($tpl, array(
|
||||||
|
'$action_url' => 'affinity',
|
||||||
|
'$form_security_token' => get_form_security_token("affinity"),
|
||||||
|
'$title' => t('Affinity Tool Settings'),
|
||||||
|
'$content' => $content,
|
||||||
|
'$baseurl' => z_root(),
|
||||||
|
'$submit' => t('Submit'),
|
||||||
|
));
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -90,12 +90,12 @@ class Appman extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
if(argc() > 2) {
|
if(argc() > 3) {
|
||||||
if(argv(2) === 'moveup') {
|
if(argv(2) === 'moveup') {
|
||||||
Zlib\Apps::moveup(local_channel(),argv(1));
|
Zlib\Apps::moveup(local_channel(),argv(1),argv(3));
|
||||||
}
|
}
|
||||||
if(argv(2) === 'movedown') {
|
if(argv(2) === 'movedown') {
|
||||||
Zlib\Apps::movedown(local_channel(),argv(1));
|
Zlib\Apps::movedown(local_channel(),argv(1),argv(3));
|
||||||
}
|
}
|
||||||
goaway(z_root() . '/apporder');
|
goaway(z_root() . '/apporder');
|
||||||
}
|
}
|
||||||
@@ -113,10 +113,12 @@ class Appman extends \Zotlabs\Web\Controller {
|
|||||||
if($r) {
|
if($r) {
|
||||||
$app = $r[0];
|
$app = $r[0];
|
||||||
|
|
||||||
$term = q("select * from term where otype = %d and oid = %d",
|
$term = q("select * from term where otype = %d and oid = %d and uid = %d",
|
||||||
intval(TERM_OBJ_APP),
|
intval(TERM_OBJ_APP),
|
||||||
intval($r[0]['id'])
|
intval($r[0]['id']),
|
||||||
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
|
|
||||||
if($term) {
|
if($term) {
|
||||||
$app['categories'] = '';
|
$app['categories'] = '';
|
||||||
foreach($term as $t) {
|
foreach($term as $t) {
|
||||||
|
|||||||
+18
-15
@@ -17,25 +17,28 @@ class Apporder extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
nav_set_selected('Order Apps');
|
nav_set_selected('Order Apps');
|
||||||
|
|
||||||
$syslist = array();
|
foreach( [ 'nav_featured_app', 'nav_pinned_app' ] as $l ) {
|
||||||
$list = Zlib\Apps::app_list(local_channel(), false, ['nav_featured_app', 'nav_pinned_app']);
|
$syslist = [];
|
||||||
if($list) {
|
$list = Zlib\Apps::app_list(local_channel(), false, [ $l ]);
|
||||||
foreach($list as $li) {
|
if($list) {
|
||||||
$syslist[] = Zlib\Apps::app_encode($li);
|
foreach($list as $li) {
|
||||||
|
$syslist[] = Zlib\Apps::app_encode($li);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Zlib\Apps::translate_system_apps($syslist);
|
Zlib\Apps::translate_system_apps($syslist);
|
||||||
|
|
||||||
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
|
usort($syslist,'Zotlabs\\Lib\\Apps::app_name_compare');
|
||||||
|
|
||||||
$syslist = Zlib\Apps::app_order(local_channel(),$syslist);
|
$syslist = Zlib\Apps::app_order(local_channel(),$syslist, $l);
|
||||||
|
|
||||||
foreach($syslist as $app) {
|
foreach($syslist as $app) {
|
||||||
if(strpos($app['categories'],'nav_pinned_app') !== false) {
|
if($l === 'nav_pinned_app') {
|
||||||
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
$navbar_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||||
}
|
}
|
||||||
else {
|
elseif(strpos($app['categories'],'nav_pinned_app') === false) {
|
||||||
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
$nav_apps[] = Zlib\Apps::app_render($app,'nav-order');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,11 +47,11 @@ class Apps extends \Zotlabs\Web\Controller {
|
|||||||
return replace_macros(get_markup_template('myapps.tpl'), array(
|
return replace_macros(get_markup_template('myapps.tpl'), array(
|
||||||
'$sitename' => get_config('system','sitename'),
|
'$sitename' => get_config('system','sitename'),
|
||||||
'$cat' => $cat,
|
'$cat' => $cat,
|
||||||
'$title' => t('Apps'),
|
'$title' => (($available) ? t('Available Apps') : t('Installed Apps')),
|
||||||
'$apps' => $apps,
|
'$apps' => $apps,
|
||||||
'$authed' => ((local_channel()) ? true : false),
|
'$authed' => ((local_channel()) ? true : false),
|
||||||
'$manage' => (($available) ? '' : t('Manage apps')),
|
'$manage' => (($available) ? '' : t('Manage Apps')),
|
||||||
'$create' => (($mode == 'edit') ? t('Create new app') : '')
|
'$create' => (($mode == 'edit') ? t('Create Custom App') : '')
|
||||||
));
|
));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
|
||||||
|
class Apschema extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
$base = z_root();
|
||||||
|
|
||||||
|
$arr = [
|
||||||
|
'@context' => [
|
||||||
|
'zot' => z_root() . '/apschema#',
|
||||||
|
'id' => '@id',
|
||||||
|
'type' => '@type',
|
||||||
|
'commentPolicy' => 'as:commentPolicy',
|
||||||
|
'meData' => 'zot:meData',
|
||||||
|
'meDataType' => 'zot:meDataType',
|
||||||
|
'meEncoding' => 'zot:meEncoding',
|
||||||
|
'meAlgorithm' => 'zot:meAlgorithm',
|
||||||
|
'meCreator' => 'zot:meCreator',
|
||||||
|
'meSignatureValue' => 'zot:meSignatureValue',
|
||||||
|
'locationAddress' => 'zot:locationAddress',
|
||||||
|
'locationPrimary' => 'zot:locationPrimary',
|
||||||
|
'locationDeleted' => 'zot:locationDeleted',
|
||||||
|
'nomadicLocation' => 'zot:nomadicLocation',
|
||||||
|
'nomadicHubs' => 'zot:nomadicHubs',
|
||||||
|
'emojiReaction' => 'zot:emojiReaction',
|
||||||
|
'expires' => 'zot:expires',
|
||||||
|
'directMessage' => 'zot:directMessage',
|
||||||
|
|
||||||
|
'magicEnv' => [
|
||||||
|
'@id' => 'zot:magicEnv',
|
||||||
|
'@type' => '@id'
|
||||||
|
],
|
||||||
|
|
||||||
|
'nomadicLocations' => [
|
||||||
|
'@id' => 'zot:nomadicLocations',
|
||||||
|
'@type' => '@id'
|
||||||
|
],
|
||||||
|
|
||||||
|
'ostatus' => 'http://ostatus.org#',
|
||||||
|
'conversation' => 'ostatus:conversation',
|
||||||
|
|
||||||
|
'diaspora' => 'https://diasporafoundation.org/ns/',
|
||||||
|
'guid' => 'diaspora:guid',
|
||||||
|
|
||||||
|
'Hashtag' => 'as:Hashtag'
|
||||||
|
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
header('Content-Type: application/ld+json');
|
||||||
|
echo json_encode($arr,JSON_UNESCAPED_SLASHES);
|
||||||
|
killme();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -85,10 +85,9 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$mimetype = $itm[0]['mimetype'];
|
$mimetype = $itm[0]['mimetype'];
|
||||||
|
|
||||||
|
$summary = (($itm[0]['summary']) ? '[summary]' . $itm[0]['summary'] . '[/summary]' . "\r\n" : '');
|
||||||
$content = $itm[0]['body'];
|
$content = $itm[0]['body'];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$rp = 'articles/' . $channel['channel_address'];
|
$rp = 'articles/' . $channel['channel_address'];
|
||||||
|
|
||||||
$x = array(
|
$x = array(
|
||||||
@@ -110,7 +109,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
|||||||
'ptyp' => $itm[0]['type'],
|
'ptyp' => $itm[0]['type'],
|
||||||
'mimeselect' => false,
|
'mimeselect' => false,
|
||||||
'mimetype' => $itm[0]['mimetype'],
|
'mimetype' => $itm[0]['mimetype'],
|
||||||
'body' => undo_post_tagging($content),
|
'body' => $summary . undo_post_tagging($content),
|
||||||
'post_id' => $post_id,
|
'post_id' => $post_id,
|
||||||
'visitor' => true,
|
'visitor' => true,
|
||||||
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
'title' => htmlspecialchars($itm[0]['title'],ENT_COMPAT,'UTF-8'),
|
||||||
@@ -122,7 +121,7 @@ class Article_edit extends \Zotlabs\Web\Controller {
|
|||||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Article_edit');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit Article'),
|
'$title' => t('Edit Article'),
|
||||||
|
|||||||
+59
-24
@@ -1,19 +1,33 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\PermissionDescription;
|
||||||
|
|
||||||
require_once('include/channel.php');
|
require_once('include/channel.php');
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
require_once('include/acl_selectors.php');
|
require_once('include/acl_selectors.php');
|
||||||
|
require_once('include/opengraph.php');
|
||||||
|
|
||||||
|
|
||||||
class Articles extends \Zotlabs\Web\Controller {
|
class Articles extends Controller {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
if(argc() > 1)
|
if(argc() > 1)
|
||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
else
|
|
||||||
return;
|
if(! $which) {
|
||||||
|
if(local_channel()) {
|
||||||
|
$channel = App::get_channel();
|
||||||
|
if($channel && $channel['channel_address'])
|
||||||
|
$which = $channel['channel_address'];
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
profile_load($which);
|
profile_load($which);
|
||||||
|
|
||||||
@@ -25,22 +39,27 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
return login();
|
return login();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! \App::$profile) {
|
if(! App::$profile) {
|
||||||
notice( t('Requested profile is not available.') . EOL );
|
notice( t('Requested profile is not available.') . EOL );
|
||||||
\App::$error = 404;
|
App::$error = 404;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! feature_enabled(\App::$profile_uid,'articles')) {
|
if(! Apps::system_app_installed(App::$profile_uid, 'Articles')) {
|
||||||
return;
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Articles App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Create interactive articles');
|
||||||
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav_set_selected(t('Articles'));
|
nav_set_selected('Articles');
|
||||||
|
|
||||||
head_add_link([
|
head_add_link([
|
||||||
'rel' => 'alternate',
|
'rel' => 'alternate',
|
||||||
'type' => 'application/json+oembed',
|
'type' => 'application/json+oembed',
|
||||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
|
||||||
'title' => 'oembed'
|
'title' => 'oembed'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -48,19 +67,21 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
||||||
|
|
||||||
if($category) {
|
if($category) {
|
||||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
|
||||||
|
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
|
||||||
|
|
||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
|
|
||||||
$selected_card = ((argc() > 2) ? argv(2) : '');
|
$selected_card = ((argc() > 2) ? argv(2) : '');
|
||||||
|
|
||||||
$_SESSION['return_url'] = \App::$query_string;
|
$_SESSION['return_url'] = App::$query_string;
|
||||||
|
|
||||||
$uid = local_channel();
|
$uid = local_channel();
|
||||||
$owner = \App::$profile_uid;
|
$owner = App::$profile_uid;
|
||||||
$observer = \App::get_observer();
|
$observer = App::get_observer();
|
||||||
|
|
||||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||||
|
|
||||||
@@ -98,7 +119,7 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||||
\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
||||||
'permissions' => $channel_acl,
|
'permissions' => $channel_acl,
|
||||||
'showacl' => (($is_owner) ? true : false),
|
'showacl' => (($is_owner) ? true : false),
|
||||||
'visitor' => true,
|
'visitor' => true,
|
||||||
@@ -120,7 +141,7 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
$x['title'] = $_REQUEST['title'];
|
$x['title'] = $_REQUEST['title'];
|
||||||
if($_REQUEST['body'])
|
if($_REQUEST['body'])
|
||||||
$x['body'] = $_REQUEST['body'];
|
$x['body'] = $_REQUEST['body'];
|
||||||
$editor = status_editor($a,$x);
|
$editor = status_editor($a,$x,false,'Articles');
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -128,8 +149,8 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||||
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||||
|
|
||||||
|
|
||||||
$sql_extra = item_permissions_sql($owner);
|
$sql_extra = item_permissions_sql($owner);
|
||||||
@@ -143,10 +164,21 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
|
$sql_item = "and item.id = " . intval($r[0]['iid']) . " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if($datequery) {
|
||||||
|
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created <= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery))));
|
||||||
|
$order = 'post';
|
||||||
|
}
|
||||||
|
if($datequery2) {
|
||||||
|
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if($datequery || $datequery2) {
|
||||||
|
$sql_extra2 .= " and item.item_thread_top != 0 ";
|
||||||
|
}
|
||||||
|
|
||||||
$r = q("select * from item
|
$r = q("select * from item
|
||||||
where item.uid = %d and item_type = %d
|
where item.uid = %d and item_type = %d
|
||||||
$sql_extra $sql_item order by item.created desc $pager_sql",
|
$sql_extra $sql_extra2 $sql_item order by item.created desc $pager_sql",
|
||||||
intval($owner),
|
intval($owner),
|
||||||
intval(ITEM_TYPE_ARTICLE)
|
intval(ITEM_TYPE_ARTICLE)
|
||||||
);
|
);
|
||||||
@@ -161,23 +193,26 @@ class Articles extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$parents_str = ids_to_querystr($r,'id');
|
$parents_str = ids_to_querystr($r,'id');
|
||||||
|
|
||||||
$items = q("SELECT item.*, item.id AS item_id
|
$r = q("SELECT item.*, item.id AS item_id
|
||||||
FROM item
|
FROM item
|
||||||
WHERE item.uid = %d $item_normal
|
WHERE item.uid = %d $item_normal
|
||||||
AND item.parent IN ( %s )
|
AND item.parent IN ( %s )
|
||||||
$sql_extra $sql_extra2 ",
|
$sql_extra $sql_extra2 ",
|
||||||
intval(\App::$profile['profile_uid']),
|
intval(App::$profile['profile_uid']),
|
||||||
dbesc($parents_str)
|
dbesc($parents_str)
|
||||||
);
|
);
|
||||||
if($items) {
|
if($r) {
|
||||||
xchan_query($items);
|
xchan_query($r);
|
||||||
$items = fetch_post_tags($items, true);
|
$items = fetch_post_tags($r, true);
|
||||||
$items = conv_sort($items,'updated');
|
$items = conv_sort($items,'updated');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$items = [];
|
$items = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add Opengraph markup
|
||||||
|
opengraph_add_meta((! empty($items) ? $r[0] : []), $channel);
|
||||||
|
|
||||||
$mode = 'articles';
|
$mode = 'articles';
|
||||||
|
|
||||||
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
|
if(get_pconfig(local_channel(),'system','articles_list_mode') && (! $selected_card))
|
||||||
|
|||||||
@@ -7,27 +7,34 @@ use Zotlabs\Identity\OAuth2Storage;
|
|||||||
class Authorize extends \Zotlabs\Web\Controller {
|
class Authorize extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
if (!local_channel()) {
|
if (! local_channel()) {
|
||||||
return login();
|
return login();
|
||||||
} else {
|
}
|
||||||
// TODO: Fully implement the dynamic client registration protocol:
|
else {
|
||||||
// OpenID Connect Dynamic Client Registration 1.0 Client Metadata
|
|
||||||
// http://openid.net/specs/openid-connect-registration-1_0.html
|
$name = $_REQUEST['client_name'];
|
||||||
$app = array(
|
if(! $name) {
|
||||||
'name' => (x($_REQUEST, 'client_name') ? urldecode($_REQUEST['client_name']) : t('Unknown App')),
|
$name = (($_REQUEST['client_id']) ?: t('Unknown App'));
|
||||||
'icon' => (x($_REQUEST, 'logo_uri') ? urldecode($_REQUEST['logo_uri']) : z_root() . '/images/icons/plugin.png'),
|
}
|
||||||
'url' => (x($_REQUEST, 'client_uri') ? urldecode($_REQUEST['client_uri']) : ''),
|
|
||||||
);
|
$app = [
|
||||||
$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), array(
|
'name' => $name,
|
||||||
'$title' => t('Authorize'),
|
'icon' => (x($_REQUEST, 'logo_uri') ? $_REQUEST['logo_uri'] : z_root() . '/images/icons/plugin.png'),
|
||||||
'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), '<a style="float: none;" href="' . $app['url'] . '">' . $app['name'] . '</a> '),
|
'url' => (x($_REQUEST, 'client_uri') ? $_REQUEST['client_uri'] : ''),
|
||||||
'$app' => $app,
|
];
|
||||||
'$yes' => t('Allow'),
|
|
||||||
'$no' => t('Deny'),
|
$link = (($app['url']) ? '<a style="float: none;" href="' . $app['url'] . '">' . $app['name'] . '</a> ' : $app['name']);
|
||||||
'$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''),
|
|
||||||
|
$o .= replace_macros(get_markup_template('oauth_authorize.tpl'), [
|
||||||
|
'$title' => t('Authorize'),
|
||||||
|
'$authorize' => sprintf( t('Do you authorize the app %s to access your channel data?'), $link ),
|
||||||
|
'$app' => $app,
|
||||||
|
'$yes' => t('Allow'),
|
||||||
|
'$no' => t('Deny'),
|
||||||
|
'$client_id' => (x($_REQUEST, 'client_id') ? $_REQUEST['client_id'] : ''),
|
||||||
'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
|
'$redirect_uri' => (x($_REQUEST, 'redirect_uri') ? $_REQUEST['redirect_uri'] : ''),
|
||||||
'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
|
'$state' => (x($_REQUEST, 'state') ? $_REQUEST['state'] : ''),
|
||||||
));
|
]);
|
||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,13 +67,16 @@ class Authorize extends \Zotlabs\Web\Controller {
|
|||||||
$request = \OAuth2\Request::createFromGlobals();
|
$request = \OAuth2\Request::createFromGlobals();
|
||||||
$response = new \OAuth2\Response();
|
$response = new \OAuth2\Response();
|
||||||
|
|
||||||
|
// Note, "sub" field must match type and content. $user_id is used to populate - make sure it's a string.
|
||||||
|
$channel = channelx_by_n(local_channel());
|
||||||
|
$user_id = $channel['channel_id'];
|
||||||
|
|
||||||
// If the client is not registered, add to the database
|
// If the client is not registered, add to the database
|
||||||
if (!$client = $storage->getClientDetails($client_id)) {
|
if (!$client = $storage->getClientDetails($client_id)) {
|
||||||
$client_secret = random_string(16);
|
// Until "Dynamic Client Registration" is pursued - allow new clients to assign their own secret in the REQUEST
|
||||||
|
$client_secret = (isset($_REQUEST['client_secret'])) ? $_REQUEST['client_secret'] : random_string(16);
|
||||||
// Client apps are registered per channel
|
// Client apps are registered per channel
|
||||||
$user_id = local_channel();
|
$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', $_REQUEST['scope'], $user_id);
|
||||||
$storage->setClientDetails($client_id, $client_secret, $redirect_uri, 'authorization_code', null, $user_id);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!$client = $storage->getClientDetails($client_id)) {
|
if (!$client = $storage->getClientDetails($client_id)) {
|
||||||
// There was an error registering the client.
|
// There was an error registering the client.
|
||||||
@@ -83,7 +93,7 @@ class Authorize extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
// print the authorization code if the user has authorized your client
|
// print the authorization code if the user has authorized your client
|
||||||
$is_authorized = ($_POST['authorize'] === 'allow');
|
$is_authorized = ($_POST['authorize'] === 'allow');
|
||||||
$s->handleAuthorizeRequest($request, $response, $is_authorized, local_channel());
|
$s->handleAuthorizeRequest($request, $response, $is_authorized, $user_id);
|
||||||
if ($is_authorized) {
|
if ($is_authorized) {
|
||||||
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
|
$code = substr($response->getHttpHeader('Location'), strpos($response->getHttpHeader('Location'), 'code=') + 5, 40);
|
||||||
logger('Authorization Code: ' . $code);
|
logger('Authorization Code: ' . $code);
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class Blocks extends \Zotlabs\Web\Controller {
|
|||||||
if($_REQUEST['pagetitle'])
|
if($_REQUEST['pagetitle'])
|
||||||
$x['pagetitle'] = $_REQUEST['pagetitle'];
|
$x['pagetitle'] = $_REQUEST['pagetitle'];
|
||||||
|
|
||||||
$editor = status_editor($a,$x);
|
$editor = status_editor($a,$x,false,'Blocks');
|
||||||
|
|
||||||
|
|
||||||
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
|
$r = q("select iconfig.iid, iconfig.k, iconfig.v, mid, title, body, mimetype, created, edited from iconfig
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
|
||||||
|
|
||||||
class Bookmarks extends \Zotlabs\Web\Controller {
|
class Bookmarks extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
@@ -8,7 +11,10 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
|||||||
if(! local_channel())
|
if(! local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nav_set_selected('View Bookmarks');
|
if(! Apps::system_app_installed(local_channel(), 'Bookmarks'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
nav_set_selected('Bookmarks');
|
||||||
|
|
||||||
$item_id = intval($_REQUEST['item']);
|
$item_id = intval($_REQUEST['item']);
|
||||||
$burl = trim($_REQUEST['burl']);
|
$burl = trim($_REQUEST['burl']);
|
||||||
@@ -59,19 +65,26 @@ class Bookmarks extends \Zotlabs\Web\Controller {
|
|||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
if(! local_channel()) {
|
if(! local_channel()) {
|
||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Bookmarks')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Bookmarks App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Bookmark links from posts and manage them');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
require_once('include/menu.php');
|
require_once('include/menu.php');
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
//$o = profile_tabs($a,true,$channel['channel_address']);
|
|
||||||
$o = '';
|
$o = '';
|
||||||
|
|
||||||
$o .= '<div class="generic-content-wrapper-styled">';
|
$o .= '<div class="generic-content-wrapper-styled">';
|
||||||
|
|||||||
+149
-292
@@ -1,22 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
require_once('include/bbcode.php');
|
require_once('include/bbcode.php');
|
||||||
require_once('include/datetime.php');
|
require_once('include/datetime.php');
|
||||||
require_once('include/event.php');
|
require_once('include/event.php');
|
||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
|
require_once('include/html2plain.php');
|
||||||
|
|
||||||
|
|
||||||
class Cal extends \Zotlabs\Web\Controller {
|
class Cal extends Controller {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if(observer_prohibited()) {
|
if(observer_prohibited()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$o = '';
|
|
||||||
|
|
||||||
if(argc() > 1) {
|
if(argc() > 1) {
|
||||||
$nick = argv(1);
|
$nick = argv(1);
|
||||||
|
|
||||||
@@ -24,19 +27,21 @@ class Cal extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$channelx = channelx_by_nick($nick);
|
$channelx = channelx_by_nick($nick);
|
||||||
|
|
||||||
if(! $channelx)
|
if(! $channelx) {
|
||||||
|
notice( t('Channel not found.') . EOL);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
\App::$data['channel'] = $channelx;
|
App::$data['channel'] = $channelx;
|
||||||
|
|
||||||
$observer = \App::get_observer();
|
$observer = App::get_observer();
|
||||||
\App::$data['observer'] = $observer;
|
App::$data['observer'] = $observer;
|
||||||
|
|
||||||
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
|
$observer_xchan = (($observer) ? $observer['xchan_hash'] : '');
|
||||||
|
|
||||||
head_set_icon(\App::$data['channel']['xchan_photo_s']);
|
head_set_icon(App::$data['channel']['xchan_photo_s']);
|
||||||
|
|
||||||
\App::$page['htmlhead'] .= "<script> var profile_uid = " . ((\App::$data['channel']) ? \App::$data['channel']['channel_id'] : 0) . "; </script>" ;
|
App::$page['htmlhead'] .= "<script> var profile_uid = " . ((App::$data['channel']) ? App::$data['channel']['channel_id'] : 0) . "; </script>" ;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,18 +56,8 @@ class Cal extends \Zotlabs\Web\Controller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel = null;
|
$channel = App::$data['channel'];
|
||||||
|
|
||||||
if(argc() > 1) {
|
|
||||||
$channel = channelx_by_nick(argv(1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(! $channel) {
|
|
||||||
notice( t('Channel not found.') . EOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// since we don't currently have an event permission - use the stream permission
|
// since we don't currently have an event permission - use the stream permission
|
||||||
|
|
||||||
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
|
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_stream')) {
|
||||||
@@ -71,290 +66,152 @@ class Cal extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
nav_set_selected('Calendar');
|
nav_set_selected('Calendar');
|
||||||
|
|
||||||
|
head_add_css('/library/fullcalendar/packages/core/main.min.css');
|
||||||
|
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
|
||||||
|
head_add_css('cdav_calendar.css');
|
||||||
|
|
||||||
|
head_add_js('/library/fullcalendar/packages/core/main.min.js');
|
||||||
|
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
|
||||||
|
|
||||||
|
$sql_extra = permissions_sql($channel['channel_id'], get_observer_hash(), 'event');
|
||||||
|
|
||||||
|
if(! perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts') || App::$profile['hide_friends'])
|
||||||
|
$sql_extra .= " and etype != 'birthday' ";
|
||||||
|
|
||||||
$sql_extra = permissions_sql($channel['channel_id'],get_observer_hash(),'event');
|
$first_day = feature_enabled($channel['channel_id'], 'cal_first_day');
|
||||||
|
|
||||||
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
|
|
||||||
$first_day = (($first_day) ? $first_day : 0);
|
$first_day = (($first_day) ? $first_day : 0);
|
||||||
|
|
||||||
$htpl = get_markup_template('event_head.tpl');
|
$start = '';
|
||||||
\App::$page['htmlhead'] .= replace_macros($htpl,array(
|
$finish = '';
|
||||||
'$baseurl' => z_root(),
|
|
||||||
'$module_url' => '/cal/' . $channel['channel_address'],
|
if (argv(2) === 'json') {
|
||||||
'$modparams' => 2,
|
if (x($_GET,'start')) $start = $_GET['start'];
|
||||||
'$lang' => \App::$language,
|
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||||
'$first_day' => $first_day
|
|
||||||
));
|
|
||||||
|
|
||||||
$o = '';
|
|
||||||
|
|
||||||
//$tabs = profile_tabs($a, True, $channel['channel_address']);
|
|
||||||
$tabs = '';
|
|
||||||
|
|
||||||
$mode = 'view';
|
|
||||||
$y = 0;
|
|
||||||
$m = 0;
|
|
||||||
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
|
|
||||||
|
|
||||||
// logger('args: ' . print_r(\App::$argv,true));
|
|
||||||
|
|
||||||
if(argc() > 3 && intval(argv(2)) && intval(argv(3))) {
|
|
||||||
$mode = 'view';
|
|
||||||
$y = intval(argv(2));
|
|
||||||
$m = intval(argv(3));
|
|
||||||
}
|
|
||||||
if(argc() <= 3) {
|
|
||||||
$mode = 'view';
|
|
||||||
$event_id = argv(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($mode == 'view') {
|
$start = datetime_convert('UTC','UTC',$start);
|
||||||
|
$finish = datetime_convert('UTC','UTC',$finish);
|
||||||
/* edit/create form */
|
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||||
if($event_id) {
|
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
||||||
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
|
||||||
dbesc($event_id),
|
|
||||||
intval($channel['channel_id'])
|
|
||||||
);
|
|
||||||
if(count($r))
|
|
||||||
$orig_event = $r[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Passed parameters overrides anything found in the DB
|
|
||||||
if(!x($orig_event))
|
|
||||||
$orig_event = array();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$tz = date_default_timezone_get();
|
|
||||||
if(x($orig_event))
|
|
||||||
$tz = (($orig_event['adjust']) ? date_default_timezone_get() : 'UTC');
|
|
||||||
|
|
||||||
$syear = datetime_convert('UTC', $tz, $sdt, 'Y');
|
|
||||||
$smonth = datetime_convert('UTC', $tz, $sdt, 'm');
|
|
||||||
$sday = datetime_convert('UTC', $tz, $sdt, 'd');
|
|
||||||
$shour = datetime_convert('UTC', $tz, $sdt, 'H');
|
|
||||||
$sminute = datetime_convert('UTC', $tz, $sdt, 'i');
|
|
||||||
|
|
||||||
$stext = datetime_convert('UTC',$tz,$sdt);
|
|
||||||
$stext = substr($stext,0,14) . "00:00";
|
|
||||||
|
|
||||||
$fyear = datetime_convert('UTC', $tz, $fdt, 'Y');
|
|
||||||
$fmonth = datetime_convert('UTC', $tz, $fdt, 'm');
|
|
||||||
$fday = datetime_convert('UTC', $tz, $fdt, 'd');
|
|
||||||
$fhour = datetime_convert('UTC', $tz, $fdt, 'H');
|
|
||||||
$fminute = datetime_convert('UTC', $tz, $fdt, 'i');
|
|
||||||
|
|
||||||
$ftext = datetime_convert('UTC',$tz,$fdt);
|
|
||||||
$ftext = substr($ftext,0,14) . "00:00";
|
|
||||||
|
|
||||||
$type = ((x($orig_event)) ? $orig_event['etype'] : 'event');
|
|
||||||
|
|
||||||
$f = get_config('system','event_input_format');
|
|
||||||
if(! $f)
|
|
||||||
$f = 'ymd';
|
|
||||||
|
|
||||||
$catsenabled = feature_enabled($channel['channel_id'],'categories');
|
|
||||||
|
|
||||||
|
|
||||||
$show_bd = perm_is_allowed($channel['channel_id'], get_observer_hash(), 'view_contacts');
|
|
||||||
if(! $show_bd) {
|
|
||||||
$sql_extra .= " and event.etype != 'birthday' ";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$category = '';
|
|
||||||
|
|
||||||
$thisyear = datetime_convert('UTC',date_default_timezone_get(),'now','Y');
|
|
||||||
$thismonth = datetime_convert('UTC',date_default_timezone_get(),'now','m');
|
|
||||||
if(! $y)
|
|
||||||
$y = intval($thisyear);
|
|
||||||
if(! $m)
|
|
||||||
$m = intval($thismonth);
|
|
||||||
|
|
||||||
// Put some limits on dates. The PHP date functions don't seem to do so well before 1900.
|
|
||||||
// An upper limit was chosen to keep search engines from exploring links millions of years in the future.
|
|
||||||
|
|
||||||
if($y < 1901)
|
|
||||||
$y = 1900;
|
|
||||||
if($y > 2099)
|
|
||||||
$y = 2100;
|
|
||||||
|
|
||||||
$nextyear = $y;
|
|
||||||
$nextmonth = $m + 1;
|
|
||||||
if($nextmonth > 12) {
|
|
||||||
$nextmonth = 1;
|
|
||||||
$nextyear ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
$prevyear = $y;
|
|
||||||
if($m > 1)
|
|
||||||
$prevmonth = $m - 1;
|
|
||||||
else {
|
|
||||||
$prevmonth = 12;
|
|
||||||
$prevyear --;
|
|
||||||
}
|
|
||||||
|
|
||||||
$dim = get_dim($y,$m);
|
|
||||||
$start = sprintf('%d-%d-%d %d:%d:%d',$y,$m,1,0,0,0);
|
|
||||||
$finish = sprintf('%d-%d-%d %d:%d:%d',$y,$m,$dim,23,59,59);
|
|
||||||
|
|
||||||
|
|
||||||
if (argv(2) === 'json'){
|
|
||||||
if (x($_GET,'start')) $start = $_GET['start'];
|
|
||||||
if (x($_GET,'end')) $finish = $_GET['end'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$start = datetime_convert('UTC','UTC',$start);
|
|
||||||
$finish = datetime_convert('UTC','UTC',$finish);
|
|
||||||
|
|
||||||
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
|
||||||
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
|
||||||
|
|
||||||
|
|
||||||
if(! perm_is_allowed(\App::$profile['uid'],get_observer_hash(),'view_contacts'))
|
if (x($_GET, 'id')) {
|
||||||
$sql_extra .= " and etype != 'birthday' ";
|
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||||
|
from event left join item on item.resource_id = event.event_hash
|
||||||
|
where item.resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
|
||||||
|
intval($channel['channel_id']),
|
||||||
|
intval($_GET['id'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// fixed an issue with "nofinish" events not showing up in the calendar.
|
||||||
|
// There's still an issue if the finish date crosses the end of month.
|
||||||
|
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||||
|
// Ultimately the finish date shouldn't be involved in the query.
|
||||||
|
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||||
|
from event left join item on event.event_hash = item.resource_id
|
||||||
|
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid
|
||||||
|
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||||
|
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' ))
|
||||||
|
$sql_extra",
|
||||||
|
intval($channel['channel_id']),
|
||||||
|
dbesc($start),
|
||||||
|
dbesc($finish),
|
||||||
|
dbesc($adjust_start),
|
||||||
|
dbesc($adjust_finish)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
xchan_query($r);
|
||||||
|
$r = fetch_post_tags($r,true);
|
||||||
|
$r = sort_by_date($r);
|
||||||
|
}
|
||||||
|
|
||||||
if (x($_GET,'id')){
|
$events = [];
|
||||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
|
|
||||||
from event left join item on resource_id = event_hash where resource_type = 'event' and event.uid = %d and event.id = %d $sql_extra limit 1",
|
|
||||||
intval($channel['channel_id']),
|
|
||||||
intval($_GET['id'])
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// fixed an issue with "nofinish" events not showing up in the calendar.
|
|
||||||
// There's still an issue if the finish date crosses the end of month.
|
|
||||||
// Noting this for now - it will need to be fixed here and in Friendica.
|
|
||||||
// Ultimately the finish date shouldn't be involved in the query.
|
|
||||||
|
|
||||||
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan
|
if($r) {
|
||||||
from event left join item on event_hash = resource_id
|
|
||||||
where resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
|
foreach($r as $rr) {
|
||||||
AND (( adjust = 0 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )
|
|
||||||
OR ( adjust = 1 AND ( dtend >= '%s' or nofinish = 1 ) AND dtstart <= '%s' )) $sql_extra ",
|
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||||
intval($channel['channel_id']),
|
if(! $tz)
|
||||||
dbesc($start),
|
$tz = 'UTC';
|
||||||
dbesc($finish),
|
|
||||||
dbesc($adjust_start),
|
$start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||||
dbesc($adjust_finish)
|
if ($rr['nofinish']){
|
||||||
);
|
$end = null;
|
||||||
|
} else {
|
||||||
}
|
$end = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||||
|
|
||||||
$links = array();
|
|
||||||
|
|
||||||
if($r) {
|
|
||||||
xchan_query($r);
|
|
||||||
$r = fetch_post_tags($r,true);
|
|
||||||
|
|
||||||
$r = sort_by_date($r);
|
|
||||||
}
|
|
||||||
|
|
||||||
if($r) {
|
|
||||||
foreach($r as $rr) {
|
|
||||||
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
|
|
||||||
if(! x($links,$j))
|
|
||||||
$links[$j] = z_root() . '/' . \App::$cmd . '#link-' . $j;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
$html = '';
|
||||||
$events=array();
|
if (x($_GET,'id')) {
|
||||||
|
$rr['timezone'] = $tz;
|
||||||
$last_date = '';
|
|
||||||
$fmt = t('l, F j');
|
|
||||||
|
|
||||||
if($r) {
|
|
||||||
|
|
||||||
foreach($r as $rr) {
|
|
||||||
|
|
||||||
$j = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'j') : datetime_convert('UTC','UTC',$rr['dtstart'],'j'));
|
|
||||||
$d = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], $fmt) : datetime_convert('UTC','UTC',$rr['dtstart'],$fmt));
|
|
||||||
$d = day_translate($d);
|
|
||||||
|
|
||||||
$start = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtstart'], 'c') : datetime_convert('UTC','UTC',$rr['dtstart'],'c'));
|
|
||||||
if ($rr['nofinish']){
|
|
||||||
$end = null;
|
|
||||||
} else {
|
|
||||||
$end = (($rr['adjust']) ? datetime_convert('UTC',date_default_timezone_get(),$rr['dtend'], 'c') : datetime_convert('UTC','UTC',$rr['dtend'],'c'));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$is_first = ($d !== $last_date);
|
|
||||||
|
|
||||||
$last_date = $d;
|
|
||||||
|
|
||||||
$edit = false;
|
|
||||||
|
|
||||||
$drop = false;
|
|
||||||
|
|
||||||
$title = strip_tags(html_entity_decode(bbcode($rr['summary']),ENT_QUOTES,'UTF-8'));
|
|
||||||
if(! $title) {
|
|
||||||
list($title, $_trash) = explode("<br",bbcode($rr['desc']),2);
|
|
||||||
$title = strip_tags(html_entity_decode($title,ENT_QUOTES,'UTF-8'));
|
|
||||||
}
|
|
||||||
$html = format_event_html($rr);
|
$html = format_event_html($rr);
|
||||||
$rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
|
|
||||||
$rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
|
|
||||||
$events[] = array(
|
|
||||||
'id'=>$rr['id'],
|
|
||||||
'hash' => $rr['event_hash'],
|
|
||||||
'start'=> $start,
|
|
||||||
'end' => $end,
|
|
||||||
'drop' => $drop,
|
|
||||||
'allDay' => false,
|
|
||||||
'title' => $title,
|
|
||||||
|
|
||||||
'j' => $j,
|
|
||||||
'd' => $d,
|
|
||||||
'edit' => $edit,
|
|
||||||
'is_first'=>$is_first,
|
|
||||||
'item'=>$rr,
|
|
||||||
'html'=>$html,
|
|
||||||
'plink' => array($rr['plink'],t('Link to Source'),'',''),
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$events[] = array(
|
||||||
|
'calendar_id' => 'channel_calendar',
|
||||||
|
'rw' => true,
|
||||||
|
'id'=>$rr['id'],
|
||||||
|
'uri' => $rr['event_hash'],
|
||||||
|
'timezone' => $tz,
|
||||||
|
'start'=> $start,
|
||||||
|
'end' => $end,
|
||||||
|
'drop' => $drop,
|
||||||
|
'allDay' => (($rr['adjust']) ? 0 : 1),
|
||||||
|
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'editable' => $edit ? true : false,
|
||||||
|
'item' => $rr,
|
||||||
|
'plink' => [$rr['plink'], t('Link to source')],
|
||||||
|
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'allow_cid' => expand_acl($rr['allow_cid']),
|
||||||
|
'allow_gid' => expand_acl($rr['allow_gid']),
|
||||||
|
'deny_cid' => expand_acl($rr['deny_cid']),
|
||||||
|
'deny_gid' => expand_acl($rr['deny_gid']),
|
||||||
|
'html' => $html
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argv(2) === 'json'){
|
|
||||||
echo json_encode($events); killme();
|
|
||||||
}
|
|
||||||
|
|
||||||
// links: array('href', 'text', 'extra css classes', 'title')
|
|
||||||
if (x($_GET,'id')){
|
|
||||||
$tpl = get_markup_template("event_cal.tpl");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$tpl = get_markup_template("events_cal-js.tpl");
|
|
||||||
}
|
|
||||||
|
|
||||||
$nick = $channel['channel_address'];
|
|
||||||
|
|
||||||
$o = replace_macros($tpl, array(
|
|
||||||
'$baseurl' => z_root(),
|
|
||||||
'$new_event' => array(z_root().'/cal',(($event_id) ? t('Edit Event') : t('Create Event')),'',''),
|
|
||||||
'$previus' => array(z_root()."/cal/$nick/$prevyear/$prevmonth",t('Previous'),'',''),
|
|
||||||
'$next' => array(z_root()."/cal/$nick/$nextyear/$nextmonth",t('Next'),'',''),
|
|
||||||
'$export' => array(z_root()."/cal/$nick/$y/$m/export",t('Export'),'',''),
|
|
||||||
'$calendar' => cal($y,$m,$links, ' eventcal'),
|
|
||||||
'$events' => $events,
|
|
||||||
'$upload' => t('Import'),
|
|
||||||
'$submit' => t('Submit'),
|
|
||||||
'$prev' => t('Previous'),
|
|
||||||
'$next' => t('Next'),
|
|
||||||
'$today' => t('Today'),
|
|
||||||
'$form' => $form,
|
|
||||||
'$expandform' => ((x($_GET,'expandform')) ? true : false),
|
|
||||||
'$tabs' => $tabs
|
|
||||||
));
|
|
||||||
|
|
||||||
if (x($_GET,'id')){ echo $o; killme(); }
|
|
||||||
|
|
||||||
return $o;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argv(2) === 'json') {
|
||||||
|
echo json_encode($events);
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x($_GET,'id')) {
|
||||||
|
$o = replace_macros(get_markup_template("cal_event.tpl"), [
|
||||||
|
'$events' => $events
|
||||||
|
]);
|
||||||
|
echo $o;
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
$nick = $channel['channel_address'];
|
||||||
|
|
||||||
|
$sources = '{
|
||||||
|
id: \'channel_calendar\',
|
||||||
|
url: \'/cal/' . $nick . '/json/\',
|
||||||
|
color: \'#3a87ad\'
|
||||||
|
}';
|
||||||
|
|
||||||
|
$o = replace_macros(get_markup_template("cal_calendar.tpl"), [
|
||||||
|
'$sources' => $sources,
|
||||||
|
'$lang' => App::$language,
|
||||||
|
'$timezone' => date_default_timezone_get(),
|
||||||
|
'$first_day' => $first_day,
|
||||||
|
'$prev' => t('Previous'),
|
||||||
|
'$next' => t('Next'),
|
||||||
|
'$today' => t('Today'),
|
||||||
|
'$title' => $title,
|
||||||
|
'$dtstart' => $dtstart,
|
||||||
|
'$dtend' => $dtend,
|
||||||
|
'$nick' => $nick
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $o;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ class Card_edit extends \Zotlabs\Web\Controller {
|
|||||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Card_edit');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit Card'),
|
'$title' => t('Edit Card'),
|
||||||
|
|||||||
+35
-22
@@ -1,14 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\PermissionDescription;
|
||||||
|
|
||||||
require_once('include/channel.php');
|
require_once('include/channel.php');
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
require_once('include/acl_selectors.php');
|
require_once('include/acl_selectors.php');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Provides the Cards module.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class Cards extends Controller {
|
||||||
|
|
||||||
class Cards extends \Zotlabs\Web\Controller {
|
public function init() {
|
||||||
|
|
||||||
function init() {
|
|
||||||
|
|
||||||
if(argc() > 1)
|
if(argc() > 1)
|
||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
@@ -16,35 +24,41 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
profile_load($which);
|
profile_load($which);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
* @see \Zotlabs\Web\Controller::get()
|
* @see \\Zotlabs\\Web\\Controller::get()
|
||||||
|
*
|
||||||
|
* @return string Parsed HTML from template 'cards.tpl'
|
||||||
*/
|
*/
|
||||||
function get($update = 0, $load = false) {
|
public function get($update = 0, $load = false) {
|
||||||
|
|
||||||
if(observer_prohibited(true)) {
|
if(observer_prohibited(true)) {
|
||||||
return login();
|
return login();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! \App::$profile) {
|
if(! App::$profile) {
|
||||||
notice( t('Requested profile is not available.') . EOL );
|
notice( t('Requested profile is not available.') . EOL );
|
||||||
\App::$error = 404;
|
App::$error = 404;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! feature_enabled(\App::$profile_uid, 'cards')) {
|
if(! Apps::system_app_installed(App::$profile_uid, 'Cards')) {
|
||||||
return;
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Cards App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Create personal planning cards');
|
||||||
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav_set_selected(t('Cards'));
|
nav_set_selected('Cards');
|
||||||
|
|
||||||
head_add_link([
|
head_add_link([
|
||||||
'rel' => 'alternate',
|
'rel' => 'alternate',
|
||||||
'type' => 'application/json+oembed',
|
'type' => 'application/json+oembed',
|
||||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
|
||||||
'title' => 'oembed'
|
'title' => 'oembed'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -52,7 +66,7 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
$category = (($_REQUEST['cat']) ? escape_tags(trim($_REQUEST['cat'])) : '');
|
||||||
|
|
||||||
if($category) {
|
if($category) {
|
||||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
|
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'], 'item', $category, TERM_CATEGORY));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -60,11 +74,11 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$selected_card = ((argc() > 2) ? argv(2) : '');
|
$selected_card = ((argc() > 2) ? argv(2) : '');
|
||||||
|
|
||||||
$_SESSION['return_url'] = \App::$query_string;
|
$_SESSION['return_url'] = App::$query_string;
|
||||||
|
|
||||||
$uid = local_channel();
|
$uid = local_channel();
|
||||||
$owner = \App::$profile_uid;
|
$owner = App::$profile_uid;
|
||||||
$observer = \App::get_observer();
|
$observer = App::get_observer();
|
||||||
|
|
||||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||||
|
|
||||||
@@ -90,7 +104,6 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(perm_is_allowed($owner, $ob_hash, 'write_pages')) {
|
if(perm_is_allowed($owner, $ob_hash, 'write_pages')) {
|
||||||
|
|
||||||
$x = [
|
$x = [
|
||||||
@@ -102,7 +115,7 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
'lockstate' => (($channel['channel_allow_cid'] || $channel['channel_allow_gid']
|
||||||
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
|| $channel['channel_deny_cid'] || $channel['channel_deny_gid']) ? 'lock' : 'unlock'),
|
||||||
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
'acl' => (($is_owner) ? populate_acl($channel_acl, false,
|
||||||
\Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
PermissionDescription::fromGlobalPermission('view_pages')) : ''),
|
||||||
'permissions' => $channel_acl,
|
'permissions' => $channel_acl,
|
||||||
'showacl' => (($is_owner) ? true : false),
|
'showacl' => (($is_owner) ? true : false),
|
||||||
'visitor' => true,
|
'visitor' => true,
|
||||||
@@ -124,7 +137,7 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
if($_REQUEST['body'])
|
if($_REQUEST['body'])
|
||||||
$x['body'] = $_REQUEST['body'];
|
$x['body'] = $_REQUEST['body'];
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Cards');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$editor = '';
|
$editor = '';
|
||||||
@@ -132,8 +145,8 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||||
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||||
|
|
||||||
|
|
||||||
$sql_extra = item_permissions_sql($owner);
|
$sql_extra = item_permissions_sql($owner);
|
||||||
@@ -171,7 +184,7 @@ class Cards extends \Zotlabs\Web\Controller {
|
|||||||
WHERE item.uid = %d $item_normal
|
WHERE item.uid = %d $item_normal
|
||||||
AND item.parent IN ( %s )
|
AND item.parent IN ( %s )
|
||||||
$sql_extra $sql_extra2 ",
|
$sql_extra $sql_extra2 ",
|
||||||
intval(\App::$profile['profile_uid']),
|
intval(App::$profile['profile_uid']),
|
||||||
dbesc($parents_str)
|
dbesc($parents_str)
|
||||||
);
|
);
|
||||||
if($items) {
|
if($items) {
|
||||||
|
|||||||
+262
-58
@@ -1,12 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
require_once('include/event.php');
|
require_once('include/event.php');
|
||||||
|
|
||||||
require_once('include/auth.php');
|
require_once('include/auth.php');
|
||||||
require_once('include/security.php');
|
require_once('include/security.php');
|
||||||
|
|
||||||
class Cdav extends \Zotlabs\Web\Controller {
|
class Cdav extends Controller {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
@@ -37,7 +42,7 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||||
if($sigblock) {
|
if($sigblock) {
|
||||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||||
if($keyId) {
|
if($keyId) {
|
||||||
@@ -60,7 +65,7 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if($record) {
|
if($record) {
|
||||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
$verified = HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||||
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
||||||
$record = null;
|
$record = null;
|
||||||
}
|
}
|
||||||
@@ -126,8 +131,14 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV');
|
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . 'CalDAV/CardDAV');
|
||||||
|
|
||||||
if (local_channel()) {
|
if (local_channel()) {
|
||||||
|
|
||||||
logger('loggedin');
|
logger('loggedin');
|
||||||
$channel = \App::get_channel();
|
|
||||||
|
if((argv(1) == 'addressbooks') && (!Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = App::get_channel();
|
||||||
$auth->setCurrentUser($channel['channel_address']);
|
$auth->setCurrentUser($channel['channel_address']);
|
||||||
$auth->channel_id = $channel['channel_id'];
|
$auth->channel_id = $channel['channel_id'];
|
||||||
$auth->channel_hash = $channel['channel_hash'];
|
$auth->channel_hash = $channel['channel_hash'];
|
||||||
@@ -161,12 +172,15 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
$nodes = [
|
$nodes = [
|
||||||
// /principals
|
// /principals
|
||||||
new \Sabre\CalDAV\Principal\Collection($principalBackend),
|
new \Sabre\CalDAV\Principal\Collection($principalBackend),
|
||||||
|
|
||||||
// /calendars
|
// /calendars
|
||||||
new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend),
|
new \Sabre\CalDAV\CalendarRoot($principalBackend, $caldavBackend),
|
||||||
|
|
||||||
// /addressbook
|
// /addressbook
|
||||||
new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend),
|
new \Sabre\CardDAV\AddressBookRoot($principalBackend, $carddavBackend)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
// The object tree needs in turn to be passed to the server class
|
// The object tree needs in turn to be passed to the server class
|
||||||
|
|
||||||
$server = new \Sabre\DAV\Server($nodes);
|
$server = new \Sabre\DAV\Server($nodes);
|
||||||
@@ -204,7 +218,11 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if(! local_channel())
|
if(! local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = App::get_channel();
|
||||||
$principalUri = 'principals/' . $channel['channel_address'];
|
$principalUri = 'principals/' . $channel['channel_address'];
|
||||||
|
|
||||||
if(!cdav_principal($principalUri))
|
if(!cdav_principal($principalUri))
|
||||||
@@ -254,10 +272,19 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if(!cdav_perms($id[0],$calendars,true))
|
if(!cdav_perms($id[0],$calendars,true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||||
|
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||||
|
|
||||||
|
$allday = $_REQUEST['allday'];
|
||||||
|
|
||||||
$title = $_REQUEST['title'];
|
$title = $_REQUEST['title'];
|
||||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||||
if($_REQUEST['dtend'])
|
$dtstart = new \DateTime($start);
|
||||||
$dtend = new \DateTime($_REQUEST['dtend']);
|
|
||||||
|
if($_REQUEST['dtend']) {
|
||||||
|
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||||
|
$dtend = new \DateTime($end);
|
||||||
|
}
|
||||||
$description = $_REQUEST['description'];
|
$description = $_REQUEST['description'];
|
||||||
$location = $_REQUEST['location'];
|
$location = $_REQUEST['location'];
|
||||||
|
|
||||||
@@ -281,13 +308,24 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
'DTSTART' => $dtstart
|
'DTSTART' => $dtstart
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
if($dtend)
|
|
||||||
|
if($dtend) {
|
||||||
$vcalendar->VEVENT->add('DTEND', $dtend);
|
$vcalendar->VEVENT->add('DTEND', $dtend);
|
||||||
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||||
|
}
|
||||||
if($description)
|
if($description)
|
||||||
$vcalendar->VEVENT->add('DESCRIPTION', $description);
|
$vcalendar->VEVENT->add('DESCRIPTION', $description);
|
||||||
if($location)
|
if($location)
|
||||||
$vcalendar->VEVENT->add('LOCATION', $location);
|
$vcalendar->VEVENT->add('LOCATION', $location);
|
||||||
|
|
||||||
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||||
|
|
||||||
$calendarData = $vcalendar->serialize();
|
$calendarData = $vcalendar->serialize();
|
||||||
|
|
||||||
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
$caldavBackend->createCalendarObject($id, $objectUri, $calendarData);
|
||||||
@@ -324,10 +362,19 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if(!cdav_perms($id[0],$calendars,true))
|
if(!cdav_perms($id[0],$calendars,true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||||
|
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||||
|
|
||||||
|
$allday = $_REQUEST['allday'];
|
||||||
|
|
||||||
$uri = $_REQUEST['uri'];
|
$uri = $_REQUEST['uri'];
|
||||||
$title = $_REQUEST['title'];
|
$title = $_REQUEST['title'];
|
||||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||||
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
|
$dtstart = new \DateTime($start);
|
||||||
|
if($_REQUEST['dtend']) {
|
||||||
|
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||||
|
$dtend = new \DateTime($end);
|
||||||
|
}
|
||||||
$description = $_REQUEST['description'];
|
$description = $_REQUEST['description'];
|
||||||
$location = $_REQUEST['location'];
|
$location = $_REQUEST['location'];
|
||||||
|
|
||||||
@@ -337,12 +384,23 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if($title)
|
if($title)
|
||||||
$vcalendar->VEVENT->SUMMARY = $title;
|
$vcalendar->VEVENT->SUMMARY = $title;
|
||||||
if($dtstart)
|
if($dtstart) {
|
||||||
$vcalendar->VEVENT->DTSTART = $dtstart;
|
$vcalendar->VEVENT->DTSTART = $dtstart;
|
||||||
if($dtend)
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||||
|
}
|
||||||
|
if($dtend) {
|
||||||
$vcalendar->VEVENT->DTEND = $dtend;
|
$vcalendar->VEVENT->DTEND = $dtend;
|
||||||
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
unset($vcalendar->VEVENT->DTEND);
|
unset($vcalendar->VEVENT->DTEND);
|
||||||
|
|
||||||
if($description)
|
if($description)
|
||||||
$vcalendar->VEVENT->DESCRIPTION = $description;
|
$vcalendar->VEVENT->DESCRIPTION = $description;
|
||||||
if($location)
|
if($location)
|
||||||
@@ -378,9 +436,18 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if(!cdav_perms($id[0],$calendars,true))
|
if(!cdav_perms($id[0],$calendars,true))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||||
|
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||||
|
|
||||||
|
$allday = $_REQUEST['allday'];
|
||||||
|
|
||||||
$uri = $_REQUEST['uri'];
|
$uri = $_REQUEST['uri'];
|
||||||
$dtstart = new \DateTime($_REQUEST['dtstart']);
|
$start = datetime_convert('UTC', 'UTC', $_REQUEST['dtstart']);
|
||||||
$dtend = $_REQUEST['dtend'] ? new \DateTime($_REQUEST['dtend']) : '';
|
$dtstart = new \DateTime($start);
|
||||||
|
if($_REQUEST['dtend']) {
|
||||||
|
$end = datetime_convert('UTC', 'UTC', $_REQUEST['dtend']);
|
||||||
|
$dtend = new \DateTime($end);
|
||||||
|
}
|
||||||
|
|
||||||
$object = $caldavBackend->getCalendarObject($id, $uri);
|
$object = $caldavBackend->getCalendarObject($id, $uri);
|
||||||
|
|
||||||
@@ -388,13 +455,20 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if($dtstart) {
|
if($dtstart) {
|
||||||
$vcalendar->VEVENT->DTSTART = $dtstart;
|
$vcalendar->VEVENT->DTSTART = $dtstart;
|
||||||
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTSTART['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTSTART['TZID'] = $tz;
|
||||||
}
|
}
|
||||||
if($dtend) {
|
if($dtend) {
|
||||||
$vcalendar->VEVENT->DTEND = $dtend;
|
$vcalendar->VEVENT->DTEND = $dtend;
|
||||||
|
if($allday)
|
||||||
|
$vcalendar->VEVENT->DTEND['VALUE'] = 'DATE';
|
||||||
|
else
|
||||||
|
$vcalendar->VEVENT->DTEND['TZID'] = $tz;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
unset($vcalendar->VEVENT->DTEND);
|
unset($vcalendar->VEVENT->DTEND);
|
||||||
}
|
|
||||||
|
|
||||||
$calendarData = $vcalendar->serialize();
|
$calendarData = $vcalendar->serialize();
|
||||||
|
|
||||||
@@ -722,16 +796,27 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
//Import calendar or addressbook
|
//Import calendar or addressbook
|
||||||
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) {
|
if(($_FILES) && array_key_exists('userfile',$_FILES) && intval($_FILES['userfile']['size']) && $_REQUEST['target']) {
|
||||||
|
|
||||||
$src = @file_get_contents($_FILES['userfile']['tmp_name']);
|
$src = $_FILES['userfile']['tmp_name'];
|
||||||
|
|
||||||
if($src) {
|
if($src) {
|
||||||
|
|
||||||
if($_REQUEST['c_upload']) {
|
if($_REQUEST['c_upload']) {
|
||||||
|
if($_REQUEST['target'] == 'channel_calendar') {
|
||||||
|
$result = parse_ical_file($src,local_channel());
|
||||||
|
if($result)
|
||||||
|
info( t('Calendar entries imported.') . EOL);
|
||||||
|
else
|
||||||
|
notice( t('No calendar entries found.') . EOL);
|
||||||
|
|
||||||
|
@unlink($src);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$id = explode(':', $_REQUEST['target']);
|
$id = explode(':', $_REQUEST['target']);
|
||||||
$ext = 'ics';
|
$ext = 'ics';
|
||||||
$table = 'calendarobjects';
|
$table = 'calendarobjects';
|
||||||
$column = 'calendarid';
|
$column = 'calendarid';
|
||||||
$objects = new \Sabre\VObject\Splitter\ICalendar($src);
|
$objects = new \Sabre\VObject\Splitter\ICalendar(@file_get_contents($src));
|
||||||
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
|
$profile = \Sabre\VObject\Node::PROFILE_CALDAV;
|
||||||
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
$backend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||||
}
|
}
|
||||||
@@ -741,7 +826,7 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
$ext = 'vcf';
|
$ext = 'vcf';
|
||||||
$table = 'cards';
|
$table = 'cards';
|
||||||
$column = 'addressbookid';
|
$column = 'addressbookid';
|
||||||
$objects = new \Sabre\VObject\Splitter\VCard($src);
|
$objects = new \Sabre\VObject\Splitter\VCard(@file_get_contents($src));
|
||||||
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
$profile = \Sabre\VObject\Node::PROFILE_CARDDAV;
|
||||||
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
$backend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||||
}
|
}
|
||||||
@@ -807,15 +892,24 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if(!local_channel())
|
if(!local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
if((argv(1) === 'addressbook') && (! Apps::system_app_installed(local_channel(), 'CardDAV'))) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('CardDAV App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('CalDAV capable addressbook');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
|
App::$profile_uid = local_channel();
|
||||||
|
|
||||||
|
$channel = App::get_channel();
|
||||||
$principalUri = 'principals/' . $channel['channel_address'];
|
$principalUri = 'principals/' . $channel['channel_address'];
|
||||||
|
|
||||||
$pdo = \DBA::$dba->db;
|
$pdo = \DBA::$dba->db;
|
||||||
|
|
||||||
require_once 'vendor/autoload.php';
|
require_once 'vendor/autoload.php';
|
||||||
|
|
||||||
head_add_css('cdav.css');
|
|
||||||
|
|
||||||
if(!cdav_principal($principalUri)) {
|
if(!cdav_principal($principalUri)) {
|
||||||
$this->activate($pdo, $channel);
|
$this->activate($pdo, $channel);
|
||||||
if(!cdav_principal($principalUri)) {
|
if(!cdav_principal($principalUri)) {
|
||||||
@@ -824,28 +918,98 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(argv(1) === 'calendar') {
|
if(argv(1) === 'calendar') {
|
||||||
nav_set_selected('CalDAV');
|
nav_set_selected('Calendar');
|
||||||
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||||
$calendars = $caldavBackend->getCalendarsForUser($principalUri);
|
$calendars = $caldavBackend->getCalendarsForUser($principalUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Display calendar(s) here
|
//Display calendar(s) here
|
||||||
if(argc() == 2 && argv(1) === 'calendar') {
|
if(argc() <= 3 && argv(1) === 'calendar') {
|
||||||
|
|
||||||
head_add_css('/library/fullcalendar/fullcalendar.css');
|
head_add_css('/library/fullcalendar/packages/core/main.min.css');
|
||||||
|
head_add_css('/library/fullcalendar/packages/daygrid/main.min.css');
|
||||||
|
head_add_css('/library/fullcalendar/packages/timegrid/main.min.css');
|
||||||
|
head_add_css('/library/fullcalendar/packages/list/main.min.css');
|
||||||
head_add_css('cdav_calendar.css');
|
head_add_css('cdav_calendar.css');
|
||||||
|
|
||||||
head_add_js('/library/moment/moment.min.js', 1);
|
head_add_js('/library/fullcalendar/packages/core/main.min.js');
|
||||||
head_add_js('/library/fullcalendar/fullcalendar.min.js', 1);
|
head_add_js('/library/fullcalendar/packages/interaction/main.min.js');
|
||||||
head_add_js('/library/fullcalendar/locale-all.js', 1);
|
head_add_js('/library/fullcalendar/packages/daygrid/main.min.js');
|
||||||
|
head_add_js('/library/fullcalendar/packages/timegrid/main.min.js');
|
||||||
|
head_add_js('/library/fullcalendar/packages/list/main.min.js');
|
||||||
|
|
||||||
|
$sources = '';
|
||||||
|
$resource_id = '';
|
||||||
|
$resource = null;
|
||||||
|
|
||||||
|
if(argc() == 3)
|
||||||
|
$resource_id = argv(2);
|
||||||
|
|
||||||
|
if($resource_id) {
|
||||||
|
$r = q("SELECT event.*, item.author_xchan, item.owner_xchan, item.plink, item.id as item_id FROM event LEFT JOIN item ON event.event_hash = item.resource_id
|
||||||
|
WHERE event.uid = %d AND event.event_hash = '%s' LIMIT 1",
|
||||||
|
intval(local_channel()),
|
||||||
|
dbesc($resource_id)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
xchan_query($r);
|
||||||
|
$r = fetch_post_tags($r,true);
|
||||||
|
|
||||||
|
$tz = get_iconfig($r[0], 'event', 'timezone');
|
||||||
|
if(! $tz)
|
||||||
|
$tz = 'UTC';
|
||||||
|
|
||||||
|
$r[0]['timezone'] = $tz;
|
||||||
|
$r[0]['dtstart'] = (($r[0]['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $r[0]['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $r[0]['dtstart'], 'c'));
|
||||||
|
$r[0]['dtend'] = (($r[0]['adjust']) ? datetime_convert('UTC', date_default_timezone_get(), $r[0]['dtend'], 'c') : datetime_convert('UTC', 'UTC' ,$r[0]['dtend'], 'c'));
|
||||||
|
|
||||||
|
$r[0]['plink'] = [$r[0]['plink'], t('Link to source')];
|
||||||
|
|
||||||
|
$resource = $r[0];
|
||||||
|
|
||||||
|
$catsenabled = feature_enabled(local_channel(),'categories');
|
||||||
|
$categories = '';
|
||||||
|
if($catsenabled){
|
||||||
|
if($r[0]['term']) {
|
||||||
|
$cats = get_terms_oftype($r[0]['term'], TERM_CATEGORY);
|
||||||
|
foreach ($cats as $cat) {
|
||||||
|
if(strlen($categories))
|
||||||
|
$categories .= ', ';
|
||||||
|
$categories .= $cat['term'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($r[0]['dismissed'] == 0) {
|
||||||
|
q("UPDATE event SET dismissed = 1 WHERE event.uid = %d AND event.event_hash = '%s'",
|
||||||
|
intval(local_channel()),
|
||||||
|
dbesc($resource_id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(get_pconfig(local_channel(), 'cdav_calendar', 'channel_calendar')) {
|
||||||
|
$sources .= '{
|
||||||
|
id: \'channel_calendar\',
|
||||||
|
url: \'/channel_calendar/json/\',
|
||||||
|
color: \'#3a87ad\'
|
||||||
|
}, ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel_calendars[] = [
|
||||||
|
'displayname' => $channel['channel_name'],
|
||||||
|
'id' => 'channel_calendar'
|
||||||
|
];
|
||||||
|
|
||||||
foreach($calendars as $calendar) {
|
foreach($calendars as $calendar) {
|
||||||
$editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
|
$editable = (($calendar['share-access'] == 2) ? 'false' : 'true'); // false/true must be string since we're passing it to javascript
|
||||||
$color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#3a87ad');
|
$color = (($calendar['{http://apple.com/ns/ical/}calendar-color']) ? $calendar['{http://apple.com/ns/ical/}calendar-color'] : '#6cad39');
|
||||||
$sharer = (($calendar['share-access'] == 3) ? $calendar['{urn:ietf:params:xml:ns:caldav}calendar-description'] : '');
|
$sharer = (($calendar['share-access'] == 3) ? $calendar['{urn:ietf:params:xml:ns:caldav}calendar-description'] : '');
|
||||||
$switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]);
|
$switch = get_pconfig(local_channel(), 'cdav_calendar', $calendar['id'][0]);
|
||||||
if($switch) {
|
if($switch) {
|
||||||
$sources .= '{
|
$sources .= '{
|
||||||
|
id: ' . $calendar['id'][0] . ',
|
||||||
url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\',
|
url: \'/cdav/calendar/json/' . $calendar['id'][0] . '/' . $calendar['id'][1] . '\',
|
||||||
color: \'' . $color . '\'
|
color: \'' . $color . '\'
|
||||||
}, ';
|
}, ';
|
||||||
@@ -862,19 +1026,34 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$sources = rtrim($sources, ', ');
|
$sources = rtrim($sources, ', ');
|
||||||
|
|
||||||
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
|
$first_day = feature_enabled(local_channel(), 'cal_first_day');
|
||||||
$first_day = (($first_day) ? $first_day : 0);
|
$first_day = (($first_day) ? $first_day : 0);
|
||||||
|
|
||||||
$title = ['title', t('Event title')];
|
$title = ['title', t('Event title') ];
|
||||||
$dtstart = ['dtstart', t('Start date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
|
$dtstart = ['dtstart', t('Start date and time')];
|
||||||
$dtend = ['dtend', t('End date and time'), '', t('Example: YYYY-MM-DD HH:mm')];
|
$dtend = ['dtend', t('End date and time')];
|
||||||
|
$timezone_select = ['timezone_select' , t('Timezone:'), date_default_timezone_get(), '', get_timezones()];
|
||||||
|
|
||||||
$description = ['description', t('Description')];
|
$description = ['description', t('Description')];
|
||||||
$location = ['location', t('Location')];
|
$location = ['location', t('Location')];
|
||||||
|
|
||||||
|
$catsenabled = feature_enabled(local_channel(), 'categories');
|
||||||
|
|
||||||
|
require_once('include/acl_selectors.php');
|
||||||
|
|
||||||
|
$accesslist = new \Zotlabs\Access\AccessList($channel);
|
||||||
|
$perm_defaults = $accesslist->get();
|
||||||
|
|
||||||
|
//$acl = (($orig_event['event_xchan']) ? '' : populate_acl(((x($orig_event)) ? $orig_event : $perm_defaults), false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream')));
|
||||||
|
$acl = populate_acl($perm_defaults, false, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'));
|
||||||
|
|
||||||
|
$permissions = (($resource_id) ? $resource : $perm_defaults);
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [
|
$o .= replace_macros(get_markup_template('cdav_calendar.tpl'), [
|
||||||
'$sources' => $sources,
|
'$sources' => $sources,
|
||||||
'$color' => $color,
|
'$color' => $color,
|
||||||
'$lang' => \App::$language,
|
'$lang' => App::$language,
|
||||||
|
'$timezone' => date_default_timezone_get(),
|
||||||
'$first_day' => $first_day,
|
'$first_day' => $first_day,
|
||||||
'$prev' => t('Previous'),
|
'$prev' => t('Previous'),
|
||||||
'$next' => t('Next'),
|
'$next' => t('Next'),
|
||||||
@@ -886,6 +1065,7 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
'$list_week' => t('List week'),
|
'$list_week' => t('List week'),
|
||||||
'$list_day' => t('List day'),
|
'$list_day' => t('List day'),
|
||||||
'$title' => $title,
|
'$title' => $title,
|
||||||
|
'$channel_calendars' => $channel_calendars,
|
||||||
'$writable_calendars' => $writable_calendars,
|
'$writable_calendars' => $writable_calendars,
|
||||||
'$dtstart' => $dtstart,
|
'$dtstart' => $dtstart,
|
||||||
'$dtend' => $dtend,
|
'$dtend' => $dtend,
|
||||||
@@ -893,11 +1073,28 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
'$location' => $location,
|
'$location' => $location,
|
||||||
'$more' => t('More'),
|
'$more' => t('More'),
|
||||||
'$less' => t('Less'),
|
'$less' => t('Less'),
|
||||||
|
'$update' => t('Update'),
|
||||||
'$calendar_select_label' => t('Select calendar'),
|
'$calendar_select_label' => t('Select calendar'),
|
||||||
|
'$calendar_optiopns_label' => [t('Channel Calendars'), t('CalDAV Calendars')],
|
||||||
'$delete' => t('Delete'),
|
'$delete' => t('Delete'),
|
||||||
'$delete_all' => t('Delete all'),
|
'$delete_all' => t('Delete all'),
|
||||||
'$cancel' => t('Cancel'),
|
'$cancel' => t('Cancel'),
|
||||||
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.')
|
'$create' => t('Create'),
|
||||||
|
'$recurrence_warning' => t('Sorry! Editing of recurrent events is not yet implemented.'),
|
||||||
|
|
||||||
|
'$channel_hash' => $channel['channel_hash'],
|
||||||
|
'$acl' => $acl,
|
||||||
|
'$lockstate' => (($accesslist->is_private()) ? 'lock' : 'unlock'),
|
||||||
|
'$allow_cid' => acl2json($permissions['allow_cid']),
|
||||||
|
'$allow_gid' => acl2json($permissions['allow_gid']),
|
||||||
|
'$deny_cid' => acl2json($permissions['deny_cid']),
|
||||||
|
'$deny_gid' => acl2json($permissions['deny_gid']),
|
||||||
|
'$catsenabled' => $catsenabled,
|
||||||
|
'$categories_label' => t('Categories'),
|
||||||
|
|
||||||
|
'$resource' => json_encode($resource),
|
||||||
|
'$categories' => $categories,
|
||||||
|
'$timezone_select' => ((feature_enabled(local_channel(),'event_tz_select')) ? $timezone_select : '')
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return $o;
|
return $o;
|
||||||
@@ -907,10 +1104,12 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
//Provide json data for calendar
|
//Provide json data for calendar
|
||||||
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) {
|
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'json' && intval(argv(3)) && intval(argv(4))) {
|
||||||
|
|
||||||
|
$events = [];
|
||||||
|
|
||||||
$id = [argv(3), argv(4)];
|
$id = [argv(3), argv(4)];
|
||||||
|
|
||||||
if(! cdav_perms($id[0],$calendars))
|
if(! cdav_perms($id[0],$calendars))
|
||||||
killme();
|
json_return_and_die($events);
|
||||||
|
|
||||||
if (x($_GET,'start'))
|
if (x($_GET,'start'))
|
||||||
$start = new \DateTime($_GET['start']);
|
$start = new \DateTime($_GET['start']);
|
||||||
@@ -927,13 +1126,16 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
if($uris) {
|
if($uris) {
|
||||||
|
|
||||||
$objects = $caldavBackend->getMultipleCalendarObjects($id, $uris);
|
$objects = $caldavBackend->getMultipleCalendarObjects($id, $uris);
|
||||||
|
|
||||||
foreach($objects as $object) {
|
foreach($objects as $object) {
|
||||||
|
|
||||||
$vcalendar = \Sabre\VObject\Reader::read($object['calendardata']);
|
$vcalendar = \Sabre\VObject\Reader::read($object['calendardata']);
|
||||||
|
|
||||||
if(isset($vcalendar->VEVENT->RRULE))
|
if(isset($vcalendar->VEVENT->RRULE)) {
|
||||||
|
// expanding recurrent events seems to loose timezone info
|
||||||
|
// save it here so we can add it later
|
||||||
|
$recurrent_timezone = (string)$vcalendar->VEVENT->DTSTART['TZID'];
|
||||||
$vcalendar = $vcalendar->expand($start, $end);
|
$vcalendar = $vcalendar->expand($start, $end);
|
||||||
|
}
|
||||||
|
|
||||||
foreach($vcalendar->VEVENT as $vevent) {
|
foreach($vcalendar->VEVENT as $vevent) {
|
||||||
$title = (string)$vevent->SUMMARY;
|
$title = (string)$vevent->SUMMARY;
|
||||||
@@ -941,29 +1143,33 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
$dtend = (string)$vevent->DTEND;
|
$dtend = (string)$vevent->DTEND;
|
||||||
$description = (string)$vevent->DESCRIPTION;
|
$description = (string)$vevent->DESCRIPTION;
|
||||||
$location = (string)$vevent->LOCATION;
|
$location = (string)$vevent->LOCATION;
|
||||||
|
$timezone_str = (string)$vevent->DTSTART['TZID'];
|
||||||
$rw = ((cdav_perms($id[0],$calendars,true)) ? true : false);
|
$rw = ((cdav_perms($id[0],$calendars,true)) ? true : false);
|
||||||
|
$editable = $rw ? true : false;
|
||||||
$recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
|
$recurrent = ((isset($vevent->{'RECURRENCE-ID'})) ? true : false);
|
||||||
|
|
||||||
$editable = $rw ? true : false;
|
if($recurrent) {
|
||||||
|
|
||||||
if($recurrent)
|
|
||||||
$editable = false;
|
$editable = false;
|
||||||
|
$timezone_str = $recurrent_timezone;
|
||||||
|
}
|
||||||
|
|
||||||
$allDay = false;
|
// Try to get an usable olson format timezone
|
||||||
|
$timezone_obj = \Sabre\VObject\TimeZoneUtil::getTimeZone($timezone_str, $vcalendar);
|
||||||
|
$timezone = $timezone_obj->getName();
|
||||||
|
|
||||||
// allDay event rules
|
// If we got nothing fallback to UTC
|
||||||
if(!strpos($dtstart, 'T') && !strpos($dtend, 'T'))
|
if(! $timezone)
|
||||||
$allDay = true;
|
$timezone = 'UTC';
|
||||||
if(strpos($dtstart, 'T000000') && strpos($dtend, 'T000000'))
|
|
||||||
$allDay = true;
|
$allDay = (((string)$vevent->DTSTART['VALUE'] == 'DATE') ? true : false);
|
||||||
|
|
||||||
$events[] = [
|
$events[] = [
|
||||||
'calendar_id' => $id,
|
'calendar_id' => $id,
|
||||||
'uri' => $object['uri'],
|
'uri' => $object['uri'],
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'start' => $dtstart,
|
'timezone' => $timezone,
|
||||||
'end' => $dtend,
|
'start' => datetime_convert($timezone, date_default_timezone_get(), $dtstart, 'c'),
|
||||||
|
'end' => (($dtend) ? datetime_convert($timezone, date_default_timezone_get(), $dtend, 'c') : ''),
|
||||||
'description' => $description,
|
'description' => $description,
|
||||||
'location' => $location,
|
'location' => $location,
|
||||||
'allDay' => $allDay,
|
'allDay' => $allDay,
|
||||||
@@ -973,15 +1179,12 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
json_return_and_die($events);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
killme();
|
|
||||||
}
|
}
|
||||||
|
json_return_and_die($events);
|
||||||
}
|
}
|
||||||
|
|
||||||
//enable/disable calendars
|
//enable/disable calendars
|
||||||
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && intval(argv(3)) && (argv(4) == 1 || argv(4) == 0)) {
|
if(argc() == 5 && argv(1) === 'calendar' && argv(2) === 'switch' && argv(3) && (argv(4) == 1 || argv(4) == 0)) {
|
||||||
$id = argv(3);
|
$id = argv(3);
|
||||||
|
|
||||||
if(! cdav_perms($id,$calendars))
|
if(! cdav_perms($id,$calendars))
|
||||||
@@ -1240,12 +1443,13 @@ class Cdav extends \Zotlabs\Web\Controller {
|
|||||||
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
$caldavBackend = new \Sabre\CalDAV\Backend\PDO($pdo);
|
||||||
$properties = [
|
$properties = [
|
||||||
'{DAV:}displayname' => t('Default Calendar'),
|
'{DAV:}displayname' => t('Default Calendar'),
|
||||||
'{http://apple.com/ns/ical/}calendar-color' => '#3a87ad',
|
'{http://apple.com/ns/ical/}calendar-color' => '#6cad39',
|
||||||
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']
|
'{urn:ietf:params:xml:ns:caldav}calendar-description' => $channel['channel_name']
|
||||||
];
|
];
|
||||||
|
|
||||||
$id = $caldavBackend->createCalendar($uri, 'default', $properties);
|
$id = $caldavBackend->createCalendar($uri, 'default', $properties);
|
||||||
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
set_pconfig(local_channel(), 'cdav_calendar' , $id[0], 1);
|
||||||
|
set_pconfig(local_channel(), 'cdav_calendar' , 'channel_calendar', 1);
|
||||||
|
|
||||||
//create default addressbook
|
//create default addressbook
|
||||||
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
$carddavBackend = new \Sabre\CardDAV\Backend\PDO($pdo);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if($account['account_password_changed'] > NULL_DATE) {
|
if($account['account_password_changed'] > NULL_DATE) {
|
||||||
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
$d1 = datetime_convert('UTC','UTC','now - 48 hours');
|
||||||
if($account['account_password_changed'] > d1) {
|
if($account['account_password_changed'] > $d1) {
|
||||||
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
|
notice( t('Channel name changes are not allowed within 48 hours of changing the account password.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -49,7 +49,7 @@ class Changeaddr extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if(check_webbie(array($new_address)) !== $new_address) {
|
if(check_webbie(array($new_address)) !== $new_address) {
|
||||||
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
|
notice( t('Nickname has unsupported characters or is already being used on this site.') . EOL);
|
||||||
return $ret;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_change_address($channel,$new_address);
|
channel_change_address($channel,$new_address);
|
||||||
|
|||||||
+136
-61
@@ -2,19 +2,26 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
require_once('include/contact_widgets.php');
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\PermissionDescription;
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
use Zotlabs\Lib\Libzot;
|
||||||
|
|
||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
require_once("include/bbcode.php");
|
|
||||||
require_once('include/security.php');
|
require_once('include/security.php');
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
require_once('include/acl_selectors.php');
|
require_once('include/acl_selectors.php');
|
||||||
require_once('include/permissions.php');
|
require_once('include/opengraph.php');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Channel Controller
|
* @brief Channel Controller
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class Channel extends \Zotlabs\Web\Controller {
|
|
||||||
|
class Channel extends Controller {
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
@@ -26,7 +33,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
if(! $which) {
|
if(! $which) {
|
||||||
if(local_channel()) {
|
if(local_channel()) {
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
if($channel && $channel['channel_address'])
|
if($channel && $channel['channel_address'])
|
||||||
$which = $channel['channel_address'];
|
$which = $channel['channel_address'];
|
||||||
}
|
}
|
||||||
@@ -37,7 +44,49 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$profile = 0;
|
$profile = 0;
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
|
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||||
|
$which = $channel['channel_address'];
|
||||||
|
$profile = argv(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = channelx_by_nick($which);
|
||||||
|
if(! $channel) {
|
||||||
|
http_status_exit(404, 'Not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle zot6 channel discovery
|
||||||
|
|
||||||
|
if(Libzot::is_zot_request()) {
|
||||||
|
|
||||||
|
$sigdata = HTTPSig::verify(file_get_contents('php://input'));
|
||||||
|
|
||||||
|
if($sigdata && $sigdata['signer'] && $sigdata['header_valid']) {
|
||||||
|
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'], 'target_url' => $sigdata['signer'] ]));
|
||||||
|
$s = q("select site_crypto, hubloc_sitekey from site left join hubloc on hubloc_url = site_url where hubloc_id_url = '%s' and hubloc_network = 'zot6' limit 1",
|
||||||
|
dbesc($sigdata['signer'])
|
||||||
|
);
|
||||||
|
|
||||||
|
if($s) {
|
||||||
|
$data = json_encode(crypto_encapsulate($data,$s[0]['hubloc_sitekey'],Libzot::best_algorithm($s[0]['site_crypto'])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$data = json_encode(Libzot::zotinfo([ 'address' => $channel['channel_address'] ]));
|
||||||
|
}
|
||||||
|
|
||||||
|
$headers = [
|
||||||
|
'Content-Type' => 'application/x-zot+json',
|
||||||
|
'Digest' => HTTPSig::generate_digest_header($data),
|
||||||
|
'(request-target)' => strtolower($_SERVER['REQUEST_METHOD']) . ' ' . $_SERVER['REQUEST_URI']
|
||||||
|
];
|
||||||
|
$h = HTTPSig::create_sig($headers,$channel['channel_prvkey'],channel_url($channel));
|
||||||
|
HTTPSig::set_headers($h);
|
||||||
|
echo $data;
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||||
$which = $channel['channel_address'];
|
$which = $channel['channel_address'];
|
||||||
@@ -61,21 +110,38 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
// Run profile_load() here to make sure the theme is set before
|
// Run profile_load() here to make sure the theme is set before
|
||||||
// we start loading content
|
// we start loading content
|
||||||
|
|
||||||
profile_load($which,$profile);
|
profile_load($which,$profile);
|
||||||
|
|
||||||
|
// Add Opengraph markup
|
||||||
|
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||||
|
if(strpos($mid,'b64.') === 0)
|
||||||
|
$mid = @base64url_decode(substr($mid,4));
|
||||||
|
|
||||||
|
if($mid)
|
||||||
|
$r = q("SELECT * FROM item WHERE mid = '%s' AND uid = %d AND item_private = 0 LIMIT 1",
|
||||||
|
dbesc($mid),
|
||||||
|
intval($channel['channel_id'])
|
||||||
|
);
|
||||||
|
|
||||||
|
opengraph_add_meta($r ? $r[0] : [], $channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get($update = 0, $load = false) {
|
function get($update = 0, $load = false) {
|
||||||
|
|
||||||
|
$noscript_content = get_config('system', 'noscript_content', '1');
|
||||||
|
|
||||||
if($load)
|
if($load)
|
||||||
$_SESSION['loadtime'] = datetime_convert();
|
$_SESSION['loadtime'] = datetime_convert();
|
||||||
|
|
||||||
$checkjs = new \Zotlabs\Web\CheckJS(1);
|
|
||||||
|
|
||||||
$category = $datequery = $datequery2 = '';
|
$category = $datequery = $datequery2 = '';
|
||||||
|
|
||||||
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
$mid = ((x($_REQUEST,'mid')) ? $_REQUEST['mid'] : '');
|
||||||
|
|
||||||
|
if(strpos($mid,'b64.') === 0)
|
||||||
|
$decoded = @base64url_decode(substr($mid,4));
|
||||||
|
if($decoded)
|
||||||
|
$mid = $decoded;
|
||||||
|
|
||||||
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
|
$datequery = ((x($_GET,'dend') && is_a_date_arg($_GET['dend'])) ? notags($_GET['dend']) : '');
|
||||||
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
|
$datequery2 = ((x($_GET,'dbegin') && is_a_date_arg($_GET['dbegin'])) ? notags($_GET['dbegin']) : '');
|
||||||
|
|
||||||
@@ -95,22 +161,22 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if($update) {
|
if($update) {
|
||||||
// Ensure we've got a profile owner if updating.
|
// Ensure we've got a profile owner if updating.
|
||||||
\App::$profile['profile_uid'] = \App::$profile_uid = $update;
|
App::$profile['profile_uid'] = App::$profile_uid = $update;
|
||||||
}
|
}
|
||||||
|
|
||||||
$is_owner = (((local_channel()) && (\App::$profile['profile_uid'] == local_channel())) ? true : false);
|
$is_owner = (((local_channel()) && (App::$profile['profile_uid'] == local_channel())) ? true : false);
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
$observer = \App::get_observer();
|
$observer = App::get_observer();
|
||||||
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
$ob_hash = (($observer) ? $observer['xchan_hash'] : '');
|
||||||
|
|
||||||
$perms = get_all_perms(\App::$profile['profile_uid'],$ob_hash);
|
$perms = get_all_perms(App::$profile['profile_uid'],$ob_hash);
|
||||||
|
|
||||||
if(! $perms['view_stream']) {
|
if(! $perms['view_stream']) {
|
||||||
// We may want to make the target of this redirect configurable
|
// We may want to make the target of this redirect configurable
|
||||||
if($perms['view_profile']) {
|
if($perms['view_profile']) {
|
||||||
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
|
notice( t('Insufficient permissions. Request redirected to profile page.') . EOL);
|
||||||
goaway (z_root() . "/profile/" . \App::$profile['channel_address']);
|
goaway (z_root() . "/profile/" . App::$profile['channel_address']);
|
||||||
}
|
}
|
||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
@@ -121,7 +187,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
nav_set_selected('Channel Home');
|
nav_set_selected('Channel Home');
|
||||||
|
|
||||||
$static = channel_manual_conv_update(\App::$profile['profile_uid']);
|
$static = channel_manual_conv_update(App::$profile['profile_uid']);
|
||||||
|
|
||||||
// search terms header
|
// search terms header
|
||||||
if($search) {
|
if($search) {
|
||||||
@@ -147,16 +213,16 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$x = array(
|
$x = array(
|
||||||
'is_owner' => $is_owner,
|
'is_owner' => $is_owner,
|
||||||
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(\App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
|
'allow_location' => ((($is_owner || $observer) && (intval(get_pconfig(App::$profile['profile_uid'],'system','use_browser_location')))) ? true : false),
|
||||||
'default_location' => (($is_owner) ? \App::$profile['channel_location'] : ''),
|
'default_location' => (($is_owner) ? App::$profile['channel_location'] : ''),
|
||||||
'nickname' => \App::$profile['channel_address'],
|
'nickname' => App::$profile['channel_address'],
|
||||||
'lockstate' => (((strlen(\App::$profile['channel_allow_cid'])) || (strlen(\App::$profile['channel_allow_gid'])) || (strlen(\App::$profile['channel_deny_cid'])) || (strlen(\App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
|
'lockstate' => (((strlen(App::$profile['channel_allow_cid'])) || (strlen(App::$profile['channel_allow_gid'])) || (strlen(App::$profile['channel_deny_cid'])) || (strlen(App::$profile['channel_deny_gid']))) ? 'lock' : 'unlock'),
|
||||||
'acl' => (($is_owner) ? populate_acl($channel_acl,true, \Zotlabs\Lib\PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
|
'acl' => (($is_owner) ? populate_acl($channel_acl,true, PermissionDescription::fromGlobalPermission('view_stream'), get_post_aclDialogDescription(), 'acl_dialog_post') : ''),
|
||||||
'permissions' => $channel_acl,
|
'permissions' => $channel_acl,
|
||||||
'showacl' => (($is_owner) ? 'yes' : ''),
|
'showacl' => (($is_owner) ? 'yes' : ''),
|
||||||
'bang' => '',
|
'bang' => '',
|
||||||
'visitor' => (($is_owner || $observer) ? true : false),
|
'visitor' => (($is_owner || $observer) ? true : false),
|
||||||
'profile_uid' => \App::$profile['profile_uid'],
|
'profile_uid' => App::$profile['profile_uid'],
|
||||||
'editor_autocomplete' => true,
|
'editor_autocomplete' => true,
|
||||||
'bbco_autocomplete' => 'bbcode',
|
'bbco_autocomplete' => 'bbcode',
|
||||||
'bbcode' => true,
|
'bbcode' => true,
|
||||||
@@ -164,7 +230,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
'reset' => t('Reset form')
|
'reset' => t('Reset form')
|
||||||
);
|
);
|
||||||
|
|
||||||
$o .= status_editor($a,$x);
|
$o .= status_editor($a,$x,false,'Channel');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -176,14 +242,14 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$item_normal = item_normal();
|
$item_normal = item_normal();
|
||||||
$item_normal_update = item_normal_update();
|
$item_normal_update = item_normal_update();
|
||||||
$sql_extra = item_permissions_sql(\App::$profile['profile_uid']);
|
$sql_extra = item_permissions_sql(App::$profile['profile_uid']);
|
||||||
|
|
||||||
if(get_pconfig(\App::$profile['profile_uid'],'system','channel_list_mode') && (! $mid))
|
if(feature_enabled(App::$profile['profile_uid'], 'channel_list_mode') && (! $mid))
|
||||||
$page_mode = 'list';
|
$page_mode = 'list';
|
||||||
else
|
else
|
||||||
$page_mode = 'client';
|
$page_mode = 'client';
|
||||||
|
|
||||||
$abook_uids = " and abook.abook_channel = " . intval(\App::$profile['profile_uid']) . " ";
|
$abook_uids = " and abook.abook_channel = " . intval(App::$profile['profile_uid']) . " ";
|
||||||
|
|
||||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||||
|
|
||||||
@@ -193,7 +259,8 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
$sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
|
$sql_extra .= term_query('item',substr($search,1),TERM_HASHTAG,TERM_COMMUNITYTAG);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$sql_extra .= sprintf(" AND item.body like '%s' ",
|
$sql_extra .= sprintf(" AND (item.body like '%s' OR item.title like '%s') ",
|
||||||
|
dbesc(protect_sprintf('%' . $search . '%')),
|
||||||
dbesc(protect_sprintf('%' . $search . '%'))
|
dbesc(protect_sprintf('%' . $search . '%'))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -203,7 +270,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
head_add_link([
|
head_add_link([
|
||||||
'rel' => 'alternate',
|
'rel' => 'alternate',
|
||||||
'type' => 'application/json+oembed',
|
'type' => 'application/json+oembed',
|
||||||
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . \App::$query_string),
|
'href' => z_root() . '/oep?f=&url=' . urlencode(z_root() . '/' . App::$query_string),
|
||||||
'title' => 'oembed'
|
'title' => 'oembed'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@@ -221,7 +288,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
|
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal_update
|
||||||
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
AND item_wall = 1 $simple_update $sql_extra limit 1",
|
||||||
dbesc($mid . '%'),
|
dbesc($mid . '%'),
|
||||||
intval(\App::$profile['profile_uid'])
|
intval(App::$profile['profile_uid'])
|
||||||
);
|
);
|
||||||
$_SESSION['loadtime'] = datetime_convert();
|
$_SESSION['loadtime'] = datetime_convert();
|
||||||
}
|
}
|
||||||
@@ -233,7 +300,7 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||||
$sql_extra
|
$sql_extra
|
||||||
ORDER BY created DESC",
|
ORDER BY created DESC",
|
||||||
intval(\App::$profile['profile_uid'])
|
intval(App::$profile['profile_uid'])
|
||||||
);
|
);
|
||||||
$_SESSION['loadtime'] = datetime_convert();
|
$_SESSION['loadtime'] = datetime_convert();
|
||||||
}
|
}
|
||||||
@@ -242,10 +309,10 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
if(x($category)) {
|
if(x($category)) {
|
||||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $category, TERM_CATEGORY));
|
||||||
}
|
}
|
||||||
if(x($hashtags)) {
|
if(x($hashtags)) {
|
||||||
$sql_extra2 .= protect_sprintf(term_item_parent_query(\App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
|
$sql_extra2 .= protect_sprintf(term_item_parent_query(App::$profile['profile_uid'],'item', $hashtags, TERM_HASHTAG, TERM_COMMUNITYTAG));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($datequery) {
|
if($datequery) {
|
||||||
@@ -256,10 +323,6 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
|
$sql_extra2 .= protect_sprintf(sprintf(" AND item.created >= '%s' ", dbesc(datetime_convert(date_default_timezone_get(),'',$datequery2))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($datequery || $datequery2) {
|
|
||||||
$sql_extra2 .= " and item.item_thread_top != 0 ";
|
|
||||||
}
|
|
||||||
|
|
||||||
if($order === 'post')
|
if($order === 'post')
|
||||||
$ordering = "created";
|
$ordering = "created";
|
||||||
else
|
else
|
||||||
@@ -267,15 +330,15 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
$itemspage = get_pconfig(local_channel(),'system','itemspage');
|
||||||
\App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
App::set_pager_itemspage(((intval($itemspage)) ? $itemspage : 20));
|
||||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']), intval(\App::$pager['start']));
|
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(App::$pager['itemspage']), intval(App::$pager['start']));
|
||||||
|
|
||||||
if($load || ($checkjs->disabled())) {
|
if($noscript_content || $load) {
|
||||||
if($mid) {
|
if($mid) {
|
||||||
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
|
$r = q("SELECT parent AS item_id from item where mid like '%s' and uid = %d $item_normal
|
||||||
AND item_wall = 1 $sql_extra limit 1",
|
AND item_wall = 1 $sql_extra limit 1",
|
||||||
dbesc($mid . '%'),
|
dbesc($mid . '%'),
|
||||||
intval(\App::$profile['profile_uid'])
|
intval(App::$profile['profile_uid'])
|
||||||
);
|
);
|
||||||
if (! $r) {
|
if (! $r) {
|
||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
@@ -288,8 +351,8 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
AND (abook.abook_blocked = 0 or abook.abook_flags is null)
|
||||||
AND item.item_wall = 1 AND item.item_thread_top = 1
|
AND item.item_wall = 1 AND item.item_thread_top = 1
|
||||||
$sql_extra $sql_extra2
|
$sql_extra $sql_extra2
|
||||||
ORDER BY $ordering DESC $pager_sql ",
|
ORDER BY $ordering DESC, item_id $pager_sql ",
|
||||||
intval(\App::$profile['profile_uid'])
|
intval(App::$profile['profile_uid'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -301,17 +364,17 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$parents_str = ids_to_querystr($r,'item_id');
|
$parents_str = ids_to_querystr($r,'item_id');
|
||||||
|
|
||||||
$items = q("SELECT item.*, item.id AS item_id
|
$r = q("SELECT item.*, item.id AS item_id
|
||||||
FROM item
|
FROM item
|
||||||
WHERE item.uid = %d $item_normal
|
WHERE item.uid = %d $item_normal
|
||||||
AND item.parent IN ( %s )
|
AND item.parent IN ( %s )
|
||||||
$sql_extra ",
|
$sql_extra ",
|
||||||
intval(\App::$profile['profile_uid']),
|
intval(App::$profile['profile_uid']),
|
||||||
dbesc($parents_str)
|
dbesc($parents_str)
|
||||||
);
|
);
|
||||||
|
|
||||||
xchan_query($items);
|
xchan_query($r);
|
||||||
$items = fetch_post_tags($items, true);
|
$items = fetch_post_tags($r, true);
|
||||||
$items = conv_sort($items,$ordering);
|
$items = conv_sort($items,$ordering);
|
||||||
|
|
||||||
if($load && $mid && (! count($items))) {
|
if($load && $mid && (! count($items))) {
|
||||||
@@ -326,22 +389,25 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if((! $update) && (! $load)) {
|
if((! $update) && (! $load)) {
|
||||||
|
|
||||||
|
if($decoded)
|
||||||
|
$mid = 'b64.' . base64url_encode($mid);
|
||||||
|
|
||||||
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
// This is ugly, but we can't pass the profile_uid through the session to the ajax updater,
|
||||||
// because browser prefetching might change it on us. We have to deliver it with the page.
|
// because browser prefetching might change it on us. We have to deliver it with the page.
|
||||||
|
|
||||||
$maxheight = get_pconfig(\App::$profile['profile_uid'],'system','channel_divmore_height');
|
$maxheight = get_pconfig(App::$profile['profile_uid'],'system','channel_divmore_height');
|
||||||
if(! $maxheight)
|
if(! $maxheight)
|
||||||
$maxheight = 400;
|
$maxheight = 400;
|
||||||
|
|
||||||
$o .= '<div id="live-channel"></div>' . "\r\n";
|
$o .= '<div id="live-channel"></div>' . "\r\n";
|
||||||
$o .= "<script> var profile_uid = " . \App::$profile['profile_uid']
|
$o .= "<script> var profile_uid = " . App::$profile['profile_uid']
|
||||||
. "; var netargs = '?f='; var profile_page = " . \App::$pager['page']
|
. "; var netargs = '?f='; var profile_page = " . App::$pager['page']
|
||||||
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
. "; divmore_height = " . intval($maxheight) . "; </script>\r\n";
|
||||||
|
|
||||||
\App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
App::$page['htmlhead'] .= replace_macros(get_markup_template("build_query.tpl"),array(
|
||||||
'$baseurl' => z_root(),
|
'$baseurl' => z_root(),
|
||||||
'$pgtype' => 'channel',
|
'$pgtype' => 'channel',
|
||||||
'$uid' => ((\App::$profile['profile_uid']) ? \App::$profile['profile_uid'] : '0'),
|
'$uid' => ((App::$profile['profile_uid']) ? App::$profile['profile_uid'] : '0'),
|
||||||
'$gid' => '0',
|
'$gid' => '0',
|
||||||
'$cid' => '0',
|
'$cid' => '0',
|
||||||
'$cmin' => '(-1)',
|
'$cmin' => '(-1)',
|
||||||
@@ -354,15 +420,15 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
'$wall' => '1',
|
'$wall' => '1',
|
||||||
'$fh' => '0',
|
'$fh' => '0',
|
||||||
'$static' => $static,
|
'$static' => $static,
|
||||||
'$page' => ((\App::$pager['page'] != 1) ? \App::$pager['page'] : 1),
|
'$page' => ((App::$pager['page'] != 1) ? App::$pager['page'] : 1),
|
||||||
'$search' => $search,
|
'$search' => $search,
|
||||||
'$xchan' => '',
|
'$xchan' => '',
|
||||||
'$order' => $order,
|
'$order' => (($order) ? urlencode($order) : ''),
|
||||||
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
'$list' => ((x($_REQUEST,'list')) ? intval($_REQUEST['list']) : 0),
|
||||||
'$file' => '',
|
'$file' => '',
|
||||||
'$cats' => (($category) ? urlencode($category) : ''),
|
'$cats' => (($category) ? urlencode($category) : ''),
|
||||||
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
'$tags' => (($hashtags) ? urlencode($hashtags) : ''),
|
||||||
'$mid' => $mid,
|
'$mid' => (($mid) ? urlencode($mid) : ''),
|
||||||
'$verb' => '',
|
'$verb' => '',
|
||||||
'$net' => '',
|
'$net' => '',
|
||||||
'$dend' => $datequery,
|
'$dend' => $datequery,
|
||||||
@@ -405,17 +471,26 @@ class Channel extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$mode = (($search) ? 'search' : 'channel');
|
$mode = (($search) ? 'search' : 'channel');
|
||||||
|
|
||||||
if($checkjs->disabled()) {
|
if($update) {
|
||||||
$o .= conversation($items,$mode,$update,'traditional');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$o .= conversation($items,$mode,$update,$page_mode);
|
$o .= conversation($items,$mode,$update,$page_mode);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
$o .= '<noscript>';
|
||||||
|
if($noscript_content) {
|
||||||
|
$o .= conversation($items,$mode,$update,'traditional');
|
||||||
|
$o .= alt_pager(count($items));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$o .= '<div class="section-content-warning-wrapper">' . t('You must enable javascript for your browser to be able to view this content.') . '</div>';
|
||||||
|
}
|
||||||
|
$o .= '</noscript>';
|
||||||
|
|
||||||
|
$o .= conversation($items,$mode,$update,$page_mode);
|
||||||
|
|
||||||
if((! $update) || ($checkjs->disabled())) {
|
|
||||||
$o .= alt_pager(count($items));
|
|
||||||
if ($mid && $items[0]['title'])
|
if ($mid && $items[0]['title'])
|
||||||
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
|
App::$page['title'] = $items[0]['title'] . " - " . App::$page['title'];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($mid)
|
if($mid)
|
||||||
|
|||||||
@@ -0,0 +1,495 @@
|
|||||||
|
<?php
|
||||||
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
require_once('include/conversation.php');
|
||||||
|
require_once('include/bbcode.php');
|
||||||
|
require_once('include/datetime.php');
|
||||||
|
require_once('include/event.php');
|
||||||
|
require_once('include/items.php');
|
||||||
|
require_once('include/html2plain.php');
|
||||||
|
|
||||||
|
class Channel_calendar extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
|
function post() {
|
||||||
|
|
||||||
|
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||||
|
|
||||||
|
if(! local_channel())
|
||||||
|
return;
|
||||||
|
|
||||||
|
$event_id = ((x($_POST,'event_id')) ? intval($_POST['event_id']) : 0);
|
||||||
|
$event_hash = ((x($_POST,'event_hash')) ? $_POST['event_hash'] : '');
|
||||||
|
|
||||||
|
$xchan = ((x($_POST,'xchan')) ? dbesc($_POST['xchan']) : '');
|
||||||
|
$uid = local_channel();
|
||||||
|
|
||||||
|
// only allow editing your own events.
|
||||||
|
if(($xchan) && ($xchan !== get_observer_hash()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$timezone = ((x($_POST,'timezone_select')) ? escape_tags(trim($_POST['timezone_select'])) : '');
|
||||||
|
$tz = (($timezone) ? $timezone : date_default_timezone_get());
|
||||||
|
|
||||||
|
$categories = escape_tags(trim($_POST['categories']));
|
||||||
|
|
||||||
|
$adjust = intval($_POST['adjust']);
|
||||||
|
|
||||||
|
$start = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtstart']));
|
||||||
|
$finish = datetime_convert('UTC', 'UTC', escape_tags($_REQUEST['dtend']));
|
||||||
|
|
||||||
|
$summary = escape_tags(trim($_POST['summary']));
|
||||||
|
$desc = escape_tags(trim($_POST['desc']));
|
||||||
|
$location = escape_tags(trim($_POST['location']));
|
||||||
|
$type = escape_tags(trim($_POST['type']));
|
||||||
|
|
||||||
|
// Don't allow the event to finish before it begins.
|
||||||
|
// It won't hurt anything, but somebody will file a bug report
|
||||||
|
// and we'll waste a bunch of time responding to it. Time that
|
||||||
|
// could've been spent doing something else.
|
||||||
|
|
||||||
|
if(strcmp($finish,$start) < 0 && !$nofinish) {
|
||||||
|
notice( t('Event can not end before it has started.') . EOL);
|
||||||
|
if(intval($_REQUEST['preview'])) {
|
||||||
|
echo( t('Unable to generate preview.'));
|
||||||
|
}
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if((! $summary) || (! $start)) {
|
||||||
|
notice( t('Event title and start time are required.') . EOL);
|
||||||
|
if(intval($_REQUEST['preview'])) {
|
||||||
|
echo( t('Unable to generate preview.'));
|
||||||
|
}
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
|
$acl = new \Zotlabs\Access\AccessList(false);
|
||||||
|
|
||||||
|
if($event_id) {
|
||||||
|
$x = q("select * from event where id = %d and uid = %d limit 1",
|
||||||
|
intval($event_id),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
if(! $x) {
|
||||||
|
notice( t('Event not found.') . EOL);
|
||||||
|
if(intval($_REQUEST['preview'])) {
|
||||||
|
echo( t('Unable to generate preview.'));
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$acl->set($x[0]);
|
||||||
|
|
||||||
|
$created = $x[0]['created'];
|
||||||
|
$edited = datetime_convert();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$created = $edited = datetime_convert();
|
||||||
|
$acl->set_from_array($_POST);
|
||||||
|
}
|
||||||
|
|
||||||
|
$post_tags = array();
|
||||||
|
$channel = \App::get_channel();
|
||||||
|
$ac = $acl->get();
|
||||||
|
|
||||||
|
$str_contact_allow = $ac['allow_cid'];
|
||||||
|
$str_group_allow = $ac['allow_gid'];
|
||||||
|
$str_contact_deny = $ac['deny_cid'];
|
||||||
|
$str_group_deny = $ac['deny_gid'];
|
||||||
|
|
||||||
|
$private = $acl->is_private();
|
||||||
|
|
||||||
|
require_once('include/text.php');
|
||||||
|
$results = linkify_tags($desc, local_channel());
|
||||||
|
|
||||||
|
if($results) {
|
||||||
|
// Set permissions based on tag replacements
|
||||||
|
set_linkified_perms($results, $str_contact_allow, $str_group_allow, local_channel(), false, $private);
|
||||||
|
|
||||||
|
foreach($results as $result) {
|
||||||
|
$success = $result['success'];
|
||||||
|
if($success['replaced']) {
|
||||||
|
$post_tags[] = array(
|
||||||
|
'uid' => local_channel(),
|
||||||
|
'ttype' => $success['termtype'],
|
||||||
|
'otype' => TERM_OBJ_POST,
|
||||||
|
'term' => $success['term'],
|
||||||
|
'url' => $success['url']
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen($categories)) {
|
||||||
|
$cats = explode(',',$categories);
|
||||||
|
foreach($cats as $cat) {
|
||||||
|
$post_tags[] = array(
|
||||||
|
'uid' => local_channel(),
|
||||||
|
'ttype' => TERM_CATEGORY,
|
||||||
|
'otype' => TERM_OBJ_POST,
|
||||||
|
'term' => trim($cat),
|
||||||
|
'url' => $channel['xchan_url'] . '?f=&cat=' . urlencode(trim($cat))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$datarray = array();
|
||||||
|
$datarray['dtstart'] = $start;
|
||||||
|
$datarray['dtend'] = $finish;
|
||||||
|
$datarray['summary'] = $summary;
|
||||||
|
$datarray['description'] = $desc;
|
||||||
|
$datarray['location'] = $location;
|
||||||
|
$datarray['etype'] = $type;
|
||||||
|
$datarray['adjust'] = $adjust;
|
||||||
|
$datarray['nofinish'] = 0;
|
||||||
|
$datarray['uid'] = local_channel();
|
||||||
|
$datarray['account'] = get_account_id();
|
||||||
|
$datarray['event_xchan'] = $channel['channel_hash'];
|
||||||
|
$datarray['allow_cid'] = $str_contact_allow;
|
||||||
|
$datarray['allow_gid'] = $str_group_allow;
|
||||||
|
$datarray['deny_cid'] = $str_contact_deny;
|
||||||
|
$datarray['deny_gid'] = $str_group_deny;
|
||||||
|
$datarray['private'] = intval($private);
|
||||||
|
$datarray['id'] = $event_id;
|
||||||
|
$datarray['created'] = $created;
|
||||||
|
$datarray['edited'] = $edited;
|
||||||
|
$datarray['timezone'] = $tz;
|
||||||
|
|
||||||
|
|
||||||
|
if(intval($_REQUEST['preview'])) {
|
||||||
|
$html = format_event_html($datarray);
|
||||||
|
echo $html;
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
$event = event_store_event($datarray);
|
||||||
|
|
||||||
|
if($post_tags)
|
||||||
|
$datarray['term'] = $post_tags;
|
||||||
|
|
||||||
|
$item_id = event_store_item($datarray,$event);
|
||||||
|
|
||||||
|
if($item_id) {
|
||||||
|
$r = q("select * from item where id = %d",
|
||||||
|
intval($item_id)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
xchan_query($r);
|
||||||
|
$sync_item = fetch_post_tags($r);
|
||||||
|
$z = q("select * from event where event_hash = '%s' and uid = %d limit 1",
|
||||||
|
dbesc($r[0]['resource_id']),
|
||||||
|
intval($channel['channel_id'])
|
||||||
|
);
|
||||||
|
if($z) {
|
||||||
|
build_sync_packet($channel['channel_id'],array('event_item' => array(encode_item($sync_item[0],true)),'event' => $z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
\Zotlabs\Daemon\Master::Summon(array('Notifier','event',$item_id));
|
||||||
|
|
||||||
|
killme();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function get() {
|
||||||
|
|
||||||
|
if(argc() > 2 && argv(1) == 'ical') {
|
||||||
|
$event_id = argv(2);
|
||||||
|
|
||||||
|
require_once('include/security.php');
|
||||||
|
$sql_extra = permissions_sql(local_channel());
|
||||||
|
|
||||||
|
$r = q("select * from event where event_hash = '%s' $sql_extra limit 1",
|
||||||
|
dbesc($event_id)
|
||||||
|
);
|
||||||
|
if($r) {
|
||||||
|
header('Content-type: text/calendar');
|
||||||
|
header('content-disposition: attachment; filename="' . t('event') . '-' . $event_id . '.ics"' );
|
||||||
|
echo ical_wrapper($r);
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
notice( t('Event not found.') . EOL );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(! local_channel()) {
|
||||||
|
notice( t('Permission denied.') . EOL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
|
||||||
|
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
|
||||||
|
intval(argv(2)),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if((argc() > 2) && (argv(1) === 'unignore') && intval(argv(2))) {
|
||||||
|
$r = q("update event set dismissed = 0 where id = %d and uid = %d",
|
||||||
|
intval(argv(2)),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
|
$mode = 'view';
|
||||||
|
$export = false;
|
||||||
|
$ignored = ((x($_REQUEST,'ignored')) ? " and dismissed = " . intval($_REQUEST['ignored']) . " " : '');
|
||||||
|
|
||||||
|
if(argc() > 1) {
|
||||||
|
if(argc() > 2 && argv(1) === 'add') {
|
||||||
|
$mode = 'add';
|
||||||
|
$item_id = intval(argv(2));
|
||||||
|
}
|
||||||
|
if(argc() > 2 && argv(1) === 'drop') {
|
||||||
|
$mode = 'drop';
|
||||||
|
$event_id = argv(2);
|
||||||
|
}
|
||||||
|
if(argc() <= 2 && argv(1) === 'export') {
|
||||||
|
$export = true;
|
||||||
|
}
|
||||||
|
if(argc() > 2 && intval(argv(1)) && intval(argv(2))) {
|
||||||
|
$mode = 'view';
|
||||||
|
}
|
||||||
|
if(argc() <= 2) {
|
||||||
|
$mode = 'view';
|
||||||
|
$event_id = argv(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($mode === 'add') {
|
||||||
|
event_addtocal($item_id,local_channel());
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($mode == 'view') {
|
||||||
|
|
||||||
|
/* edit/create form */
|
||||||
|
if($event_id) {
|
||||||
|
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||||
|
dbesc($event_id),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
if(count($r))
|
||||||
|
$orig_event = $r[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
|
if (argv(1) === 'json'){
|
||||||
|
if (x($_GET,'start')) $start = $_GET['start'];
|
||||||
|
if (x($_GET,'end')) $finish = $_GET['end'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$start = datetime_convert('UTC','UTC',$start);
|
||||||
|
$finish = datetime_convert('UTC','UTC',$finish);
|
||||||
|
$adjust_start = datetime_convert('UTC', date_default_timezone_get(), $start);
|
||||||
|
$adjust_finish = datetime_convert('UTC', date_default_timezone_get(), $finish);
|
||||||
|
|
||||||
|
if (x($_GET,'id')){
|
||||||
|
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||||
|
from event left join item on item.resource_id = event.event_hash
|
||||||
|
where item.resource_type = 'event' and event.uid = %d and event.id = %d limit 1",
|
||||||
|
intval(local_channel()),
|
||||||
|
intval($_GET['id'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elseif($export) {
|
||||||
|
$r = q("SELECT event.*, item.id as item_id
|
||||||
|
from event left join item on item.resource_id = event.event_hash
|
||||||
|
where event.uid = %d and event.dtstart > '%s' and event.dtend > event.dtstart",
|
||||||
|
intval(local_channel()),
|
||||||
|
dbesc(NULL_DATE)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// fixed an issue with "nofinish" events not showing up in the calendar.
|
||||||
|
// There's still an issue if the finish date crosses the end of month.
|
||||||
|
// Noting this for now - it will need to be fixed here and in Friendica.
|
||||||
|
// Ultimately the finish date shouldn't be involved in the query.
|
||||||
|
|
||||||
|
$r = q("SELECT event.*, item.plink, item.item_flags, item.author_xchan, item.owner_xchan, item.id as item_id
|
||||||
|
from event left join item on event.event_hash = item.resource_id
|
||||||
|
where item.resource_type = 'event' and event.uid = %d and event.uid = item.uid $ignored
|
||||||
|
AND (( event.adjust = 0 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )
|
||||||
|
OR ( event.adjust = 1 AND ( event.dtend >= '%s' or event.nofinish = 1 ) AND event.dtstart <= '%s' )) ",
|
||||||
|
intval(local_channel()),
|
||||||
|
dbesc($start),
|
||||||
|
dbesc($finish),
|
||||||
|
dbesc($adjust_start),
|
||||||
|
dbesc($adjust_finish)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($r && ! $export) {
|
||||||
|
xchan_query($r);
|
||||||
|
$r = fetch_post_tags($r,true);
|
||||||
|
$r = sort_by_date($r);
|
||||||
|
}
|
||||||
|
|
||||||
|
$events = [];
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
|
||||||
|
foreach($r as $rr) {
|
||||||
|
|
||||||
|
$tz = get_iconfig($rr, 'event', 'timezone');
|
||||||
|
|
||||||
|
if(! $tz)
|
||||||
|
$tz = 'UTC';
|
||||||
|
|
||||||
|
$start = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtstart'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtstart'], 'c'));
|
||||||
|
if ($rr['nofinish']){
|
||||||
|
$end = null;
|
||||||
|
} else {
|
||||||
|
$end = (($rr['adjust']) ? datetime_convert($tz, date_default_timezone_get(), $rr['dtend'], 'c') : datetime_convert('UTC', 'UTC', $rr['dtend'], 'c'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$catsenabled = feature_enabled(local_channel(),'categories');
|
||||||
|
$categories = '';
|
||||||
|
if($catsenabled){
|
||||||
|
if($rr['term']) {
|
||||||
|
$cats = get_terms_oftype($rr['term'], TERM_CATEGORY);
|
||||||
|
foreach ($cats as $cat) {
|
||||||
|
if(strlen($categories))
|
||||||
|
$categories .= ', ';
|
||||||
|
$categories .= $cat['term'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$edit = ((local_channel() && $rr['author_xchan'] == get_observer_hash()) ? array(z_root().'/events/'.$rr['event_hash'].'?expandform=1',t('Edit event'),'','') : false);
|
||||||
|
|
||||||
|
$drop = array(z_root().'/events/drop/'.$rr['event_hash'],t('Delete event'),'','');
|
||||||
|
|
||||||
|
$events[] = array(
|
||||||
|
'calendar_id' => 'channel_calendar',
|
||||||
|
'rw' => true,
|
||||||
|
'id'=>$rr['id'],
|
||||||
|
'uri' => $rr['event_hash'],
|
||||||
|
'timezone' => $tz,
|
||||||
|
'start'=> $start,
|
||||||
|
'end' => $end,
|
||||||
|
'drop' => $drop,
|
||||||
|
'allDay' => (($rr['adjust']) ? 0 : 1),
|
||||||
|
'title' => html_entity_decode($rr['summary'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'editable' => $edit ? true : false,
|
||||||
|
'item' => $rr,
|
||||||
|
'plink' => [$rr['plink'], t('Link to source')],
|
||||||
|
'description' => html_entity_decode($rr['description'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'location' => html_entity_decode($rr['location'], ENT_COMPAT, 'UTF-8'),
|
||||||
|
'allow_cid' => expand_acl($rr['allow_cid']),
|
||||||
|
'allow_gid' => expand_acl($rr['allow_gid']),
|
||||||
|
'deny_cid' => expand_acl($rr['deny_cid']),
|
||||||
|
'deny_gid' => expand_acl($rr['deny_gid']),
|
||||||
|
'categories' => $categories
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if($export) {
|
||||||
|
header('Content-type: text/calendar');
|
||||||
|
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
|
||||||
|
echo ical_wrapper($r);
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\App::$argv[1] === 'json'){
|
||||||
|
json_return_and_die($events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if($mode === 'drop' && $event_id) {
|
||||||
|
$r = q("SELECT * FROM event WHERE event_hash = '%s' AND uid = %d LIMIT 1",
|
||||||
|
dbesc($event_id),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
|
||||||
|
$sync_event = $r[0];
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
$r = q("delete from event where event_hash = '%s' and uid = %d",
|
||||||
|
dbesc($event_id),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
|
||||||
|
$sync_event['event_deleted'] = 1;
|
||||||
|
build_sync_packet(0,array('event' => array($sync_event)));
|
||||||
|
|
||||||
|
$i = q("select * from item where resource_type = 'event' and resource_id = '%s' and uid = %d",
|
||||||
|
dbesc($event_id),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($i) {
|
||||||
|
|
||||||
|
$can_delete = false;
|
||||||
|
$local_delete = true;
|
||||||
|
|
||||||
|
$ob_hash = get_observer_hash();
|
||||||
|
if($ob_hash && ($ob_hash === $i[0]['author_xchan'] || $ob_hash === $i[0]['owner_xchan'] || $ob_hash === $i[0]['source_xchan'])) {
|
||||||
|
$can_delete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The site admin can delete any post/item on the site.
|
||||||
|
// If the item originated on this site+channel the deletion will propagate downstream.
|
||||||
|
// Otherwise just the local copy is removed.
|
||||||
|
|
||||||
|
if(is_site_admin()) {
|
||||||
|
$local_delete = true;
|
||||||
|
if(intval($i[0]['item_origin']))
|
||||||
|
$can_delete = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($can_delete || $local_delete) {
|
||||||
|
|
||||||
|
// if this is a different page type or it's just a local delete
|
||||||
|
// but not by the item author or owner, do a simple deletion
|
||||||
|
|
||||||
|
$complex = false;
|
||||||
|
|
||||||
|
if(intval($i[0]['item_type']) || ($local_delete && (! $can_delete))) {
|
||||||
|
drop_item($i[0]['id']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// complex deletion that needs to propagate and be performed in phases
|
||||||
|
drop_item($i[0]['id'],true,DROPITEM_PHASE1);
|
||||||
|
$complex = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ii = q("select * from item where id = %d",
|
||||||
|
intval($i[0]['id'])
|
||||||
|
);
|
||||||
|
if($ii) {
|
||||||
|
xchan_query($ii);
|
||||||
|
$sync_item = fetch_post_tags($ii);
|
||||||
|
build_sync_packet($i[0]['uid'],array('item' => array(encode_item($sync_item[0],true))));
|
||||||
|
}
|
||||||
|
|
||||||
|
if($complex) {
|
||||||
|
tag_deliver($i[0]['uid'],$i[0]['id']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
notice( t('Failed to remove event' ) . EOL);
|
||||||
|
killme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -106,7 +106,7 @@ class Chanview extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if (\App::$poi) {
|
if (\App::$poi) {
|
||||||
$url = \App::$poi['xchan_url'];
|
$url = \App::$poi['xchan_url'];
|
||||||
if(\App::$poi['xchan_network'] === 'zot') {
|
if(in_array(\App::$poi['xchan_network'], ['zot', 'zot6'])) {
|
||||||
$is_zot = true;
|
$is_zot = true;
|
||||||
}
|
}
|
||||||
if(local_channel()) {
|
if(local_channel()) {
|
||||||
|
|||||||
+39
-31
@@ -1,13 +1,19 @@
|
|||||||
<?php /** @file */
|
<?php /** @file */
|
||||||
|
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\Chatroom;
|
||||||
|
use Zotlabs\Access\AccessList;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
require_once('include/bookmarks.php');
|
require_once('include/bookmarks.php');
|
||||||
|
|
||||||
use \Zotlabs\Lib as Zlib;
|
class Chat extends Controller {
|
||||||
|
|
||||||
class Chat extends \Zotlabs\Web\Controller {
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
@@ -16,7 +22,7 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
if(! $which) {
|
if(! $which) {
|
||||||
if(local_channel()) {
|
if(local_channel()) {
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
if($channel && $channel['channel_address'])
|
if($channel && $channel['channel_address'])
|
||||||
$which = $channel['channel_address'];
|
$which = $channel['channel_address'];
|
||||||
}
|
}
|
||||||
@@ -27,7 +33,7 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$profile = 0;
|
$profile = 0;
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
if((local_channel()) && (argc() > 2) && (argv(2) === 'view')) {
|
||||||
$which = $channel['channel_address'];
|
$which = $channel['channel_address'];
|
||||||
@@ -49,16 +55,16 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
if((! $room) || (! local_channel()))
|
if((! $room) || (! local_channel()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
|
|
||||||
if($_POST['action'] === 'drop') {
|
if($_POST['action'] === 'drop') {
|
||||||
logger('delete chatroom');
|
logger('delete chatroom');
|
||||||
Zlib\Chatroom::destroy($channel,array('cr_name' => $room));
|
Chatroom::destroy($channel,array('cr_name' => $room));
|
||||||
goaway(z_root() . '/chat/' . $channel['channel_address']);
|
goaway(z_root() . '/chat/' . $channel['channel_address']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
$acl = new AccessList($channel);
|
||||||
$acl->set_from_array($_REQUEST);
|
$acl->set_from_array($_REQUEST);
|
||||||
|
|
||||||
$arr = $acl->get();
|
$arr = $acl->get();
|
||||||
@@ -67,7 +73,7 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
if(intval($arr['expire']) < 0)
|
if(intval($arr['expire']) < 0)
|
||||||
$arr['expire'] = 0;
|
$arr['expire'] = 0;
|
||||||
|
|
||||||
Zlib\Chatroom::create($channel,$arr);
|
Chatroom::create($channel,$arr);
|
||||||
|
|
||||||
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
|
$x = q("select * from chatroom where cr_name = '%s' and cr_uid = %d limit 1",
|
||||||
dbesc($room),
|
dbesc($room),
|
||||||
@@ -88,26 +94,35 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(App::$profile_uid, 'Chatrooms')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Chatrooms App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Access Controlled Chatrooms');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
if(local_channel()) {
|
if(local_channel()) {
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
nav_set_selected('My Chatrooms');
|
nav_set_selected('Chatrooms');
|
||||||
}
|
}
|
||||||
|
|
||||||
$ob = \App::get_observer();
|
$ob = App::get_observer();
|
||||||
$observer = get_observer_hash();
|
$observer = get_observer_hash();
|
||||||
if(! $observer) {
|
if(! $observer) {
|
||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! perm_is_allowed(\App::$profile['profile_uid'],$observer,'chat')) {
|
if(! perm_is_allowed(App::$profile['profile_uid'],$observer,'chat')) {
|
||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
|
if((argc() > 3) && intval(argv(2)) && (argv(3) === 'leave')) {
|
||||||
Zlib\Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
|
Chatroom::leave($observer,argv(2),$_SERVER['REMOTE_ADDR']);
|
||||||
goaway(z_root() . '/channel/' . argv(1));
|
goaway(z_root() . '/channel/' . argv(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,16 +175,16 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
$room_id = intval(argv(2));
|
$room_id = intval(argv(2));
|
||||||
$bookmark_link = get_bookmark_link($ob);
|
$bookmark_link = get_bookmark_link($ob);
|
||||||
|
|
||||||
$x = Zlib\Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
|
$x = Chatroom::enter($observer,$room_id,'online',$_SERVER['REMOTE_ADDR']);
|
||||||
if(! $x)
|
if(! $x)
|
||||||
return;
|
return;
|
||||||
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
|
$x = q("select * from chatroom where cr_id = %d and cr_uid = %d $sql_extra limit 1",
|
||||||
intval($room_id),
|
intval($room_id),
|
||||||
intval(\App::$profile['profile_uid'])
|
intval(App::$profile['profile_uid'])
|
||||||
);
|
);
|
||||||
|
|
||||||
if($x) {
|
if($x) {
|
||||||
$acl = new \Zotlabs\Access\AccessList(false);
|
$acl = new AccessList(false);
|
||||||
$acl->set($x[0]);
|
$acl->set($x[0]);
|
||||||
|
|
||||||
$private = $acl->is_private();
|
$private = $acl->is_private();
|
||||||
@@ -208,19 +223,12 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
));
|
));
|
||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
require_once('include/conversation.php');
|
require_once('include/conversation.php');
|
||||||
|
|
||||||
//$o = profile_tabs($a,((local_channel() && local_channel() == \App::$profile['profile_uid']) ? true : false),\App::$profile['channel_address']);
|
|
||||||
$o = '';
|
$o = '';
|
||||||
|
|
||||||
if(! feature_enabled(\App::$profile['profile_uid'],'ajaxchat')) {
|
|
||||||
notice( t('Feature disabled.') . EOL);
|
|
||||||
return $o;
|
|
||||||
}
|
|
||||||
|
|
||||||
$acl = new \Zotlabs\Access\AccessList($channel);
|
$acl = new AccessList($channel);
|
||||||
$channel_acl = $acl->get();
|
$channel_acl = $acl->get();
|
||||||
|
|
||||||
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');
|
$lockstate = (($channel_acl['allow_cid'] || $channel_acl['allow_gid'] || $channel_acl['deny_cid'] || $channel_acl['deny_gid']) ? 'lock' : 'unlock');
|
||||||
@@ -244,17 +252,17 @@ class Chat extends \Zotlabs\Web\Controller {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$rooms = Zlib\Chatroom::roomlist(\App::$profile['profile_uid']);
|
$rooms = Chatroom::roomlist(App::$profile['profile_uid']);
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
|
$o .= replace_macros(get_markup_template('chatrooms.tpl'), array(
|
||||||
'$header' => sprintf( t('%1$s\'s Chatrooms'), \App::$profile['fullname']),
|
'$header' => sprintf( t('%1$s\'s Chatrooms'), App::$profile['fullname']),
|
||||||
'$name' => t('Name'),
|
'$name' => t('Name'),
|
||||||
'$baseurl' => z_root(),
|
'$baseurl' => z_root(),
|
||||||
'$nickname' => \App::$profile['channel_address'],
|
'$nickname' => App::$profile['channel_address'],
|
||||||
'$rooms' => $rooms,
|
'$rooms' => $rooms,
|
||||||
'$norooms' => t('No chatrooms available'),
|
'$norooms' => t('No chatrooms available'),
|
||||||
'$newroom' => t('Create New'),
|
'$newroom' => t('Create New'),
|
||||||
'$is_owner' => ((local_channel() && local_channel() == \App::$profile['profile_uid']) ? 1 : 0),
|
'$is_owner' => ((local_channel() && local_channel() == App::$profile['profile_uid']) ? 1 : 0),
|
||||||
'$chatroom_new' => $chatroom_new,
|
'$chatroom_new' => $chatroom_new,
|
||||||
'$expire' => t('Expiration'),
|
'$expire' => t('Expiration'),
|
||||||
'$expire_unit' => t('min') //minutes
|
'$expire_unit' => t('min') //minutes
|
||||||
|
|||||||
@@ -35,13 +35,6 @@ class Cloud extends \Zotlabs\Web\Controller {
|
|||||||
if (argc() > 1)
|
if (argc() > 1)
|
||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
|
|
||||||
|
|
||||||
if (argc() < 2 && intval(get_config('system','cloud_disable_siteroot'))) {
|
|
||||||
notice( t('Permission denied.') . EOL);
|
|
||||||
construct_page();
|
|
||||||
killme();
|
|
||||||
}
|
|
||||||
|
|
||||||
$profile = 0;
|
$profile = 0;
|
||||||
|
|
||||||
if ($which)
|
if ($which)
|
||||||
|
|||||||
+47
-21
@@ -1,21 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module; /** @file */
|
namespace Zotlabs\Module; /** @file */
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
|
||||||
require_once('include/contact_widgets.php');
|
require_once('include/contact_widgets.php');
|
||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
|
|
||||||
|
class Connect extends Controller {
|
||||||
|
|
||||||
class Connect extends \Zotlabs\Web\Controller {
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if(argc() > 1)
|
if(argc() > 1)
|
||||||
$which = argv(1);
|
$which = argv(1);
|
||||||
else {
|
else {
|
||||||
notice( t('Requested profile is not available.') . EOL );
|
notice( t('Requested profile is not available.') . EOL );
|
||||||
\App::$error = 404;
|
App::$error = 404;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -24,20 +24,32 @@ class Connect extends \Zotlabs\Web\Controller {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if($r)
|
if($r)
|
||||||
\App::$data['channel'] = $r[0];
|
App::$data['channel'] = $r[0];
|
||||||
|
|
||||||
|
$channel_id = App::$data['channel']['channel_id'];
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
profile_load($which,'');
|
profile_load($which,'');
|
||||||
}
|
}
|
||||||
|
|
||||||
function post() {
|
function post() {
|
||||||
|
|
||||||
if(! array_key_exists('channel', \App::$data))
|
if(! array_key_exists('channel', App::$data))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
$channel_id = App::$data['channel']['channel_id'];
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
|
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||||
|
|
||||||
if($edit) {
|
if($edit) {
|
||||||
$has_premium = ((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0);
|
$has_premium = ((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? 1 : 0);
|
||||||
$premium = (($_POST['premium']) ? intval($_POST['premium']) : 0);
|
$premium = (($_POST['premium']) ? intval($_POST['premium']) : 0);
|
||||||
$text = escape_tags($_POST['text']);
|
$text = escape_tags($_POST['text']);
|
||||||
|
|
||||||
@@ -48,25 +60,25 @@ class Connect extends \Zotlabs\Web\Controller {
|
|||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
|
|
||||||
\Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',\App::$data['channel']['channel_id']));
|
\Zotlabs\Daemon\Master::Summon(array('Notifier','refresh_all',$channel_id));
|
||||||
}
|
}
|
||||||
set_pconfig(\App::$data['channel']['channel_id'],'system','selltext',$text);
|
set_pconfig($channel_id,'system','selltext',$text);
|
||||||
// reload the page completely to get fresh data
|
// reload the page completely to get fresh data
|
||||||
goaway(z_root() . '/' . \App::$query_string);
|
goaway(z_root() . '/' . App::$query_string);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$url = '';
|
$url = '';
|
||||||
$observer = \App::get_observer();
|
$observer = App::get_observer();
|
||||||
if(($observer) && ($_POST['submit'] === t('Continue'))) {
|
if(($observer) && ($_POST['submit'] === t('Continue'))) {
|
||||||
if($observer['xchan_follow'])
|
if($observer['xchan_follow'])
|
||||||
$url = sprintf($observer['xchan_follow'],urlencode(channel_reddress(\App::$data['channel'])));
|
$url = sprintf($observer['xchan_follow'],urlencode(channel_reddress(App::$data['channel'])));
|
||||||
if(! $url) {
|
if(! $url) {
|
||||||
$r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1",
|
$r = q("select * from hubloc where hubloc_hash = '%s' order by hubloc_id desc limit 1",
|
||||||
dbesc($observer['xchan_hash'])
|
dbesc($observer['xchan_hash'])
|
||||||
);
|
);
|
||||||
if($r)
|
if($r)
|
||||||
$url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(\App::$data['channel']));
|
$url = $r[0]['hubloc_url'] . '/follow?f=&url=' . urlencode(channel_reddress(App::$data['channel']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if($url)
|
if($url)
|
||||||
@@ -79,17 +91,31 @@ class Connect extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
|
|
||||||
|
if(! array_key_exists('channel', App::$data))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$channel_id = App::$data['channel']['channel_id'];
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed($channel_id, 'Premium Channel')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Premium Channel App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Allows you to set restrictions and terms on those that connect with your channel');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
$edit = ((local_channel() && (local_channel() == \App::$data['channel']['channel_id'])) ? true : false);
|
$edit = ((local_channel() && (local_channel() == $channel_id)) ? true : false);
|
||||||
|
|
||||||
$text = get_pconfig(\App::$data['channel']['channel_id'],'system','selltext');
|
$text = get_pconfig($channel_id,'system','selltext');
|
||||||
|
|
||||||
if($edit) {
|
if($edit) {
|
||||||
|
|
||||||
$o = replace_macros(get_markup_template('sellpage_edit.tpl'),array(
|
$o = replace_macros(get_markup_template('sellpage_edit.tpl'),array(
|
||||||
'$header' => t('Premium Channel Setup'),
|
'$header' => t('Premium Channel Setup'),
|
||||||
'$address' => \App::$data['channel']['channel_address'],
|
'$address' => App::$data['channel']['channel_address'],
|
||||||
'$premium' => array('premium', t('Enable premium channel connection restrictions'),((\App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''),
|
'$premium' => array('premium', t('Enable premium channel connection restrictions'),((App::$data['channel']['channel_pageflags'] & PAGE_PREMIUM) ? '1' : ''),''),
|
||||||
'$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'),
|
'$lbl_about' => t('Please enter your restrictions or conditions, such as paypal receipt, usage guidelines, etc.'),
|
||||||
'$text' => $text,
|
'$text' => $text,
|
||||||
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
|
'$desc' => t('This channel may require additional steps or acknowledgement of the following conditions prior to connecting:'),
|
||||||
@@ -107,7 +133,7 @@ class Connect extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array(
|
$submit = replace_macros(get_markup_template('sellpage_submit.tpl'), array(
|
||||||
'$continue' => t('Continue'),
|
'$continue' => t('Continue'),
|
||||||
'$address' => \App::$data['channel']['channel_address']
|
'$address' => App::$data['channel']['channel_address']
|
||||||
));
|
));
|
||||||
|
|
||||||
$o = replace_macros(get_markup_template('sellpage_view.tpl'),array(
|
$o = replace_macros(get_markup_template('sellpage_view.tpl'),array(
|
||||||
@@ -120,7 +146,7 @@ class Connect extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
));
|
));
|
||||||
|
|
||||||
$arr = array('channel' => \App::$data['channel'],'observer' => \App::get_observer(), 'sellpage' => $o, 'submit' => $submit);
|
$arr = array('channel' => App::$data['channel'],'observer' => App::get_observer(), 'sellpage' => $o, 'submit' => $submit);
|
||||||
call_hooks('connect_premium', $arr);
|
call_hooks('connect_premium', $arr);
|
||||||
$o = $arr['sellpage'];
|
$o = $arr['sellpage'];
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
|
||||||
require_once('include/socgraph.php');
|
require_once('include/socgraph.php');
|
||||||
require_once('include/selectors.php');
|
require_once('include/selectors.php');
|
||||||
@@ -12,8 +13,10 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if(! local_channel())
|
if(! local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
App::$profile_uid = local_channel();
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
if($channel)
|
if($channel)
|
||||||
head_set_icon($channel['xchan_photo_s']);
|
head_set_icon($channel['xchan_photo_s']);
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
$all = false;
|
$all = false;
|
||||||
|
|
||||||
if(! $_REQUEST['aj'])
|
if(! $_REQUEST['aj'])
|
||||||
$_SESSION['return_url'] = \App::$query_string;
|
$_SESSION['return_url'] = App::$query_string;
|
||||||
|
|
||||||
$search_flags = "";
|
$search_flags = "";
|
||||||
$head = '';
|
$head = '';
|
||||||
@@ -88,14 +91,14 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
$search_flags = " and abook_pending = 1 ";
|
$search_flags = " and abook_pending = 1 ";
|
||||||
$head = t('New');
|
$head = t('New');
|
||||||
$pending = true;
|
$pending = true;
|
||||||
\App::$argv[1] = 'pending';
|
App::$argv[1] = 'pending';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$head = t('All');
|
$head = t('All');
|
||||||
$search_flags = '';
|
$search_flags = '';
|
||||||
$all = true;
|
$all = true;
|
||||||
\App::$argc = 1;
|
App::$argc = 1;
|
||||||
unset(\App::$argv[1]);
|
unset(App::$argv[1]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// case 'unconnected':
|
// case 'unconnected':
|
||||||
@@ -124,6 +127,20 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
$unblocked = true;
|
$unblocked = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch($_REQUEST['order']) {
|
||||||
|
case 'name_desc':
|
||||||
|
$sql_order = 'xchan_name DESC';
|
||||||
|
break;
|
||||||
|
case 'connected':
|
||||||
|
$sql_order = 'abook_created';
|
||||||
|
break;
|
||||||
|
case 'connected_desc':
|
||||||
|
$sql_order = 'abook_created DESC';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$sql_order = 'xchan_name';
|
||||||
|
}
|
||||||
|
|
||||||
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
|
$search = ((x($_REQUEST,'search')) ? notags(trim($_REQUEST['search'])) : '');
|
||||||
|
|
||||||
$tabs = array(
|
$tabs = array(
|
||||||
@@ -217,7 +234,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
|
$sql_extra .= (($searching) ? protect_sprintf(" AND xchan_name like '%$search_txt%' ") : "");
|
||||||
|
|
||||||
if($_REQUEST['gid']) {
|
if($_REQUEST['gid']) {
|
||||||
$sql_extra .= " and xchan_hash in ( select xchan from group_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
|
$sql_extra .= " and xchan_hash in ( select xchan from pgrp_member where gid = " . intval($_REQUEST['gid']) . " and uid = " . intval(local_channel()) . " ) ";
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
$r = q("SELECT COUNT(abook.abook_id) AS total FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||||
@@ -225,15 +242,15 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
\App::set_pager_total($r[0]['total']);
|
App::set_pager_total($r[0]['total']);
|
||||||
$total = $r[0]['total'];
|
$total = $r[0]['total'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
$r = q("SELECT abook.*, xchan.* FROM abook left join xchan on abook.abook_xchan = xchan.xchan_hash
|
||||||
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY xchan_name LIMIT %d OFFSET %d ",
|
WHERE abook_channel = %d and abook_self = 0 and xchan_deleted = 0 and xchan_orphan = 0 $sql_extra $sql_extra2 ORDER BY $sql_order LIMIT %d OFFSET %d ",
|
||||||
intval(local_channel()),
|
intval(local_channel()),
|
||||||
intval(\App::$pager['itemspage']),
|
intval(App::$pager['itemspage']),
|
||||||
intval(\App::$pager['start'])
|
intval(App::$pager['start'])
|
||||||
);
|
);
|
||||||
|
|
||||||
$contacts = array();
|
$contacts = array();
|
||||||
@@ -304,8 +321,11 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
'ignore_hover' => t('Ignore connection'),
|
'ignore_hover' => t('Ignore connection'),
|
||||||
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
|
'ignore' => ((! $rr['abook_ignored']) ? t('Ignore') : false),
|
||||||
'recent_label' => t('Recent activity'),
|
'recent_label' => t('Recent activity'),
|
||||||
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']),
|
'recentlink' => z_root() . '/network/?f=&cid=' . intval($rr['abook_id']) . '&name=' . $rr['xchan_name'],
|
||||||
'oneway' => $oneway
|
'oneway' => $oneway,
|
||||||
|
'connect' => (intval($rr['abook_not_here']) ? t('Connect') : ''),
|
||||||
|
'follow' => z_root() . '/follow/?f=&url=' . urlencode($rr['xchan_hash']) . '&interactive=0',
|
||||||
|
'connect_hover' => t('Connect at this location')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -326,7 +346,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; </script>";
|
||||||
$o .= replace_macros(get_markup_template('connections.tpl'),array(
|
$o .= replace_macros(get_markup_template('connections.tpl'),array(
|
||||||
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
|
'$header' => t('Connections') . (($head) ? ': ' . $head : ''),
|
||||||
'$tabs' => $tabs,
|
'$tabs' => $tabs,
|
||||||
@@ -337,7 +357,7 @@ class Connections extends \Zotlabs\Web\Controller {
|
|||||||
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
|
'$finding' => (($searching) ? t('Connections search') . ": '" . $search . "'" : ""),
|
||||||
'$submit' => t('Find'),
|
'$submit' => t('Find'),
|
||||||
'$edit' => t('Edit'),
|
'$edit' => t('Edit'),
|
||||||
'$cmd' => \App::$cmd,
|
'$cmd' => App::$cmd,
|
||||||
'$contacts' => $contacts,
|
'$contacts' => $contacts,
|
||||||
'$paginate' => paginate($a),
|
'$paginate' => paginate($a),
|
||||||
|
|
||||||
|
|||||||
+29
-12
@@ -7,6 +7,8 @@ namespace Zotlabs\Module;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Lib\Libzot;
|
||||||
|
|
||||||
require_once('include/socgraph.php');
|
require_once('include/socgraph.php');
|
||||||
require_once('include/selectors.php');
|
require_once('include/selectors.php');
|
||||||
@@ -99,7 +101,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$profile_id = $_POST['profile_assign'];
|
$profile_id = ((array_key_exists('profile_assign',$_POST)) ? $_POST['profile_assign'] : $orig_record[0]['abook_profile']);
|
||||||
|
|
||||||
if($profile_id) {
|
if($profile_id) {
|
||||||
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
|
$r = q("SELECT profile_guid FROM profile WHERE profile_guid = '%s' AND uid = %d LIMIT 1",
|
||||||
dbesc($profile_id),
|
dbesc($profile_id),
|
||||||
@@ -111,18 +114,23 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$abook_incl = escape_tags($_POST['abook_incl']);
|
$abook_incl = ((array_key_exists('abook_incl',$_POST)) ? escape_tags($_POST['abook_incl']) : $orig_record[0]['abook_incl']);
|
||||||
$abook_excl = escape_tags($_POST['abook_excl']);
|
$abook_excl = ((array_key_exists('abook_excl',$_POST)) ? escape_tags($_POST['abook_excl']) : $orig_record[0]['abook_excl']);
|
||||||
|
|
||||||
|
|
||||||
$hidden = intval($_POST['hidden']);
|
$hidden = intval($_POST['hidden']);
|
||||||
|
|
||||||
$priority = intval($_POST['poll']);
|
$priority = intval($_POST['poll']);
|
||||||
if($priority > 5 || $priority < 0)
|
if($priority > 5 || $priority < 0)
|
||||||
$priority = 0;
|
$priority = 0;
|
||||||
|
|
||||||
|
if(! array_key_exists('closeness',$_POST)) {
|
||||||
|
$_POST['closeness'] = 80;
|
||||||
|
}
|
||||||
$closeness = intval($_POST['closeness']);
|
$closeness = intval($_POST['closeness']);
|
||||||
if($closeness < 0)
|
if($closeness < 0 || $closeness > 99) {
|
||||||
$closeness = 99;
|
$closeness = 80;
|
||||||
|
}
|
||||||
|
|
||||||
$rating = intval($_POST['rating']);
|
$rating = intval($_POST['rating']);
|
||||||
if($rating < (-10))
|
if($rating < (-10))
|
||||||
@@ -229,6 +237,8 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
|
$abook_pending = (($new_friend) ? 0 : $orig_record[0]['abook_pending']);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
|
$r = q("UPDATE abook SET abook_profile = '%s', abook_closeness = %d, abook_pending = %d,
|
||||||
abook_incl = '%s', abook_excl = '%s'
|
abook_incl = '%s', abook_excl = '%s'
|
||||||
@@ -474,6 +484,10 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
if(! zot_refresh($orig_record[0],\App::get_channel()))
|
if(! zot_refresh($orig_record[0],\App::get_channel()))
|
||||||
notice( t('Refresh failed - channel is currently unavailable.') );
|
notice( t('Refresh failed - channel is currently unavailable.') );
|
||||||
}
|
}
|
||||||
|
elseif($orig_record[0]['xchan_network'] === 'zot6') {
|
||||||
|
if(! Libzot::refresh($orig_record[0],\App::get_channel()))
|
||||||
|
notice( t('Refresh failed - channel is currently unavailable.') );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// if you are on a different network we'll force a refresh of the connection basic info
|
// if you are on a different network we'll force a refresh of the connection basic info
|
||||||
@@ -696,7 +710,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$tpl = get_markup_template("abook_edit.tpl");
|
$tpl = get_markup_template("abook_edit.tpl");
|
||||||
|
|
||||||
if(feature_enabled(local_channel(),'affinity')) {
|
if(Apps::system_app_installed(local_channel(),'Affinity Tool')) {
|
||||||
|
|
||||||
$sections['affinity'] = [
|
$sections['affinity'] = [
|
||||||
'label' => t('Affinity'),
|
'label' => t('Affinity'),
|
||||||
@@ -727,9 +741,12 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$slider_tpl = get_markup_template('contact_slider.tpl');
|
$slider_tpl = get_markup_template('contact_slider.tpl');
|
||||||
|
|
||||||
|
$slideval = intval($contact['abook_closeness']);
|
||||||
|
|
||||||
$slide = replace_macros($slider_tpl,array(
|
$slide = replace_macros($slider_tpl,array(
|
||||||
'$min' => 1,
|
'$min' => 1,
|
||||||
'$val' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 99),
|
'$val' => $slideval,
|
||||||
'$labels' => $label_str,
|
'$labels' => $label_str,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -774,7 +791,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||||
|
|
||||||
$existing = get_all_perms(local_channel(),$contact['abook_xchan']);
|
$existing = get_all_perms(local_channel(),$contact['abook_xchan'],false);
|
||||||
|
|
||||||
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
|
$unapproved = array('pending', t('Approve this connection'), '', t('Accept connection to allow communication'), array(t('No'),('Yes')));
|
||||||
|
|
||||||
@@ -831,7 +848,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
$locstr = unpunify($contact['xchan_url']);
|
$locstr = unpunify($contact['xchan_url']);
|
||||||
|
|
||||||
$clone_warn = '';
|
$clone_warn = '';
|
||||||
$clonable = (in_array($contact['xchan_network'],['zot','rss']) ? true : false);
|
$clonable = (in_array($contact['xchan_network'],['zot', 'zot6', 'rss']) ? true : false);
|
||||||
if(! $clonable) {
|
if(! $clonable) {
|
||||||
$clone_warn = '<strong>';
|
$clone_warn = '<strong>';
|
||||||
$clone_warn .= ((intval($contact['abook_not_here']))
|
$clone_warn .= ((intval($contact['abook_not_here']))
|
||||||
@@ -851,7 +868,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
|
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('Connection requests will be approved without your interaction'), $yes_no),
|
||||||
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
|
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
|
||||||
'$permcat_new' => t('Add permission role'),
|
'$permcat_new' => t('Add permission role'),
|
||||||
'$permcat_enable' => feature_enabled(local_channel(),'permcats'),
|
'$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
|
||||||
'$addr' => unpunify($contact['xchan_addr']),
|
'$addr' => unpunify($contact['xchan_addr']),
|
||||||
'$primeurl' => unpunify($contact['xchan_url']),
|
'$primeurl' => unpunify($contact['xchan_url']),
|
||||||
'$section' => $section,
|
'$section' => $section,
|
||||||
@@ -886,7 +903,7 @@ class Connedit extends \Zotlabs\Web\Controller {
|
|||||||
'$inherited' => t('inherited'),
|
'$inherited' => t('inherited'),
|
||||||
'$submit' => t('Submit'),
|
'$submit' => t('Submit'),
|
||||||
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
|
'$lbl_vis2' => sprintf( t('Please choose the profile you would like to display to %s when viewing your profile securely.'), $contact['xchan_name']),
|
||||||
'$close' => $contact['abook_closeness'],
|
'$close' => (($contact['abook_closeness']) ? $contact['abook_closeness'] : 80),
|
||||||
'$them' => t('Their Settings'),
|
'$them' => t('Their Settings'),
|
||||||
'$me' => t('My Settings'),
|
'$me' => t('My Settings'),
|
||||||
'$perms' => $perms,
|
'$perms' => $perms,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Contactgroup extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if((argc() > 1) && (intval(argv(1)))) {
|
if((argc() > 1) && (intval(argv(1)))) {
|
||||||
|
|
||||||
$r = q("SELECT * FROM groups WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
|
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
|
||||||
intval(argv(1)),
|
intval(argv(1)),
|
||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,6 +48,32 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
|||||||
$channel = \App::get_channel();
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
check_form_security_token_redirectOnErr('/cover_photo', 'cover_photo');
|
||||||
|
|
||||||
|
// Remove cover photo
|
||||||
|
if(isset($_POST['remove'])) {
|
||||||
|
|
||||||
|
$r = q("SELECT resource_id FROM photo WHERE photo_usage = %d AND uid = %d LIMIT 1",
|
||||||
|
intval(PHOTO_COVER),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
|
||||||
|
if($r) {
|
||||||
|
q("update photo set photo_usage = %d where photo_usage = %d and uid = %d",
|
||||||
|
intval(PHOTO_NORMAL),
|
||||||
|
intval(PHOTO_COVER),
|
||||||
|
intval(local_channel())
|
||||||
|
);
|
||||||
|
|
||||||
|
$sync = attach_export_data($channel,$r[0]['resource_id']);
|
||||||
|
if($sync)
|
||||||
|
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update directory in background
|
||||||
|
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||||
|
|
||||||
|
goaway(z_root() . '/cover_photo');
|
||||||
|
}
|
||||||
|
|
||||||
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
|
if((array_key_exists('cropfinal',$_POST)) && ($_POST['cropfinal'] == 1)) {
|
||||||
|
|
||||||
@@ -106,7 +132,7 @@ class Cover_photo extends \Zotlabs\Web\Controller {
|
|||||||
if(file_exists($tmp_name)) {
|
if(file_exists($tmp_name)) {
|
||||||
$base_image = $r[0];
|
$base_image = $r[0];
|
||||||
$gis = getimagesize($tmp_name);
|
$gis = getimagesize($tmp_name);
|
||||||
logger('gis: ' . print_r($gis,true));
|
logger('gis: ' . print_r($gis,true), LOGGER_DEBUG);
|
||||||
$base_image['width'] = $gis[0];
|
$base_image['width'] = $gis[0];
|
||||||
$base_image['height'] = $gis[1];
|
$base_image['height'] = $gis[1];
|
||||||
$base_image['content'] = @file_get_contents($tmp_name);
|
$base_image['content'] = @file_get_contents($tmp_name);
|
||||||
@@ -167,25 +193,18 @@ logger('gis: ' . print_r($gis,true));
|
|||||||
'filename' => $base_image['filename'],
|
'filename' => $base_image['filename'],
|
||||||
'album' => t('Cover Photos'),
|
'album' => t('Cover Photos'),
|
||||||
'os_path' => $base_image['os_path'],
|
'os_path' => $base_image['os_path'],
|
||||||
'display_path' => $base_image['display_path']
|
'display_path' => $base_image['display_path'],
|
||||||
|
'photo_usage' => PHOTO_COVER
|
||||||
];
|
];
|
||||||
|
|
||||||
$p['imgscale'] = 7;
|
$r1 = $im->storeThumbnail($p, PHOTO_RES_COVER_1200);
|
||||||
$p['photo_usage'] = PHOTO_COVER;
|
|
||||||
|
|
||||||
$r1 = $im->save($p);
|
|
||||||
|
|
||||||
$im->doScaleImage(850,310);
|
$im->doScaleImage(850,310);
|
||||||
$p['imgscale'] = 8;
|
$r2 = $im->storeThumbnail($p, PHOTO_RES_COVER_850);
|
||||||
|
|
||||||
$r2 = $im->save($p);
|
|
||||||
|
|
||||||
|
|
||||||
$im->doScaleImage(425,160);
|
$im->doScaleImage(425,160);
|
||||||
$p['imgscale'] = 9;
|
$r3 = $im->storeThumbnail($p, PHOTO_RES_COVER_425);
|
||||||
|
|
||||||
$r3 = $im->save($p);
|
|
||||||
|
|
||||||
if($r1 === false || $r2 === false || $r3 === false) {
|
if($r1 === false || $r2 === false || $r3 === false) {
|
||||||
// if one failed, delete them all so we can start over.
|
// if one failed, delete them all so we can start over.
|
||||||
notice( t('Image resize failed.') . EOL );
|
notice( t('Image resize failed.') . EOL );
|
||||||
@@ -193,13 +212,28 @@ logger('gis: ' . print_r($gis,true));
|
|||||||
dbesc($base_image['resource_id']),
|
dbesc($base_image['resource_id']),
|
||||||
local_channel()
|
local_channel()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$x = q("SELECT content FROM photo WHERE resource_id = '%s' AND uid = %d AND os_storage = 1 AND imgscale >= 7",
|
||||||
|
dbesc($base_image['resource_id']),
|
||||||
|
local_channel()
|
||||||
|
);
|
||||||
|
if($x) {
|
||||||
|
foreach($x as $xx) {
|
||||||
|
@unlink(dbunescbin($xx['content']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
|
||||||
$this->send_cover_photo_activity($channel,$base_image,$profile);
|
$this->send_cover_photo_activity($channel,$base_image,$profile);
|
||||||
|
|
||||||
|
$sync = attach_export_data($channel,$base_image['resource_id']);
|
||||||
|
if($sync)
|
||||||
|
build_sync_packet($channel['channel_id'],array('file' => array($sync)));
|
||||||
|
|
||||||
|
// Update directory in background
|
||||||
|
\Zotlabs\Daemon\Master::Summon(array('Directory',$channel['channel_id']));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
notice( t('Unable to process image') . EOL);
|
notice( t('Unable to process image') . EOL);
|
||||||
@@ -215,7 +249,7 @@ logger('gis: ' . print_r($gis,true));
|
|||||||
|
|
||||||
require_once('include/attach.php');
|
require_once('include/attach.php');
|
||||||
|
|
||||||
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash));
|
$res = attach_store(\App::get_channel(), get_observer_hash(), '', array('album' => t('Cover Photos'), 'hash' => $hash, 'nosync' => true));
|
||||||
|
|
||||||
logger('attach_store: ' . print_r($res,true));
|
logger('attach_store: ' . print_r($res,true));
|
||||||
|
|
||||||
@@ -393,6 +427,7 @@ logger('gis: ' . print_r($gis,true));
|
|||||||
'$lbl_profiles' => t('Select a profile:'),
|
'$lbl_profiles' => t('Select a profile:'),
|
||||||
'$title' => t('Change Cover Photo'),
|
'$title' => t('Change Cover Photo'),
|
||||||
'$submit' => t('Upload'),
|
'$submit' => t('Upload'),
|
||||||
|
'$remove' => t('Remove'),
|
||||||
'$profiles' => $profiles,
|
'$profiles' => $profiles,
|
||||||
'$embedPhotos' => t('Use a photo from your albums'),
|
'$embedPhotos' => t('Use a photo from your albums'),
|
||||||
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
'$embedPhotosModalTitle' => t('Use a photo from your albums'),
|
||||||
|
|||||||
@@ -8,8 +8,9 @@
|
|||||||
|
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
use \Sabre\DAV as SDAV;
|
use Sabre\DAV as SDAV;
|
||||||
use \Zotlabs\Storage;
|
use Zotlabs\Storage;
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
require_once('include/attach.php');
|
require_once('include/attach.php');
|
||||||
require_once('include/auth.php');
|
require_once('include/auth.php');
|
||||||
@@ -46,7 +47,7 @@ class Dav extends \Zotlabs\Web\Controller {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||||
if($sigblock) {
|
if($sigblock) {
|
||||||
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
$keyId = str_replace('acct:','',$sigblock['keyId']);
|
||||||
if($keyId) {
|
if($keyId) {
|
||||||
@@ -69,7 +70,7 @@ class Dav extends \Zotlabs\Web\Controller {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if($record) {
|
if($record) {
|
||||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
$verified = HTTPSig::verify('',$record['channel']['channel_pubkey']);
|
||||||
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
if(! ($verified && $verified['header_signed'] && $verified['header_valid'])) {
|
||||||
$record = null;
|
$record = null;
|
||||||
}
|
}
|
||||||
@@ -94,6 +95,8 @@ class Dav extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
$auth = new \Zotlabs\Storage\BasicAuth();
|
$auth = new \Zotlabs\Storage\BasicAuth();
|
||||||
|
$auth->observer = get_observer_hash();
|
||||||
|
|
||||||
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
|
$auth->setRealm(ucfirst(\Zotlabs\Lib\System::get_platform_name()) . ' ' . 'WebDAV');
|
||||||
|
|
||||||
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
$rootDirectory = new \Zotlabs\Storage\Directory('/', $auth);
|
||||||
|
|||||||
+33
-17
@@ -1,14 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
|
||||||
require_once('include/socgraph.php');
|
require_once('include/socgraph.php');
|
||||||
require_once('include/selectors.php');
|
require_once('include/selectors.php');
|
||||||
require_once('include/group.php');
|
require_once('include/group.php');
|
||||||
require_once('include/photos.php');
|
require_once('include/photos.php');
|
||||||
|
|
||||||
|
class Defperms extends Controller {
|
||||||
class Defperms extends \Zotlabs\Web\Controller {
|
|
||||||
|
|
||||||
/* @brief Initialize the connection-editor
|
/* @brief Initialize the connection-editor
|
||||||
*
|
*
|
||||||
@@ -19,6 +21,9 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if(! local_channel())
|
if(! local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||||
|
return;
|
||||||
|
|
||||||
$r = q("SELECT abook.*, xchan.*
|
$r = q("SELECT abook.*, xchan.*
|
||||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||||
@@ -26,10 +31,10 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
\App::$poi = $r[0];
|
App::$poi = $r[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
if($channel)
|
if($channel)
|
||||||
head_set_icon($channel['xchan_photo_s']);
|
head_set_icon($channel['xchan_photo_s']);
|
||||||
}
|
}
|
||||||
@@ -43,12 +48,15 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
if(! local_channel())
|
if(! local_channel())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Default Permissions'))
|
||||||
|
return;
|
||||||
|
|
||||||
$contact_id = intval(argv(1));
|
$contact_id = intval(argv(1));
|
||||||
if(! $contact_id)
|
if(! $contact_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
|
$orig_record = q("SELECT * FROM abook WHERE abook_id = %d AND abook_channel = %d LIMIT 1",
|
||||||
intval($contact_id),
|
intval($contact_id),
|
||||||
@@ -112,7 +120,7 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
intval($contact_id)
|
intval($contact_id)
|
||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
\App::$poi = $r[0];
|
App::$poi = $r[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -131,22 +139,22 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
function defperms_clone(&$a) {
|
function defperms_clone(&$a) {
|
||||||
|
|
||||||
if(! \App::$poi)
|
if(! App::$poi)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
$r = q("SELECT abook.*, xchan.*
|
$r = q("SELECT abook.*, xchan.*
|
||||||
FROM abook left join xchan on abook_xchan = xchan_hash
|
FROM abook left join xchan on abook_xchan = xchan_hash
|
||||||
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
WHERE abook_channel = %d and abook_id = %d LIMIT 1",
|
||||||
intval(local_channel()),
|
intval(local_channel()),
|
||||||
intval(\App::$poi['abook_id'])
|
intval(App::$poi['abook_id'])
|
||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
\App::$poi = array_shift($r);
|
App::$poi = array_shift($r);
|
||||||
}
|
}
|
||||||
|
|
||||||
$clone = \App::$poi;
|
$clone = App::$poi;
|
||||||
|
|
||||||
unset($clone['abook_id']);
|
unset($clone['abook_id']);
|
||||||
unset($clone['abook_account']);
|
unset($clone['abook_account']);
|
||||||
@@ -173,9 +181,18 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return login();
|
return login();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Default Permissions')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Default Permissions App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Set custom default permissions for new connections');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
$section = ((array_key_exists('section',$_REQUEST)) ? $_REQUEST['section'] : '');
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
$yes_no = array(t('No'),t('Yes'));
|
$yes_no = array(t('No'),t('Yes'));
|
||||||
|
|
||||||
@@ -193,7 +210,7 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
$o .= " }\n</script>\n";
|
$o .= " }\n</script>\n";
|
||||||
|
|
||||||
if(\App::$poi) {
|
if(App::$poi) {
|
||||||
|
|
||||||
$sections = [];
|
$sections = [];
|
||||||
|
|
||||||
@@ -203,13 +220,12 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
$perms = array();
|
$perms = array();
|
||||||
$channel = \App::get_channel();
|
$channel = App::get_channel();
|
||||||
|
|
||||||
$contact = \App::$poi;
|
$contact = App::$poi;
|
||||||
|
|
||||||
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
$global_perms = \Zotlabs\Access\Permissions::Perms();
|
||||||
|
|
||||||
$existing = get_all_perms(local_channel(),$contact['abook_xchan']);
|
|
||||||
$hidden_perms = [];
|
$hidden_perms = [];
|
||||||
|
|
||||||
foreach($global_perms as $k => $v) {
|
foreach($global_perms as $k => $v) {
|
||||||
@@ -239,7 +255,7 @@ class Defperms extends \Zotlabs\Web\Controller {
|
|||||||
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no),
|
'$autoperms' => array('autoperms',t('Apply these permissions automatically'), ((get_pconfig(local_channel(),'system','autoperms')) ? 1 : 0), t('If enabled, connection requests will be approved without your interaction'), $yes_no),
|
||||||
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
|
'$permcat' => [ 'permcat', t('Permission role'), '', '<span class="loading invisible">' . t('Loading') . '<span class="jumping-dots"><span class="dot-1">.</span><span class="dot-2">.</span><span class="dot-3">.</span></span></span>',$permcats ],
|
||||||
'$permcat_new' => t('Add permission role'),
|
'$permcat_new' => t('Add permission role'),
|
||||||
'$permcat_enable' => feature_enabled(local_channel(),'permcats'),
|
'$permcat_enable' => Apps::system_app_installed(local_channel(), 'Permission Categories'),
|
||||||
'$section' => $section,
|
'$section' => $section,
|
||||||
'$sections' => $sections,
|
'$sections' => $sections,
|
||||||
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
|
'$autolbl' => t('The permissions indicated on this page will be applied to all new connections.'),
|
||||||
|
|||||||
@@ -12,13 +12,16 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
function init() {
|
function init() {
|
||||||
\App::set_pager_itemspage(60);
|
\App::set_pager_itemspage(60);
|
||||||
|
|
||||||
if(x($_GET,'ignore')) {
|
if(local_channel() && x($_GET,'ignore')) {
|
||||||
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
q("insert into xign ( uid, xchan ) values ( %d, '%s' ) ",
|
||||||
intval(local_channel()),
|
intval(local_channel()),
|
||||||
dbesc($_GET['ignore'])
|
dbesc($_GET['ignore'])
|
||||||
);
|
);
|
||||||
goaway(z_root() . '/directory?f=&suggest=1');
|
goaway(z_root() . '/directory?f=&suggest=1');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(local_channel())
|
||||||
|
\App::$profile_uid = local_channel();
|
||||||
|
|
||||||
$observer = get_observer_hash();
|
$observer = get_observer_hash();
|
||||||
$global_changed = false;
|
$global_changed = false;
|
||||||
@@ -55,6 +58,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
if($observer)
|
if($observer)
|
||||||
set_xconfig($observer,'directory','pubforums',$pubforums);
|
set_xconfig($observer,'directory','pubforums',$pubforums);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
@@ -99,8 +103,14 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
|
$suggest = (local_channel() && x($_REQUEST,'suggest')) ? $_REQUEST['suggest'] : '';
|
||||||
|
|
||||||
if($suggest) {
|
if($suggest) {
|
||||||
|
|
||||||
$r = suggestion_query(local_channel(),get_observer_hash());
|
// the directory options have no effect in suggestion mode
|
||||||
|
|
||||||
|
$globaldir = 1;
|
||||||
|
$safe_mode = 1;
|
||||||
|
$type = 0;
|
||||||
|
|
||||||
|
$r = suggestion_query(local_channel(),get_observer_hash(),0,60);
|
||||||
|
|
||||||
if(! $r) {
|
if(! $r) {
|
||||||
notice( t('No default suggestions were found.') . EOL);
|
notice( t('No default suggestions were found.') . EOL);
|
||||||
@@ -208,12 +218,17 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
if($j) {
|
if($j) {
|
||||||
|
|
||||||
if($j['results']) {
|
if($j['results']) {
|
||||||
|
|
||||||
|
$results = $j['results'];
|
||||||
|
if($suggest) {
|
||||||
|
$results = self::reorder_results($results,$addresses);
|
||||||
|
}
|
||||||
|
|
||||||
$entries = array();
|
$entries = array();
|
||||||
|
|
||||||
$photo = 'thumb';
|
$photo = 'thumb';
|
||||||
|
|
||||||
foreach($j['results'] as $rr) {
|
foreach($results as $rr) {
|
||||||
|
|
||||||
$profile_link = chanlink_url($rr['url']);
|
$profile_link = chanlink_url($rr['url']);
|
||||||
|
|
||||||
@@ -272,7 +287,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
|
$hometown = ((x($profile,'hometown') == 1) ? $profile['hometown'] : False);
|
||||||
|
|
||||||
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'])) : False);
|
$about = ((x($profile,'about') == 1) ? zidify_links(bbcode($profile['about'], ['tryoembed' => false])) : False);
|
||||||
|
|
||||||
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
$keywords = ((x($profile,'keywords')) ? $profile['keywords'] : '');
|
||||||
|
|
||||||
@@ -330,7 +345,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
'pdesc_label' => t('Description:'),
|
'pdesc_label' => t('Description:'),
|
||||||
'marital' => $marital,
|
'marital' => $marital,
|
||||||
'homepage' => $homepage,
|
'homepage' => $homepage,
|
||||||
'homepageurl' => linkify($homepageurl),
|
'homepageurl' => linkify($homepageurl, true),
|
||||||
'hometown' => $hometown,
|
'hometown' => $hometown,
|
||||||
'hometown_label' => t('Hometown:'),
|
'hometown_label' => t('Hometown:'),
|
||||||
'about' => $about,
|
'about' => $about,
|
||||||
@@ -395,7 +410,7 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
|
$dirtitle = (($globaldir) ? t('Global Directory') : t('Local Directory'));
|
||||||
|
|
||||||
$o .= "<script> var page_query = '" . escape_tags($_GET['q']) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
|
$o .= "<script> var page_query = '" . escape_tags(urlencode($_GET['q'])) . "'; var extra_args = '" . extra_query_args() . "' ; divmore_height = " . intval($maxheight) . "; </script>";
|
||||||
$o .= replace_macros($tpl, array(
|
$o .= replace_macros($tpl, array(
|
||||||
'$search' => $search,
|
'$search' => $search,
|
||||||
'$desc' => t('Find'),
|
'$desc' => t('Find'),
|
||||||
@@ -434,5 +449,22 @@ class Directory extends \Zotlabs\Web\Controller {
|
|||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function reorder_results($results,$suggests) {
|
||||||
|
|
||||||
|
if(! $suggests)
|
||||||
|
return $results;
|
||||||
|
|
||||||
|
$out = [];
|
||||||
|
foreach($suggests as $k => $v) {
|
||||||
|
foreach($results as $rv) {
|
||||||
|
if($k == $rv['address']) {
|
||||||
|
$out[intval($v)] = $rv;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,12 +116,12 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
|||||||
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
|
$sql_extra .= $this->dir_query_build($joiner,'xchan_name',$name);
|
||||||
if($address)
|
if($address)
|
||||||
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
|
$sql_extra .= $this->dir_query_build($joiner,'xchan_addr',$address);
|
||||||
if($city)
|
if($locale)
|
||||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$city);
|
$sql_extra .= $this->dir_query_build($joiner,'xprof_locale',$locale);
|
||||||
if($region)
|
if($region)
|
||||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
|
$sql_extra .= $this->dir_query_build($joiner,'xprof_region',$region);
|
||||||
if($post)
|
if($postcode)
|
||||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$post);
|
$sql_extra .= $this->dir_query_build($joiner,'xprof_postcode',$postcode);
|
||||||
if($country)
|
if($country)
|
||||||
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
|
$sql_extra .= $this->dir_query_build($joiner,'xprof_country',$country);
|
||||||
if($gender)
|
if($gender)
|
||||||
@@ -394,7 +394,7 @@ class Dirsearch extends \Zotlabs\Web\Controller {
|
|||||||
$quoted_string = false;
|
$quoted_string = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
$curr['value'] .= ' ' . trim(q);
|
$curr['value'] .= ' ' . trim($q);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+58
-56
@@ -12,8 +12,9 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
function get($update = 0, $load = false) {
|
function get($update = 0, $load = false) {
|
||||||
|
|
||||||
$module_format = 'html';
|
$noscript_content = (get_config('system', 'noscript_content', '1') && (! $update));
|
||||||
|
|
||||||
|
$module_format = 'html';
|
||||||
|
|
||||||
if(argc() > 1) {
|
if(argc() > 1) {
|
||||||
$module_format = substr(argv(1),strrpos(argv(1),'.') + 1);
|
$module_format = substr(argv(1),strrpos(argv(1),'.') + 1);
|
||||||
@@ -21,8 +22,6 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
$module_format = 'html';
|
$module_format = 'html';
|
||||||
}
|
}
|
||||||
|
|
||||||
$checkjs = new \Zotlabs\Web\CheckJS(1);
|
|
||||||
|
|
||||||
if($load)
|
if($load)
|
||||||
$_SESSION['loadtime'] = datetime_convert();
|
$_SESSION['loadtime'] = datetime_convert();
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
);
|
);
|
||||||
|
|
||||||
$o = '<div id="jot-popup">';
|
$o = '<div id="jot-popup">';
|
||||||
$o .= status_editor($a,$x);
|
$o .= status_editor($a,$x,false,'Display');
|
||||||
$o .= '</div>';
|
$o .= '</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,11 +175,15 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($target_item['item_type'] == ITEM_TYPE_CUSTOM) {
|
||||||
|
call_hooks('item_custom_display',$target_item);
|
||||||
|
notice( t('Page not found.') . EOL);
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
$static = ((array_key_exists('static',$_REQUEST)) ? intval($_REQUEST['static']) : 0);
|
||||||
|
|
||||||
|
|
||||||
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
$simple_update = (($update) ? " AND item_unseen = 1 " : '');
|
||||||
|
|
||||||
if($update && $_SESSION['loadtime'])
|
if($update && $_SESSION['loadtime'])
|
||||||
@@ -235,7 +238,7 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
'$dbegin' => '',
|
'$dbegin' => '',
|
||||||
'$verb' => '',
|
'$verb' => '',
|
||||||
'$net' => '',
|
'$net' => '',
|
||||||
'$mid' => $mid
|
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||||
));
|
));
|
||||||
|
|
||||||
head_add_link([
|
head_add_link([
|
||||||
@@ -253,53 +256,44 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$sql_extra = public_permissions_sql($observer_hash);
|
$sql_extra = public_permissions_sql($observer_hash);
|
||||||
|
|
||||||
if(($update && $load) || ($checkjs->disabled()) || ($module_format !== 'html')) {
|
if($noscript_content || $load) {
|
||||||
|
|
||||||
$pager_sql = sprintf(" LIMIT %d OFFSET %d ", intval(\App::$pager['itemspage']),intval(\App::$pager['start']));
|
$r = null;
|
||||||
|
|
||||||
if($load || ($checkjs->disabled()) || ($module_format !== 'html')) {
|
require_once('include/channel.php');
|
||||||
|
$sys = get_sys_channel();
|
||||||
|
$sysid = $sys['channel_id'];
|
||||||
|
|
||||||
$r = null;
|
if(local_channel()) {
|
||||||
|
$r = q("SELECT item.id as item_id from item WHERE uid = %d and mid = '%s' $item_normal limit 1",
|
||||||
require_once('include/channel.php');
|
intval(local_channel()),
|
||||||
$sys = get_sys_channel();
|
dbesc($target_item['parent_mid'])
|
||||||
$sysid = $sys['channel_id'];
|
);
|
||||||
|
if($r) {
|
||||||
if(local_channel()) {
|
$updateable = true;
|
||||||
$r = q("SELECT item.id as item_id from item
|
|
||||||
WHERE uid = %d
|
|
||||||
and mid = '%s'
|
|
||||||
$item_normal
|
|
||||||
limit 1",
|
|
||||||
intval(local_channel()),
|
|
||||||
dbesc($target_item['parent_mid'])
|
|
||||||
);
|
|
||||||
if($r) {
|
|
||||||
$updateable = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(! $r) {
|
if(! $r) {
|
||||||
|
|
||||||
// in case somebody turned off public access to sys channel content using permissions
|
// in case somebody turned off public access to sys channel content using permissions
|
||||||
// make that content unsearchable by ensuring the owner uid can't match
|
// make that content unsearchable by ensuring the owner uid can't match
|
||||||
|
|
||||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||||
$sysid = 0;
|
$sysid = 0;
|
||||||
|
|
||||||
$r = q("SELECT item.id as item_id from item
|
$r = q("SELECT item.id as item_id from item
|
||||||
WHERE mid = '%s'
|
WHERE mid = '%s'
|
||||||
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
AND (((( item.allow_cid = '' AND item.allow_gid = '' AND item.deny_cid = ''
|
||||||
AND item.deny_gid = '' AND item_private = 0 )
|
AND item.deny_gid = '' AND item_private = 0 )
|
||||||
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
and uid in ( " . stream_perms_api_uids(($observer_hash) ? (PERMS_NETWORK|PERMS_PUBLIC) : PERMS_PUBLIC) . " ))
|
||||||
OR uid = %d )
|
OR uid = %d )
|
||||||
$sql_extra )
|
$sql_extra )
|
||||||
$item_normal
|
$item_normal
|
||||||
limit 1",
|
limit 1",
|
||||||
dbesc($target_item['parent_mid']),
|
dbesc($target_item['parent_mid']),
|
||||||
intval($sysid)
|
intval($sysid)
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,7 +303,6 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
require_once('include/channel.php');
|
require_once('include/channel.php');
|
||||||
$sys = get_sys_channel();
|
$sys = get_sys_channel();
|
||||||
$sysid = $sys['channel_id'];
|
$sysid = $sys['channel_id'];
|
||||||
|
|
||||||
if(local_channel()) {
|
if(local_channel()) {
|
||||||
$r = q("SELECT item.parent AS item_id from item
|
$r = q("SELECT item.parent AS item_id from item
|
||||||
WHERE uid = %d
|
WHERE uid = %d
|
||||||
@@ -325,7 +318,7 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(! $r) {
|
if($r === null) {
|
||||||
// in case somebody turned off public access to sys channel content using permissions
|
// in case somebody turned off public access to sys channel content using permissions
|
||||||
// make that content unsearchable by ensuring the owner_xchan can't match
|
// make that content unsearchable by ensuring the owner_xchan can't match
|
||||||
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
if(! perm_is_allowed($sysid,$observer_hash,'view_stream'))
|
||||||
@@ -350,7 +343,7 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
else {
|
else {
|
||||||
$r = array();
|
$r = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
if($r) {
|
if($r) {
|
||||||
$parents_str = ids_to_querystr($r,'item_id');
|
$parents_str = ids_to_querystr($r,'item_id');
|
||||||
if($parents_str) {
|
if($parents_str) {
|
||||||
@@ -373,14 +366,23 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
case 'html':
|
case 'html':
|
||||||
|
|
||||||
if ($checkjs->disabled()) {
|
if ($update) {
|
||||||
$o .= conversation($items, 'display', $update, 'traditional');
|
|
||||||
if ($items[0]['title'])
|
|
||||||
\App::$page['title'] = $items[0]['title'] . " - " . \App::$page['title'];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$o .= conversation($items, 'display', $update, 'client');
|
$o .= conversation($items, 'display', $update, 'client');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
$o .= '<noscript>';
|
||||||
|
if($noscript_content) {
|
||||||
|
$o .= conversation($items, 'display', $update, 'traditional');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$o .= '<div class="section-content-warning-wrapper">' . t('You must enable javascript for your browser to be able to view this content.') . '</div>';
|
||||||
|
}
|
||||||
|
$o .= '</noscript>';
|
||||||
|
|
||||||
|
\App::$page['title'] = (($items[0]['title']) ? $items[0]['title'] . " - " . \App::$page['title'] : \App::$page['title']);
|
||||||
|
|
||||||
|
$o .= conversation($items, 'display', $update, 'client');
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -435,7 +437,7 @@ class Display extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$o .= '<div id="content-complete"></div>';
|
$o .= '<div id="content-complete"></div>';
|
||||||
|
|
||||||
if((($update && $load) || $checkjs->disabled()) && (! $items)) {
|
if((($update && $load) || $noscript_content) && (! $items)) {
|
||||||
|
|
||||||
$r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1",
|
$r = q("SELECT id, item_deleted FROM item WHERE mid = '%s' LIMIT 1",
|
||||||
dbesc($item_hash)
|
dbesc($item_hash)
|
||||||
|
|||||||
@@ -16,10 +16,21 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
$channel = \App::get_channel();
|
$channel = \App::get_channel();
|
||||||
|
|
||||||
$mid = ((argc() > 1) ? argv(1) : '');
|
$mid = ((argc() > 1) ? argv(1) : '');
|
||||||
|
$encoded_mid = '';
|
||||||
|
|
||||||
|
if(strpos($mid,'b64.') === 0) {
|
||||||
|
$encoded_mid = $mid;
|
||||||
|
$mid = @base64url_decode(substr($mid,4));
|
||||||
|
}
|
||||||
if($mid === 'push') {
|
if($mid === 'push') {
|
||||||
$table = 'push';
|
$table = 'push';
|
||||||
$mid = ((argc() > 2) ? argv(2) : '');
|
$mid = ((argc() > 2) ? argv(2) : '');
|
||||||
|
|
||||||
|
if(strpos($mid,'b64.') === 0) {
|
||||||
|
$encoded_mid = $mid;
|
||||||
|
$mid = @base64url_decode(substr($mid,4));
|
||||||
|
}
|
||||||
|
|
||||||
if($mid) {
|
if($mid) {
|
||||||
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
|
$i = q("select id from item where mid = '%s' and uid = %d and ( author_xchan = '%s' or ( owner_xchan = '%s' and item_wall = 1 )) ",
|
||||||
dbesc($mid),
|
dbesc($mid),
|
||||||
@@ -32,12 +43,15 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
sleep(3);
|
sleep(3);
|
||||||
goaway(z_root() . '/dreport/' . urlencode($mid));
|
goaway(z_root() . '/dreport/' . (($encoded_mid) ? $encoded_mid : $mid));
|
||||||
}
|
}
|
||||||
|
|
||||||
if($mid === 'mail') {
|
if($mid === 'mail') {
|
||||||
$table = 'mail';
|
$table = 'mail';
|
||||||
$mid = ((argc() > 2) ? argv(2) : '');
|
$mid = ((argc() > 2) ? argv(2) : '');
|
||||||
|
if(strpos($mid,'b64.') === 0)
|
||||||
|
$mid = @base64url_decode(substr($mid,4));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -69,8 +83,9 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$r = q("select * from dreport where dreport_xchan = '%s' and dreport_mid = '%s'",
|
$r = q("select * from dreport where (dreport_xchan = '%s' or dreport_xchan = '%s') and dreport_mid = '%s'",
|
||||||
dbesc($channel['channel_hash']),
|
dbesc($channel['channel_hash']),
|
||||||
|
dbesc($channel['channel_portable_id']),
|
||||||
dbesc($mid)
|
dbesc($mid)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -80,7 +95,6 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for($x = 0; $x < count($r); $x++ ) {
|
for($x = 0; $x < count($r); $x++ ) {
|
||||||
$r[$x]['name'] = escape_tags(substr($r[$x]['dreport_recip'],strpos($r[$x]['dreport_recip'],' ')));
|
|
||||||
|
|
||||||
// This has two purposes: 1. make the delivery report strings translateable, and
|
// This has two purposes: 1. make the delivery report strings translateable, and
|
||||||
// 2. assign an ordering to item delivery results so we can group them and provide
|
// 2. assign an ordering to item delivery results so we can group them and provide
|
||||||
@@ -138,16 +152,17 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
$entries = array();
|
$entries = array();
|
||||||
foreach($r as $rr) {
|
foreach($r as $rr) {
|
||||||
$entries[] = [
|
$entries[] = [
|
||||||
'name' => $rr['name'],
|
'name' => escape_tags($rr['dreport_name'] ?: $rr['dreport_recip']),
|
||||||
'result' => escape_tags($rr['dreport_result']),
|
'result' => escape_tags($rr['dreport_result']),
|
||||||
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
|
'time' => escape_tags(datetime_convert('UTC',date_default_timezone_get(),$rr['dreport_time']))
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
$o = replace_macros(get_markup_template('dreport.tpl'), array(
|
$o = replace_macros(get_markup_template('dreport.tpl'), array(
|
||||||
'$title' => sprintf( t('Delivery report for %1$s'),substr($mid,0,32)) . '...',
|
'$title' => sprintf( t('Delivery report for %1$s'),basename($mid)) . '...',
|
||||||
'$table' => $table,
|
'$table' => $table,
|
||||||
'$mid' => urlencode($mid),
|
'$mid' => urlencode($mid),
|
||||||
|
'$safe_mid' => urlencode(gen_link_id($mid)),
|
||||||
'$options' => t('Options'),
|
'$options' => t('Options'),
|
||||||
'$push' => t('Redeliver'),
|
'$push' => t('Redeliver'),
|
||||||
'$entries' => $entries
|
'$entries' => $entries
|
||||||
@@ -162,9 +177,9 @@ class Dreport extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
private static function dreport_gravity_sort($a,$b) {
|
private static function dreport_gravity_sort($a,$b) {
|
||||||
if($a['gravity'] == $b['gravity']) {
|
if($a['gravity'] == $b['gravity']) {
|
||||||
if($a['name'] === $b['name'])
|
if($a['dreport_name'] === $b['dreport_name'])
|
||||||
return strcmp($a['dreport_time'],$b['dreport_time']);
|
return strcmp($a['dreport_time'],$b['dreport_time']);
|
||||||
return strcmp($a['name'],$b['name']);
|
return strcmp($a['dreport_name'],$b['dreport_name']);
|
||||||
}
|
}
|
||||||
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
|
return (($a['gravity'] > $b['gravity']) ? 1 : (-1));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class Editblock extends \Zotlabs\Web\Controller {
|
|||||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Editblock');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit Block'),
|
'$title' => t('Edit Block'),
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ class Editlayout extends \Zotlabs\Web\Controller {
|
|||||||
'profile_uid' => intval($owner),
|
'profile_uid' => intval($owner),
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Editlayout');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit Layout'),
|
'$title' => t('Edit Layout'),
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ class Editpost extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
|
if($itm[0]['resource_type'] === 'event' && $itm[0]['resource_id']) {
|
||||||
goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
|
goaway(z_root() . '/cdav/calendar/' . $itm[0]['resource_id']);
|
||||||
|
//goaway(z_root() . '/events/' . $itm[0]['resource_id'] . '?expandform=1');
|
||||||
}
|
}
|
||||||
|
|
||||||
$owner_uid = $itm[0]['uid'];
|
$owner_uid = $itm[0]['uid'];
|
||||||
@@ -102,7 +103,7 @@ class Editpost extends \Zotlabs\Web\Controller {
|
|||||||
'bbcode' => true
|
'bbcode' => true
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Editpost');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit post'),
|
'$title' => t('Edit post'),
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ class Editwebpage extends \Zotlabs\Web\Controller {
|
|||||||
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
'bbcode' => (($mimetype == 'text/bbcode') ? true : false)
|
||||||
);
|
);
|
||||||
|
|
||||||
$editor = status_editor($a, $x);
|
$editor = status_editor($a, $x, false, 'Editwebpage');
|
||||||
|
|
||||||
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
$o .= replace_macros(get_markup_template('edpost_head.tpl'), array(
|
||||||
'$title' => t('Edit Webpage'),
|
'$title' => t('Edit Webpage'),
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
require_once('include/security.php');
|
||||||
|
require_once('include/bbcode.php');
|
||||||
|
|
||||||
|
|
||||||
|
class Embed extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
|
||||||
|
$post_id = ((argc() > 1) ? intval(argv(1)) : 0);
|
||||||
|
|
||||||
|
if(! $post_id)
|
||||||
|
killme();
|
||||||
|
|
||||||
|
echo '[share=' . $post_id . '][/share]';
|
||||||
|
killme();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+103
-67
@@ -3,8 +3,10 @@
|
|||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief
|
* @brief Embedphoto endpoint.
|
||||||
*
|
*
|
||||||
|
* Provide an AJAX endpoint to fill the embedPhotoModal with folders and photos
|
||||||
|
* selection.
|
||||||
*/
|
*/
|
||||||
class Embedphotos extends \Zotlabs\Web\Controller {
|
class Embedphotos extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
@@ -13,93 +15,116 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @brief This is the POST destination for the embedphotos button.
|
||||||
*
|
*
|
||||||
* This is the POST destination for the embedphotos button
|
* @return string A JSON string.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
function post() {
|
public function post() {
|
||||||
if (argc() > 1 && argv(1) === 'album') {
|
if (argc() > 1 && argv(1) === 'album') {
|
||||||
// API: /embedphotos/album
|
// API: /embedphotos/album
|
||||||
$name = (x($_POST,'name') ? $_POST['name'] : null );
|
$name = (x($_POST, 'name') ? $_POST['name'] : null );
|
||||||
if(!$name) {
|
if (!$name) {
|
||||||
json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false));
|
json_return_and_die(array('errormsg' => 'Error retrieving album', 'status' => false));
|
||||||
}
|
}
|
||||||
$album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name));
|
$album = $this->embedphotos_widget_album(array('channel' => \App::get_channel(), 'album' => $name));
|
||||||
json_return_and_die(array('status' => true, 'content' => $album));
|
json_return_and_die(array('status' => true, 'content' => $album));
|
||||||
}
|
}
|
||||||
if(argc() > 1 && argv(1) === 'albumlist') {
|
if (argc() > 1 && argv(1) === 'albumlist') {
|
||||||
// API: /embedphotos/albumlist
|
// API: /embedphotos/albumlist
|
||||||
$album_list = $this->embedphotos_album_list($a);
|
$album_list = $this->embedphotos_album_list();
|
||||||
json_return_and_die(array('status' => true, 'albumlist' => $album_list));
|
json_return_and_die(array('status' => true, 'albumlist' => $album_list));
|
||||||
}
|
}
|
||||||
if(argc() > 1 && argv(1) === 'photolink') {
|
if (argc() > 1 && argv(1) === 'photolink') {
|
||||||
// API: /embedphotos/photolink
|
// API: /embedphotos/photolink
|
||||||
$href = (x($_POST,'href') ? $_POST['href'] : null );
|
$href = (x($_POST, 'href') ? $_POST['href'] : null );
|
||||||
if(!$href) {
|
if (!$href) {
|
||||||
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
|
json_return_and_die(array('errormsg' => 'Error retrieving link ' . $href, 'status' => false));
|
||||||
}
|
}
|
||||||
$resource_id = array_pop(explode("/", $href));
|
$resource_id = array_pop(explode('/', $href));
|
||||||
$r = q("SELECT obj from item where resource_type = 'photo' and resource_id = '%s' limit 1",
|
$x = self::photolink($resource_id);
|
||||||
dbesc($resource_id)
|
if($x)
|
||||||
);
|
json_return_and_die(array('status' => true, 'photolink' => $x, 'resource_id' => $resource_id));
|
||||||
if(!$r) {
|
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
||||||
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
|
||||||
}
|
|
||||||
$obj = json_decode($r[0]['obj'], true);
|
|
||||||
if(x($obj,'body')) {
|
|
||||||
$photolink = $obj['body'];
|
|
||||||
} elseif (x($obj,'bbcode')) {
|
|
||||||
$photolink = $obj['bbcode'];
|
|
||||||
} else {
|
|
||||||
json_return_and_die(array('errormsg' => 'Error retrieving resource ' . $resource_id, 'status' => false));
|
|
||||||
}
|
|
||||||
json_return_and_die(array('status' => true, 'photolink' => $photolink, 'resource_id' => $resource_id));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Copied from include/widgets.php::widget_album() with a modification to get the profile_uid from
|
|
||||||
* the input array as in widget_item()
|
|
||||||
*
|
|
||||||
* @param array $args
|
|
||||||
* @return string with HTML
|
|
||||||
*/
|
|
||||||
function embedphotos_widget_album($args) {
|
|
||||||
|
|
||||||
|
protected static function photolink($resource) {
|
||||||
|
$channel = \App::get_channel();
|
||||||
|
$output = EMPTY_STR;
|
||||||
|
if($channel) {
|
||||||
|
$resolution = ((feature_enabled($channel['channel_id'],'large_photos')) ? 1 : 2);
|
||||||
|
$r = q("select mimetype, height, width from photo where resource_id = '%s' and $resolution = %d and uid = %d limit 1",
|
||||||
|
dbesc($resource),
|
||||||
|
intval($resolution),
|
||||||
|
intval($channel['channel_id'])
|
||||||
|
);
|
||||||
|
if(! $r)
|
||||||
|
return $output;
|
||||||
|
|
||||||
|
if($r[0]['mimetype'] === 'image/jpeg')
|
||||||
|
$ext = '.jpg';
|
||||||
|
elseif($r[0]['mimetype'] === 'image/png')
|
||||||
|
$ext = '.png';
|
||||||
|
elseif($r[0]['mimetype'] === 'image/gif')
|
||||||
|
$ext = '.gif';
|
||||||
|
else
|
||||||
|
$ext = EMPTY_STR;
|
||||||
|
|
||||||
|
$output = '[zrl=' . z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $resource . ']' .
|
||||||
|
'[zmg=' . $r[0]['width'] . 'x' . $r[0]['height'] . ']' . z_root() . '/photo/' . $resource . '-' . $resolution . $ext . '[/zmg][/zrl]';
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get photos from an album.
|
||||||
|
*
|
||||||
|
* @see \\Zotlabs\\Widget\\Album::widget()
|
||||||
|
*
|
||||||
|
* @param array $args associative array with
|
||||||
|
* * \e array \b channel
|
||||||
|
* * \e string \b album
|
||||||
|
* @return string with HTML code from 'photo_album.tpl'
|
||||||
|
*/
|
||||||
|
protected function embedphotos_widget_album($args) {
|
||||||
$channel_id = 0;
|
$channel_id = 0;
|
||||||
if(array_key_exists('channel', $args))
|
|
||||||
|
if (array_key_exists('channel', $args)) {
|
||||||
$channel = $args['channel'];
|
$channel = $args['channel'];
|
||||||
$channel_id = intval($channel['channel_id']);
|
$channel_id = intval($channel['channel_id']);
|
||||||
if(! $channel_id)
|
}
|
||||||
|
if (! $channel_id)
|
||||||
$channel_id = \App::$profile_uid;
|
$channel_id = \App::$profile_uid;
|
||||||
if(! $channel_id)
|
if (! $channel_id)
|
||||||
return '';
|
return '';
|
||||||
|
|
||||||
$owner_uid = $channel_id;
|
|
||||||
require_once('include/security.php');
|
require_once('include/security.php');
|
||||||
$sql_extra = permissions_sql($channel_id);
|
$sql_extra = permissions_sql($channel_id);
|
||||||
|
|
||||||
if(! perm_is_allowed($channel_id,get_observer_hash(),'view_storage'))
|
if (! perm_is_allowed($channel_id, get_observer_hash(), 'view_storage'))
|
||||||
return '';
|
return '';
|
||||||
|
|
||||||
if($args['album'])
|
if (isset($args['album']))
|
||||||
$album = (($args['album'] === '/') ? '' : $args['album']);
|
$album = (($args['album'] === '/') ? '' : $args['album']);
|
||||||
if($args['title'])
|
if (isset($args['title']))
|
||||||
$title = $args['title'];
|
$title = $args['title'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This may return incorrect permissions if you have multiple directories of the same name.
|
* @note This may return incorrect permissions if you have multiple directories of the same name.
|
||||||
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
|
* It is a limitation of the photo table using a name for a photo album instead of a folder hash
|
||||||
*/
|
*/
|
||||||
if($album) {
|
if ($album) {
|
||||||
require_once('include/attach.php');
|
require_once('include/attach.php');
|
||||||
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
|
$x = q("select hash from attach where filename = '%s' and uid = %d limit 1",
|
||||||
dbesc($album),
|
dbesc($album),
|
||||||
intval($owner_uid)
|
intval($channel_id)
|
||||||
);
|
);
|
||||||
if($x) {
|
if ($x) {
|
||||||
$y = attach_can_view_folder($owner_uid,get_observer_hash(),$x[0]['hash']);
|
$y = attach_can_view_folder($channel_id, get_observer_hash(), $x[0]['hash']);
|
||||||
if(! $y)
|
if (! $y)
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,30 +135,33 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
|||||||
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
|
(SELECT resource_id, max(imgscale) imgscale FROM photo WHERE uid = %d AND album = '%s' AND imgscale <= 4 AND photo_usage IN ( %d, %d ) $sql_extra GROUP BY resource_id) ph
|
||||||
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
|
ON (p.resource_id = ph.resource_id AND p.imgscale = ph.imgscale)
|
||||||
ORDER BY created $order",
|
ORDER BY created $order",
|
||||||
intval($owner_uid),
|
intval($channel_id),
|
||||||
dbesc($album),
|
dbesc($album),
|
||||||
intval(PHOTO_NORMAL),
|
intval(PHOTO_NORMAL),
|
||||||
intval(PHOTO_PROFILE)
|
intval(PHOTO_PROFILE)
|
||||||
);
|
);
|
||||||
|
|
||||||
$photos = array();
|
$photos = [];
|
||||||
if(count($r)) {
|
if (count($r)) {
|
||||||
$twist = 'rotright';
|
$twist = 'rotright';
|
||||||
foreach($r as $rr) {
|
foreach ($r as $rr) {
|
||||||
if($twist == 'rotright')
|
if ($twist == 'rotright')
|
||||||
$twist = 'rotleft';
|
$twist = 'rotleft';
|
||||||
else
|
else
|
||||||
$twist = 'rotright';
|
$twist = 'rotright';
|
||||||
|
|
||||||
|
$ph = photo_factory('');
|
||||||
|
$phototypes = $ph->supportedTypes();
|
||||||
|
|
||||||
$ext = $phototypes[$rr['mimetype']];
|
$ext = $phototypes[$rr['mimetype']];
|
||||||
|
|
||||||
$imgalt_e = $rr['filename'];
|
$imgalt_e = $rr['filename'];
|
||||||
$desc_e = $rr['description'];
|
$desc_e = $rr['description'];
|
||||||
|
|
||||||
$imagelink = (z_root() . '/photos/' . \App::$data['channel']['channel_address'] . '/image/' . $rr['resource_id']
|
$imagelink = (z_root() . '/photos/' . $channel['channel_address'] . '/image/' . $rr['resource_id']
|
||||||
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
|
. (($_GET['order'] === 'posted') ? '?f=&order=posted' : ''));
|
||||||
|
|
||||||
$photos[] = array(
|
$photos[] = [
|
||||||
'id' => $rr['id'],
|
'id' => $rr['id'],
|
||||||
'twist' => ' ' . $twist . rand(2,4),
|
'twist' => ' ' . $twist . rand(2,4),
|
||||||
'link' => $imagelink,
|
'link' => $imagelink,
|
||||||
@@ -143,35 +171,43 @@ class Embedphotos extends \Zotlabs\Web\Controller {
|
|||||||
'desc'=> $desc_e,
|
'desc'=> $desc_e,
|
||||||
'ext' => $ext,
|
'ext' => $ext,
|
||||||
'hash'=> $rr['resource_id'],
|
'hash'=> $rr['resource_id'],
|
||||||
'unknown' => t('Unknown')
|
'unknown' => t('Unknown'),
|
||||||
);
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$tpl = get_markup_template('photo_album.tpl');
|
$tpl = get_markup_template('photo_album.tpl');
|
||||||
$o .= replace_macros($tpl, array(
|
$o = replace_macros($tpl, [
|
||||||
'$photos' => $photos,
|
'$photos' => $photos,
|
||||||
'$album' => (($title) ? $title : $album),
|
'$album' => (($title) ? $title : $album),
|
||||||
'$album_id' => rand(),
|
'$album_id' => rand(),
|
||||||
'$album_edit' => array(t('Edit Album'), $album_edit),
|
'$album_edit' => array(t('Edit Album'), false),
|
||||||
'$can_post' => false,
|
'$can_post' => false,
|
||||||
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
|
'$upload' => array(t('Upload'), z_root() . '/photos/' . \App::$profile['channel_address'] . '/upload/' . bin2hex($album)),
|
||||||
'$order' => false,
|
'$order' => false,
|
||||||
'$upload_form' => $upload_form,
|
'$upload_form' => '',
|
||||||
'$no_fullscreen_btn' => true
|
'$no_fullscreen_btn' => true,
|
||||||
));
|
]);
|
||||||
|
|
||||||
return $o;
|
return $o;
|
||||||
}
|
}
|
||||||
|
|
||||||
function embedphotos_album_list($a) {
|
/**
|
||||||
|
* @brief Get albums observer is allowed to see.
|
||||||
|
*
|
||||||
|
* @see photos_albums_list()
|
||||||
|
*
|
||||||
|
* @return NULL|array
|
||||||
|
*/
|
||||||
|
protected function embedphotos_album_list() {
|
||||||
require_once('include/photos.php');
|
require_once('include/photos.php');
|
||||||
$p = photos_albums_list(\App::get_channel(), \App::get_observer());
|
$p = photos_albums_list(\App::get_channel(), \App::get_observer());
|
||||||
if($p['success']) {
|
|
||||||
|
if ($p['success']) {
|
||||||
return $p['albums'];
|
return $p['albums'];
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ require_once('include/bbcode.php');
|
|||||||
require_once('include/datetime.php');
|
require_once('include/datetime.php');
|
||||||
require_once('include/event.php');
|
require_once('include/event.php');
|
||||||
require_once('include/items.php');
|
require_once('include/items.php');
|
||||||
|
require_once('include/html2plain.php');
|
||||||
|
|
||||||
class Events extends \Zotlabs\Web\Controller {
|
class Events extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
function post() {
|
function post() {
|
||||||
|
|
||||||
|
// this module is deprecated
|
||||||
|
return;
|
||||||
|
|
||||||
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
|
logger('post: ' . print_r($_REQUEST,true), LOGGER_DATA);
|
||||||
|
|
||||||
@@ -97,8 +100,8 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
$type = escape_tags(trim($_POST['type']));
|
$type = escape_tags(trim($_POST['type']));
|
||||||
|
|
||||||
require_once('include/text.php');
|
require_once('include/text.php');
|
||||||
linkify_tags($a, $desc, local_channel());
|
linkify_tags($desc, local_channel());
|
||||||
linkify_tags($a, $location, local_channel());
|
linkify_tags($location, local_channel());
|
||||||
|
|
||||||
//$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
|
//$action = ($event_hash == '') ? 'new' : "event/" . $event_hash;
|
||||||
|
|
||||||
@@ -245,6 +248,9 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
|
|
||||||
function get() {
|
function get() {
|
||||||
|
|
||||||
|
// this module is deprecated
|
||||||
|
return;
|
||||||
|
|
||||||
if(argc() > 2 && argv(1) == 'ical') {
|
if(argc() > 2 && argv(1) == 'ical') {
|
||||||
$event_id = argv(2);
|
$event_id = argv(2);
|
||||||
@@ -271,8 +277,10 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\App::$profile_uid = local_channel();
|
||||||
nav_set_selected('Events');
|
nav_set_selected('Events');
|
||||||
|
|
||||||
|
|
||||||
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
|
if((argc() > 2) && (argv(1) === 'ignore') && intval(argv(2))) {
|
||||||
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
|
$r = q("update event set dismissed = 1 where id = %d and uid = %d",
|
||||||
@@ -288,7 +296,7 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$first_day = get_pconfig(local_channel(),'system','cal_first_day');
|
$first_day = feature_enabled(local_channel(), 'events_cal_first_day');
|
||||||
$first_day = (($first_day) ? $first_day : 0);
|
$first_day = (($first_day) ? $first_day : 0);
|
||||||
|
|
||||||
$htpl = get_markup_template('event_head.tpl');
|
$htpl = get_markup_template('event_head.tpl');
|
||||||
@@ -641,6 +649,7 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
$html = format_event_html($rr);
|
$html = format_event_html($rr);
|
||||||
$rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
|
$rr['desc'] = zidify_links(smilies(bbcode($rr['desc'])));
|
||||||
|
$rr['description'] = htmlentities(html2plain(bbcode($rr['description'])),ENT_COMPAT,'UTF-8',false);
|
||||||
$rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
|
$rr['location'] = zidify_links(smilies(bbcode($rr['location'])));
|
||||||
$events[] = array(
|
$events[] = array(
|
||||||
'id'=>$rr['id'],
|
'id'=>$rr['id'],
|
||||||
@@ -659,11 +668,10 @@ class Events extends \Zotlabs\Web\Controller {
|
|||||||
'html'=>$html,
|
'html'=>$html,
|
||||||
'plink' => array($rr['plink'],t('Link to Source'),'',''),
|
'plink' => array($rr['plink'],t('Link to Source'),'',''),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($export) {
|
if($export) {
|
||||||
header('Content-type: text/calendar');
|
header('Content-type: text/calendar');
|
||||||
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
|
header('content-disposition: attachment; filename="' . t('calendar') . '-' . $channel['channel_address'] . '.ics"' );
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ namespace Zotlabs\Module;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Filestorage extends \Zotlabs\Web\Controller {
|
class Filestorage extends \Zotlabs\Web\Controller {
|
||||||
|
|
||||||
function post() {
|
function post() {
|
||||||
@@ -71,14 +73,6 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
|
|
||||||
// need to return for anyone other than the owner, despite the perms check for now.
|
|
||||||
|
|
||||||
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
|
|
||||||
if(! ($is_owner || is_site_admin())){
|
|
||||||
info( t('Permission Denied.') . EOL );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(argc() > 3 && argv(3) === 'delete') {
|
if(argc() > 3 && argv(3) === 'delete') {
|
||||||
|
|
||||||
@@ -101,18 +95,31 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$file = intval(argv(2));
|
$file = intval(argv(2));
|
||||||
$r = q("SELECT hash FROM attach WHERE id = %d AND uid = %d LIMIT 1",
|
$r = q("SELECT hash, creator FROM attach WHERE id = %d AND uid = %d LIMIT 1",
|
||||||
dbesc($file),
|
dbesc($file),
|
||||||
intval($owner)
|
intval($owner)
|
||||||
);
|
);
|
||||||
if(! $r) {
|
if(! $r) {
|
||||||
|
notice( t('File not found.') . EOL);
|
||||||
|
|
||||||
if($json_return)
|
if($json_return)
|
||||||
json_return_and_die([ 'success' => false ]);
|
json_return_and_die([ 'success' => false ]);
|
||||||
|
|
||||||
notice( t('File not found.') . EOL);
|
|
||||||
goaway(z_root() . '/cloud/' . $which);
|
goaway(z_root() . '/cloud/' . $which);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(local_channel() !== $owner) {
|
||||||
|
if($r[0]['creator'] && $r[0]['creator'] !== $ob_hash) {
|
||||||
|
notice( t('Permission denied.') . EOL);
|
||||||
|
|
||||||
|
if($json_return)
|
||||||
|
json_return_and_die([ 'success' => false ]);
|
||||||
|
|
||||||
|
goaway(z_root() . '/cloud/' . $which);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$f = $r[0];
|
$f = $r[0];
|
||||||
|
|
||||||
$channel = channelx_by_n($owner);
|
$channel = channelx_by_n($owner);
|
||||||
@@ -128,12 +135,25 @@ class Filestorage extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(json_return)
|
if($json_return)
|
||||||
json_return_and_die([ 'success' => true ]);
|
json_return_and_die([ 'success' => true ]);
|
||||||
|
|
||||||
goaway(dirname($url));
|
goaway(dirname($url));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Since we have ACL'd files in the wild, but don't have ACL here yet, we
|
||||||
|
// need to return for anyone other than the owner, despite the perms check for now.
|
||||||
|
|
||||||
|
$is_owner = (((local_channel()) && ($owner == local_channel())) ? true : false);
|
||||||
|
if(! ($is_owner || is_site_admin())){
|
||||||
|
info( t('Permission Denied.') . EOL );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if(argc() > 3 && argv(3) === 'edit') {
|
if(argc() > 3 && argv(3) === 'edit') {
|
||||||
require_once('include/acl_selectors.php');
|
require_once('include/acl_selectors.php');
|
||||||
if(! $perms['write_storage']) {
|
if(! $perms['write_storage']) {
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use Zotlabs\Web\HTTPSig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* module: getfile
|
* module: getfile
|
||||||
*
|
*
|
||||||
@@ -35,7 +37,6 @@ class Getfile extends \Zotlabs\Web\Controller {
|
|||||||
$sig = $_POST['signature'];
|
$sig = $_POST['signature'];
|
||||||
$resource = $_POST['resource'];
|
$resource = $_POST['resource'];
|
||||||
$revision = intval($_POST['revision']);
|
$revision = intval($_POST['revision']);
|
||||||
$resolution = (-1);
|
|
||||||
|
|
||||||
if(! $hash)
|
if(! $hash)
|
||||||
killme();
|
killme();
|
||||||
@@ -47,7 +48,7 @@ class Getfile extends \Zotlabs\Web\Controller {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$sigblock = \Zotlabs\Web\HTTPSig::parse_sigheader($_SERVER[$head]);
|
$sigblock = HTTPSig::parse_sigheader($_SERVER[$head]);
|
||||||
if($sigblock) {
|
if($sigblock) {
|
||||||
$keyId = $sigblock['keyId'];
|
$keyId = $sigblock['keyId'];
|
||||||
|
|
||||||
@@ -58,7 +59,7 @@ class Getfile extends \Zotlabs\Web\Controller {
|
|||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
$hubloc = $r[0];
|
$hubloc = $r[0];
|
||||||
$verified = \Zotlabs\Web\HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
$verified = HTTPSig::verify('',$hubloc['xchan_pubkey']);
|
||||||
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
if($verified && $verified['header_signed'] && $verified['header_valid'] && $hash == $hubloc['hubloc_hash']) {
|
||||||
$header_verified = true;
|
$header_verified = true;
|
||||||
}
|
}
|
||||||
@@ -81,9 +82,14 @@ class Getfile extends \Zotlabs\Web\Controller {
|
|||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(substr($resource,-2,1) == '-') {
|
if(isset($_POST['resolution']))
|
||||||
|
$resolution = intval($_POST['resolution']);
|
||||||
|
elseif(substr($resource,-2,1) == '-') {
|
||||||
$resolution = intval(substr($resource,-1,1));
|
$resolution = intval(substr($resource,-1,1));
|
||||||
$resource = substr($resource,0,-2);
|
$resource = substr($resource,0,-2);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$resolution = (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
|
$slop = intval(get_pconfig($channel['channel_id'],'system','getfile_time_slop'));
|
||||||
@@ -106,9 +112,10 @@ class Getfile extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($resolution > 0) {
|
if($resolution > 0) {
|
||||||
$r = q("select * from photo where resource_id = '%s' and uid = %d limit 1",
|
$r = q("SELECT * FROM photo WHERE resource_id = '%s' AND uid = %d AND imgscale = %d LIMIT 1",
|
||||||
dbesc($resource),
|
dbesc($resource),
|
||||||
intval($channel['channel_id'])
|
intval($channel['channel_id']),
|
||||||
|
$resolution
|
||||||
);
|
);
|
||||||
if($r) {
|
if($r) {
|
||||||
header('Content-type: ' . $r[0]['mimetype']);
|
header('Content-type: ' . $r[0]['mimetype']);
|
||||||
|
|||||||
+49
-11
@@ -1,11 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Zotlabs\Module;
|
namespace Zotlabs\Module;
|
||||||
|
|
||||||
|
use App;
|
||||||
|
use Zotlabs\Web\Controller;
|
||||||
|
use Zotlabs\Lib\Apps;
|
||||||
|
|
||||||
require_once('include/group.php');
|
require_once('include/group.php');
|
||||||
|
|
||||||
|
class Group extends Controller {
|
||||||
|
|
||||||
class Group extends \Zotlabs\Web\Controller {
|
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
if(! local_channel()) {
|
if(! local_channel()) {
|
||||||
@@ -13,7 +15,11 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
\App::$profile_uid = local_channel();
|
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
App::$profile_uid = local_channel();
|
||||||
|
|
||||||
nav_set_selected('Privacy Groups');
|
nav_set_selected('Privacy Groups');
|
||||||
}
|
}
|
||||||
@@ -24,6 +30,10 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
notice( t('Permission denied.') . EOL);
|
notice( t('Permission denied.') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if((argc() == 2) && (argv(1) === 'new')) {
|
if((argc() == 2) && (argv(1) === 'new')) {
|
||||||
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
|
check_form_security_token_redirectOnErr('/group/new', 'group_edit');
|
||||||
@@ -43,7 +53,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
if((argc() == 2) && (intval(argv(1)))) {
|
if((argc() == 2) && (intval(argv(1)))) {
|
||||||
check_form_security_token_redirectOnErr('/group', 'group_edit');
|
check_form_security_token_redirectOnErr('/group', 'group_edit');
|
||||||
|
|
||||||
$r = q("SELECT * FROM groups WHERE id = %d AND uid = %d LIMIT 1",
|
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
|
||||||
intval(argv(1)),
|
intval(argv(1)),
|
||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
@@ -56,8 +66,11 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
$groupname = notags(trim($_POST['groupname']));
|
$groupname = notags(trim($_POST['groupname']));
|
||||||
$public = intval($_POST['public']);
|
$public = intval($_POST['public']);
|
||||||
|
|
||||||
|
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
|
||||||
|
call_hooks ('privacygroup_extras_post',$hookinfo);
|
||||||
|
|
||||||
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
|
if((strlen($groupname)) && (($groupname != $group['gname']) || ($public != $group['visible']))) {
|
||||||
$r = q("UPDATE groups SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
|
$r = q("UPDATE pgrp SET gname = '%s', visible = %d WHERE uid = %d AND id = %d",
|
||||||
dbesc($groupname),
|
dbesc($groupname),
|
||||||
intval($public),
|
intval($public),
|
||||||
intval(local_channel()),
|
intval(local_channel()),
|
||||||
@@ -65,6 +78,8 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
);
|
);
|
||||||
if($r)
|
if($r)
|
||||||
info( t('Privacy group updated.') . EOL );
|
info( t('Privacy group updated.') . EOL );
|
||||||
|
|
||||||
|
|
||||||
build_sync_packet(local_channel(),null,true);
|
build_sync_packet(local_channel(),null,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +92,22 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$change = false;
|
$change = false;
|
||||||
|
|
||||||
logger('mod_group: ' . \App::$cmd,LOGGER_DEBUG);
|
logger('mod_group: ' . App::$cmd,LOGGER_DEBUG);
|
||||||
|
|
||||||
if(! local_channel()) {
|
if(! local_channel()) {
|
||||||
notice( t('Permission denied') . EOL);
|
notice( t('Permission denied') . EOL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(! Apps::system_app_installed(local_channel(), 'Privacy Groups')) {
|
||||||
|
//Do not display any associated widgets at this point
|
||||||
|
App::$pdl = '';
|
||||||
|
|
||||||
|
$o = '<b>' . t('Privacy Groups App') . ' (' . t('Not Installed') . '):</b><br>';
|
||||||
|
$o .= t('Management of privacy groups');
|
||||||
|
return $o;
|
||||||
|
}
|
||||||
|
|
||||||
// Switch to text mode interface if we have more than 'n' contacts or group members
|
// Switch to text mode interface if we have more than 'n' contacts or group members
|
||||||
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
|
$switchtotext = get_pconfig(local_channel(),'system','groupedit_image_limit');
|
||||||
if($switchtotext === false)
|
if($switchtotext === false)
|
||||||
@@ -96,7 +120,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
|
$new = (((argc() == 2) && (argv(1) === 'new')) ? true : false);
|
||||||
|
|
||||||
$groups = q("SELECT id, gname FROM groups WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
$groups = q("SELECT id, gname FROM pgrp WHERE deleted = 0 AND uid = %d ORDER BY gname ASC",
|
||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -108,6 +132,10 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hookinfo = [ 'pgrp_extras' => '', 'group'=>argv(1) ];
|
||||||
|
call_hooks ('privacygroup_extras',$hookinfo);
|
||||||
|
$pgrp_extras = $hookinfo['pgrp_extras'];
|
||||||
|
|
||||||
$tpl = get_markup_template('privacy_groups.tpl');
|
$tpl = get_markup_template('privacy_groups.tpl');
|
||||||
$o = replace_macros($tpl, [
|
$o = replace_macros($tpl, [
|
||||||
'$title' => t('Privacy Groups'),
|
'$title' => t('Privacy Groups'),
|
||||||
@@ -117,6 +145,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
// new group form
|
// new group form
|
||||||
'$gname' => array('groupname',t('Privacy group name')),
|
'$gname' => array('groupname',t('Privacy group name')),
|
||||||
'$public' => array('public',t('Members are visible to other channels'), false),
|
'$public' => array('public',t('Members are visible to other channels'), false),
|
||||||
|
'$pgrp_extras' => $pgrp_extras,
|
||||||
'$form_security_token' => get_form_security_token("group_edit"),
|
'$form_security_token' => get_form_security_token("group_edit"),
|
||||||
'$submit' => t('Submit'),
|
'$submit' => t('Submit'),
|
||||||
|
|
||||||
@@ -141,14 +170,17 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
|
check_form_security_token_redirectOnErr('/group', 'group_drop', 't');
|
||||||
|
|
||||||
if(intval(argv(2))) {
|
if(intval(argv(2))) {
|
||||||
$r = q("SELECT gname FROM groups WHERE id = %d AND uid = %d LIMIT 1",
|
$r = q("SELECT gname FROM pgrp WHERE id = %d AND uid = %d LIMIT 1",
|
||||||
intval(argv(2)),
|
intval(argv(2)),
|
||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
if($r)
|
if($r)
|
||||||
$result = group_rmv(local_channel(),$r[0]['gname']);
|
$result = group_rmv(local_channel(),$r[0]['gname']);
|
||||||
if($result)
|
if($result) {
|
||||||
|
$hookinfo = [ 'pgrp_extras' => '', 'group' => argv(2) ];
|
||||||
|
call_hooks ('privacygroup_extras_drop',$hookinfo);
|
||||||
info( t('Privacy group removed.') . EOL);
|
info( t('Privacy group removed.') . EOL);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
notice( t('Unable to remove privacy group.') . EOL);
|
notice( t('Unable to remove privacy group.') . EOL);
|
||||||
}
|
}
|
||||||
@@ -173,7 +205,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
if((argc() > 1) && (intval(argv(1)))) {
|
if((argc() > 1) && (intval(argv(1)))) {
|
||||||
|
|
||||||
require_once('include/acl_selectors.php');
|
require_once('include/acl_selectors.php');
|
||||||
$r = q("SELECT * FROM groups WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
|
$r = q("SELECT * FROM pgrp WHERE id = %d AND uid = %d AND deleted = 0 LIMIT 1",
|
||||||
intval(argv(1)),
|
intval(argv(1)),
|
||||||
intval(local_channel())
|
intval(local_channel())
|
||||||
);
|
);
|
||||||
@@ -211,6 +243,10 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hookinfo = [ 'pgrp_extras' => '', 'group'=>$group['id'] ];
|
||||||
|
call_hooks ('privacygroup_extras',$hookinfo);
|
||||||
|
$pgrp_extras = $hookinfo['pgrp_extras'];
|
||||||
|
|
||||||
$context = $context + array(
|
$context = $context + array(
|
||||||
'$title' => sprintf(t('Privacy Group: %s'), $group['gname']),
|
'$title' => sprintf(t('Privacy Group: %s'), $group['gname']),
|
||||||
'$details_label' => t('Edit'),
|
'$details_label' => t('Edit'),
|
||||||
@@ -221,6 +257,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
'$form_security_token_edit' => get_form_security_token('group_edit'),
|
'$form_security_token_edit' => get_form_security_token('group_edit'),
|
||||||
'$delete' => t('Delete Group'),
|
'$delete' => t('Delete Group'),
|
||||||
'$form_security_token_drop' => get_form_security_token("group_drop"),
|
'$form_security_token_drop' => get_form_security_token("group_drop"),
|
||||||
|
'$pgrp_extras' => $pgrp_extras,
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -264,6 +301,7 @@ class Group extends \Zotlabs\Web\Controller {
|
|||||||
|
|
||||||
$context['$groupeditor'] = $groupeditor;
|
$context['$groupeditor'] = $groupeditor;
|
||||||
$context['$desc'] = t('Click a channel to toggle membership');
|
$context['$desc'] = t('Click a channel to toggle membership');
|
||||||
|
$context['$pgrp_extras'] = $pgrp_extras;
|
||||||
|
|
||||||
if($change) {
|
if($change) {
|
||||||
$tpl = get_markup_template('groupeditor.tpl');
|
$tpl = get_markup_template('groupeditor.tpl');
|
||||||
|
|||||||
@@ -13,14 +13,12 @@ class Home extends \Zotlabs\Web\Controller {
|
|||||||
$ret = array();
|
$ret = array();
|
||||||
|
|
||||||
call_hooks('home_init',$ret);
|
call_hooks('home_init',$ret);
|
||||||
|
|
||||||
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
|
$splash = ((argc() > 1 && argv(1) === 'splash') ? true : false);
|
||||||
|
|
||||||
$channel = \App::get_channel();
|
$channel = \App::get_channel();
|
||||||
if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) {
|
if(local_channel() && $channel && $channel['xchan_url'] && ! $splash) {
|
||||||
$dest = $channel['channel_startpage'];
|
$dest = (($ret['startpage']) ? $ret['startpage'] : '');
|
||||||
if(! $dest)
|
|
||||||
$dest = get_pconfig(local_channel(),'system','startpage');
|
|
||||||
if(! $dest)
|
if(! $dest)
|
||||||
$dest = get_config('system','startpage');
|
$dest = get_config('system','startpage');
|
||||||
if(! $dest)
|
if(! $dest)
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
|||||||
[
|
[
|
||||||
'$no_messages' => (($target_item) ? false : true),
|
'$no_messages' => (($target_item) ? false : true),
|
||||||
'$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ],
|
'$no_messages_label' => [ t('Welcome to Hubzilla!'), t('You have got no unseen posts...') ],
|
||||||
'$editor' => status_editor($a,$x)
|
'$editor' => status_editor($a,$x,false,'Hq')
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@ class Hq extends \Zotlabs\Web\Controller {
|
|||||||
'$dbegin' => '',
|
'$dbegin' => '',
|
||||||
'$verb' => '',
|
'$verb' => '',
|
||||||
'$net' => '',
|
'$net' => '',
|
||||||
'$mid' => $mid
|
'$mid' => (($mid) ? urlencode($mid) : '')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user