boot.php 69 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442
  1. <?php
  2. /** @file boot.php
  3. *
  4. * This file defines some global constants and includes the central App class.
  5. */
  6. /**
  7. * Hubzilla.
  8. *
  9. * Hubzilla is an open source decentralised communications
  10. * platform combined with a decentralised identity/authentication framework
  11. * wrapped in an extensible content management system, providing website designers
  12. * the ability to embed fully decentralised communications and social tools
  13. * into many traditional website designs (blogs, forums, small business
  14. * websites, charitable organisations, etc.). Hubzilla also provides DNS mobility
  15. * and internet scale privacy/access control.
  16. *
  17. * This allows any individual website to participate in a matrix of linked
  18. * sites and people and media sharing which is far greater than the reach
  19. * of an individual site.
  20. *
  21. * If you are reading the source code and come across a function
  22. * or code block which is not documented, but you have a good idea what it
  23. * does, please add some descriptive comments and push it to the main project.
  24. * Even if your description isn't perfect, it gives us a base which we
  25. * can build on and correct - so that eventually everything is fully
  26. * documented.
  27. */
  28. require_once('include/config.php');
  29. require_once('include/network.php');
  30. require_once('include/plugin.php');
  31. require_once('include/text.php');
  32. require_once('include/datetime.php');
  33. require_once('include/language.php');
  34. require_once('include/nav.php');
  35. require_once('include/cache.php');
  36. require_once('include/permissions.php');
  37. require_once('library/Mobile_Detect/Mobile_Detect.php');
  38. require_once('include/BaseObject.php');
  39. require_once('include/features.php');
  40. require_once('include/taxonomy.php');
  41. require_once('include/identity.php');
  42. require_once('include/Contact.php');
  43. require_once('include/account.php');
  44. define ( 'PLATFORM_NAME', 'hubzilla' );
  45. define ( 'RED_VERSION', trim(file_get_contents('version.inc')));
  46. define ( 'STD_VERSION', '1.4' );
  47. define ( 'ZOT_REVISION', 1 );
  48. define ( 'DB_UPDATE_VERSION', 1165 );
  49. /**
  50. * @brief Constant with a HTML line break.
  51. *
  52. * Contains a HTML line break (br) element and a real carriage return with line
  53. * feed for the source.
  54. * This can be used in HTML and JavaScript where needed a line break.
  55. */
  56. define ( 'EOL', '<br>' . "\r\n" );
  57. define ( 'ATOM_TIME', 'Y-m-d\TH:i:s\Z' );
  58. //define ( 'NULL_DATE', '0000-00-00 00:00:00' );
  59. define ( 'TEMPLATE_BUILD_PATH', 'store/[data]/smarty3' );
  60. define ( 'DIRECTORY_MODE_NORMAL', 0x0000); // A directory client
  61. define ( 'DIRECTORY_MODE_PRIMARY', 0x0001); // There can only be *one* primary directory server in a directory_realm.
  62. define ( 'DIRECTORY_MODE_SECONDARY', 0x0002); // All other mirror directory servers
  63. define ( 'DIRECTORY_MODE_STANDALONE', 0x0100); // A detached (off the grid) hub with itself as directory server.
  64. // We will look for upstream directories whenever me make contact
  65. // with other sites, but if this is a new installation and isn't
  66. // a standalone hub, we need to seed the service with a starting
  67. // point to go out and find the rest of the world.
  68. define ( 'DIRECTORY_REALM', 'RED_GLOBAL');
  69. define ( 'DIRECTORY_FALLBACK_MASTER', 'https://hub.pixelbits.de');
  70. $DIRECTORY_FALLBACK_SERVERS = array(
  71. 'https://hubzilla.site',
  72. 'https://hubzilla.zottel.net',
  73. 'https://hub.pixelbits.de',
  74. 'https://my.federated.social',
  75. 'https://hubzilla.nl',
  76. 'https://blablanet.es'
  77. );
  78. /**
  79. *
  80. * Image storage quality. Lower numbers save space at cost of image detail.
  81. * For ease of upgrade, please do not change here. Change jpeg quality with
  82. * App::$config['system']['jpeg_quality'] = n;
  83. * in .htconfig.php, where n is netween 1 and 100, and with very poor results
  84. * below about 50
  85. *
  86. */
  87. define ( 'JPEG_QUALITY', 100 );
  88. /**
  89. * App::$config['system']['png_quality'] from 0 (uncompressed) to 9
  90. */
  91. define ( 'PNG_QUALITY', 8 );
  92. /**
  93. * Language detection parameters
  94. */
  95. define ( 'LANGUAGE_DETECT_MIN_LENGTH', 128 );
  96. define ( 'LANGUAGE_DETECT_MIN_CONFIDENCE', 0.01 );
  97. /**
  98. * Default permissions for file-based storage (webDAV, etc.)
  99. * These files will be owned by the webserver who will need write
  100. * access to the "storage" folder.
  101. * Ideally you should make this 700, however some hosted platforms
  102. * may not let you change ownership of this directory so we're
  103. * defaulting to both owner-write and group-write privilege.
  104. * This should work for most cases without modification.
  105. * Over-ride this in your .htconfig.php if you need something
  106. * either more or less restrictive.
  107. */
  108. define ( 'STORAGE_DEFAULT_PERMISSIONS', 0770 );
  109. /**
  110. *
  111. * An alternate way of limiting picture upload sizes. Specify the maximum pixel
  112. * length that pictures are allowed to be (for non-square pictures, it will apply
  113. * to the longest side). Pictures longer than this length will be resized to be
  114. * this length (on the longest side, the other side will be scaled appropriately).
  115. * Modify this value using
  116. *
  117. * App::$config['system']['max_image_length'] = n;
  118. *
  119. * in .htconfig.php
  120. *
  121. * If you don't want to set a maximum length, set to -1. The default value is
  122. * defined by 'MAX_IMAGE_LENGTH' below.
  123. *
  124. */
  125. define ( 'MAX_IMAGE_LENGTH', -1 );
  126. /**
  127. * Not yet used
  128. */
  129. define ( 'DEFAULT_DB_ENGINE', 'MyISAM' );
  130. /**
  131. * SSL redirection policies
  132. */
  133. define ( 'SSL_POLICY_NONE', 0 );
  134. define ( 'SSL_POLICY_FULL', 1 );
  135. define ( 'SSL_POLICY_SELFSIGN', 2 ); // NOT supported in Red
  136. /**
  137. * log levels
  138. */
  139. define ( 'LOGGER_NORMAL', 0 );
  140. define ( 'LOGGER_TRACE', 1 );
  141. define ( 'LOGGER_DEBUG', 2 );
  142. define ( 'LOGGER_DATA', 3 );
  143. define ( 'LOGGER_ALL', 4 );
  144. /**
  145. * registration policies
  146. */
  147. define ( 'REGISTER_CLOSED', 0 );
  148. define ( 'REGISTER_APPROVE', 1 );
  149. define ( 'REGISTER_OPEN', 2 );
  150. /**
  151. * site access policy
  152. */
  153. define ( 'ACCESS_PRIVATE', 0 );
  154. define ( 'ACCESS_PAID', 1 );
  155. define ( 'ACCESS_FREE', 2 );
  156. define ( 'ACCESS_TIERED', 3 );
  157. /**
  158. * relationship types
  159. */
  160. define ( 'CONTACT_IS_FOLLOWER', 1);
  161. define ( 'CONTACT_IS_SHARING', 2);
  162. define ( 'CONTACT_IS_FRIEND', 3);
  163. /**
  164. * DB update return values
  165. */
  166. define ( 'UPDATE_SUCCESS', 0);
  167. define ( 'UPDATE_FAILED', 1);
  168. define ( 'CLIENT_MODE_NORMAL', 0x0000);
  169. define ( 'CLIENT_MODE_LOAD', 0x0001);
  170. define ( 'CLIENT_MODE_UPDATE', 0x0002);
  171. /**
  172. *
  173. * Channel pageflags
  174. *
  175. */
  176. define ( 'PAGE_NORMAL', 0x0000 );
  177. define ( 'PAGE_HIDDEN', 0x0001 );
  178. define ( 'PAGE_AUTOCONNECT', 0x0002 );
  179. define ( 'PAGE_APPLICATION', 0x0004 );
  180. define ( 'PAGE_ALLOWCODE', 0x0008 );
  181. define ( 'PAGE_PREMIUM', 0x0010 );
  182. define ( 'PAGE_ADULT', 0x0020 );
  183. define ( 'PAGE_CENSORED', 0x0040 ); // Site admin has blocked this channel from appearing in casual search results and site feeds
  184. define ( 'PAGE_SYSTEM', 0x1000 );
  185. define ( 'PAGE_HUBADMIN', 0x2000 ); // set this to indicate a preferred admin channel rather than the
  186. // default channel of any accounts with the admin role.
  187. define ( 'PAGE_REMOVED', 0x8000 );
  188. /**
  189. * Photo usage types
  190. */
  191. define ( 'PHOTO_NORMAL', 0x0000 );
  192. define ( 'PHOTO_PROFILE', 0x0001 );
  193. define ( 'PHOTO_XCHAN', 0x0002 );
  194. define ( 'PHOTO_THING', 0x0004 );
  195. define ( 'PHOTO_COVER', 0x0010 );
  196. define ( 'PHOTO_ADULT', 0x0008 );
  197. define ( 'PHOTO_FLAG_OS', 0x4000 );
  198. define ( 'PHOTO_RES_ORIG', 0 );
  199. define ( 'PHOTO_RES_1024', 1 ); // rectangular 1024 max width or height, floating height if not (4:3)
  200. define ( 'PHOTO_RES_640', 2 ); // to accomodate SMBC vertical comic strips without scrunching the width
  201. define ( 'PHOTO_RES_320', 3 ); // accordingly
  202. define ( 'PHOTO_RES_PROFILE_300', 4 ); // square 300 px
  203. define ( 'PHOTO_RES_PROFILE_80', 5 ); // square 80 px
  204. define ( 'PHOTO_RES_PROFILE_48', 6 ); // square 48 px
  205. define ( 'PHOTO_RES_COVER_1200', 7 ); // 1200w x 435h (2.75:1)
  206. define ( 'PHOTO_RES_COVER_850', 8 ); // 850w x 310h
  207. define ( 'PHOTO_RES_COVER_425', 9 ); // 425w x 160h
  208. /**
  209. * Menu types
  210. */
  211. define ( 'MENU_SYSTEM', 0x0001 );
  212. define ( 'MENU_BOOKMARK', 0x0002 );
  213. /**
  214. * Network and protocol family types
  215. */
  216. define ( 'NETWORK_FRND', 'friendica-over-diaspora'); // Friendica, Mistpark, other DFRN implementations
  217. define ( 'NETWORK_DFRN', 'dfrn'); // Friendica, Mistpark, other DFRN implementations
  218. define ( 'NETWORK_ZOT', 'zot'); // Zot!
  219. define ( 'NETWORK_OSTATUS', 'stat'); // status.net, identi.ca, GNU-social, other OStatus implementations
  220. define ( 'NETWORK_GNUSOCIAL', 'gnusoc'); // status.net, identi.ca, GNU-social, other OStatus implementations
  221. define ( 'NETWORK_FEED', 'rss'); // RSS/Atom feeds with no known "post/notify" protocol
  222. define ( 'NETWORK_DIASPORA', 'diaspora'); // Diaspora
  223. define ( 'NETWORK_MAIL', 'mail'); // IMAP/POP
  224. define ( 'NETWORK_MAIL2', 'mai2'); // extended IMAP/POP
  225. define ( 'NETWORK_FACEBOOK', 'face'); // Facebook API
  226. define ( 'NETWORK_LINKEDIN', 'lnkd'); // LinkedIn
  227. define ( 'NETWORK_XMPP', 'xmpp'); // XMPP
  228. define ( 'NETWORK_MYSPACE', 'mysp'); // MySpace
  229. define ( 'NETWORK_GPLUS', 'goog'); // Google+
  230. define ( 'NETWORK_PHANTOM', 'unkn'); // Place holder
  231. /**
  232. * Permissions
  233. */
  234. define ( 'PERMS_R_STREAM', 0x00001);
  235. define ( 'PERMS_R_PROFILE', 0x00002);
  236. define ( 'PERMS_R_PHOTOS', 0x00004);
  237. define ( 'PERMS_R_ABOOK', 0x00008);
  238. define ( 'PERMS_W_STREAM', 0x00010);
  239. define ( 'PERMS_W_WALL', 0x00020);
  240. define ( 'PERMS_W_TAGWALL', 0x00040);
  241. define ( 'PERMS_W_COMMENT', 0x00080);
  242. define ( 'PERMS_W_MAIL', 0x00100);
  243. define ( 'PERMS_W_PHOTOS', 0x00200);
  244. define ( 'PERMS_W_CHAT', 0x00400);
  245. define ( 'PERMS_A_DELEGATE', 0x00800);
  246. define ( 'PERMS_R_STORAGE', 0x01000);
  247. define ( 'PERMS_W_STORAGE', 0x02000);
  248. define ( 'PERMS_R_PAGES', 0x04000);
  249. define ( 'PERMS_W_PAGES', 0x08000);
  250. define ( 'PERMS_A_REPUBLISH', 0x10000);
  251. define ( 'PERMS_W_LIKE', 0x20000);
  252. // General channel permissions
  253. define ( 'PERMS_PUBLIC' , 0x0001 );
  254. define ( 'PERMS_NETWORK' , 0x0002 );
  255. define ( 'PERMS_SITE' , 0x0004 );
  256. define ( 'PERMS_CONTACTS' , 0x0008 );
  257. define ( 'PERMS_SPECIFIC' , 0x0080 );
  258. define ( 'PERMS_AUTHED' , 0x0100 );
  259. define ( 'PERMS_PENDING' , 0x0200 );
  260. // Address book flags
  261. define ( 'ABOOK_FLAG_BLOCKED' , 0x0001);
  262. define ( 'ABOOK_FLAG_IGNORED' , 0x0002);
  263. define ( 'ABOOK_FLAG_HIDDEN' , 0x0004);
  264. define ( 'ABOOK_FLAG_ARCHIVED' , 0x0008);
  265. define ( 'ABOOK_FLAG_PENDING' , 0x0010);
  266. define ( 'ABOOK_FLAG_UNCONNECTED', 0x0020);
  267. define ( 'ABOOK_FLAG_SELF' , 0x0080);
  268. define ( 'ABOOK_FLAG_FEED' , 0x0100);
  269. define ( 'MAIL_DELETED', 0x0001);
  270. define ( 'MAIL_REPLIED', 0x0002);
  271. define ( 'MAIL_ISREPLY', 0x0004);
  272. define ( 'MAIL_SEEN', 0x0008);
  273. define ( 'MAIL_RECALLED', 0x0010);
  274. define ( 'MAIL_OBSCURED', 0x0020);
  275. define ( 'ATTACH_FLAG_DIR', 0x0001);
  276. define ( 'ATTACH_FLAG_OS', 0x0002);
  277. define ( 'MENU_ITEM_ZID', 0x0001);
  278. define ( 'MENU_ITEM_NEWWIN', 0x0002);
  279. define ( 'MENU_ITEM_CHATROOM', 0x0004);
  280. define ( 'SITE_TYPE_ZOT', 0);
  281. define ( 'SITE_TYPE_NOTZOT', 1);
  282. define ( 'SITE_TYPE_UNKNOWN', 2);
  283. /**
  284. * Poll/Survey types
  285. */
  286. define ( 'POLL_SIMPLE_RATING', 0x0001); // 1-5
  287. define ( 'POLL_TENSCALE', 0x0002); // 1-10
  288. define ( 'POLL_MULTIPLE_CHOICE', 0x0004);
  289. define ( 'POLL_OVERWRITE', 0x8000); // If you vote twice remove the prior entry
  290. define ( 'UPDATE_FLAGS_UPDATED', 0x0001);
  291. define ( 'UPDATE_FLAGS_FORCED', 0x0002);
  292. define ( 'UPDATE_FLAGS_DELETED', 0x1000);
  293. define ( 'DROPITEM_NORMAL', 0);
  294. define ( 'DROPITEM_PHASE1', 1);
  295. define ( 'DROPITEM_PHASE2', 2);
  296. /**
  297. * Maximum number of "people who like (or don't like) this" that we will list by name
  298. */
  299. define ( 'MAX_LIKERS', 10);
  300. /**
  301. * Communication timeout
  302. */
  303. define ( 'ZCURL_TIMEOUT' , (-1));
  304. /**
  305. * email notification options
  306. */
  307. define ( 'NOTIFY_INTRO', 0x0001 );
  308. define ( 'NOTIFY_CONFIRM', 0x0002 );
  309. define ( 'NOTIFY_WALL', 0x0004 );
  310. define ( 'NOTIFY_COMMENT', 0x0008 );
  311. define ( 'NOTIFY_MAIL', 0x0010 );
  312. define ( 'NOTIFY_SUGGEST', 0x0020 );
  313. define ( 'NOTIFY_PROFILE', 0x0040 );
  314. define ( 'NOTIFY_TAGSELF', 0x0080 );
  315. define ( 'NOTIFY_TAGSHARE', 0x0100 );
  316. define ( 'NOTIFY_POKE', 0x0200 );
  317. define ( 'NOTIFY_SYSTEM', 0x8000 );
  318. /**
  319. * visual notification options
  320. */
  321. define ( 'VNOTIFY_NETWORK', 0x0001 );
  322. define ( 'VNOTIFY_CHANNEL', 0x0002 );
  323. define ( 'VNOTIFY_MAIL', 0x0004 );
  324. define ( 'VNOTIFY_EVENT', 0x0008 );
  325. define ( 'VNOTIFY_EVENTTODAY', 0x0010 );
  326. define ( 'VNOTIFY_BIRTHDAY', 0x0020 );
  327. define ( 'VNOTIFY_SYSTEM', 0x0040 );
  328. define ( 'VNOTIFY_INFO', 0x0080 );
  329. define ( 'VNOTIFY_ALERT', 0x0100 );
  330. define ( 'VNOTIFY_INTRO', 0x0200 );
  331. define ( 'VNOTIFY_REGISTER', 0x0400 );
  332. /**
  333. * Tag/term types
  334. */
  335. define ( 'TERM_UNKNOWN', 0 );
  336. define ( 'TERM_HASHTAG', 1 );
  337. define ( 'TERM_MENTION', 2 );
  338. define ( 'TERM_CATEGORY', 3 );
  339. define ( 'TERM_PCATEGORY', 4 );
  340. define ( 'TERM_FILE', 5 );
  341. define ( 'TERM_SAVEDSEARCH', 6 );
  342. define ( 'TERM_THING', 7 );
  343. define ( 'TERM_BOOKMARK', 8 );
  344. define ( 'TERM_HIERARCHY', 9 );
  345. define ( 'TERM_COMMUNITYTAG', 10 );
  346. define ( 'TERM_OBJ_POST', 1 );
  347. define ( 'TERM_OBJ_PHOTO', 2 );
  348. define ( 'TERM_OBJ_PROFILE', 3 );
  349. define ( 'TERM_OBJ_CHANNEL', 4 );
  350. define ( 'TERM_OBJ_OBJECT', 5 );
  351. define ( 'TERM_OBJ_THING', 6 );
  352. define ( 'TERM_OBJ_APP', 7 );
  353. /**
  354. * various namespaces we may need to parse
  355. */
  356. define ( 'PROTOCOL_ZOT', 'http://purl.org/zot/protocol' );
  357. define ( 'NAMESPACE_ZOT', 'http://purl.org/zot' );
  358. define ( 'NAMESPACE_DFRN' , 'http://purl.org/macgirvin/dfrn/1.0' );
  359. define ( 'NAMESPACE_THREAD' , 'http://purl.org/syndication/thread/1.0' );
  360. define ( 'NAMESPACE_TOMB' , 'http://purl.org/atompub/tombstones/1.0' );
  361. define ( 'NAMESPACE_ACTIVITY', 'http://activitystrea.ms/spec/1.0/' );
  362. define ( 'NAMESPACE_ACTIVITY_SCHEMA', 'http://activitystrea.ms/schema/1.0/' );
  363. define ( 'NAMESPACE_MEDIA', 'http://purl.org/syndication/atommedia' );
  364. define ( 'NAMESPACE_SALMON_ME', 'http://salmon-protocol.org/ns/magic-env' );
  365. define ( 'NAMESPACE_OSTATUSSUB', 'http://ostatus.org/schema/1.0/subscribe' );
  366. define ( 'NAMESPACE_GEORSS', 'http://www.georss.org/georss' );
  367. define ( 'NAMESPACE_POCO', 'http://portablecontacts.net/spec/1.0' );
  368. define ( 'NAMESPACE_FEED', 'http://schemas.google.com/g/2010#updates-from' );
  369. define ( 'NAMESPACE_OSTATUS', 'http://ostatus.org/schema/1.0' );
  370. define ( 'NAMESPACE_STATUSNET', 'http://status.net/schema/api/1/' );
  371. define ( 'NAMESPACE_ATOM1', 'http://www.w3.org/2005/Atom' );
  372. define ( 'NAMESPACE_YMEDIA', 'http://search.yahoo.com/mrss/' );
  373. /**
  374. * activity stream defines
  375. */
  376. define ( 'ACTIVITY_LIKE', NAMESPACE_ACTIVITY_SCHEMA . 'like' );
  377. define ( 'ACTIVITY_DISLIKE', NAMESPACE_ZOT . '/activity/dislike' );
  378. define ( 'ACTIVITY_AGREE', NAMESPACE_ZOT . '/activity/agree' );
  379. define ( 'ACTIVITY_DISAGREE', NAMESPACE_ZOT . '/activity/disagree' );
  380. define ( 'ACTIVITY_ABSTAIN', NAMESPACE_ZOT . '/activity/abstain' );
  381. define ( 'ACTIVITY_ATTEND', NAMESPACE_ZOT . '/activity/attendyes' );
  382. define ( 'ACTIVITY_ATTENDNO', NAMESPACE_ZOT . '/activity/attendno' );
  383. define ( 'ACTIVITY_ATTENDMAYBE', NAMESPACE_ZOT . '/activity/attendmaybe' );
  384. define ( 'ACTIVITY_OBJ_HEART', NAMESPACE_ZOT . '/activity/heart' );
  385. define ( 'ACTIVITY_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'make-friend' );
  386. define ( 'ACTIVITY_REQ_FRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'request-friend' );
  387. define ( 'ACTIVITY_UNFRIEND', NAMESPACE_ACTIVITY_SCHEMA . 'remove-friend' );
  388. define ( 'ACTIVITY_FOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'follow' );
  389. define ( 'ACTIVITY_UNFOLLOW', NAMESPACE_ACTIVITY_SCHEMA . 'stop-following' );
  390. define ( 'ACTIVITY_JOIN', NAMESPACE_ACTIVITY_SCHEMA . 'join' );
  391. define ( 'ACTIVITY_POST', NAMESPACE_ACTIVITY_SCHEMA . 'post' );
  392. define ( 'ACTIVITY_UPDATE', NAMESPACE_ACTIVITY_SCHEMA . 'update' );
  393. define ( 'ACTIVITY_TAG', NAMESPACE_ACTIVITY_SCHEMA . 'tag' );
  394. define ( 'ACTIVITY_FAVORITE', NAMESPACE_ACTIVITY_SCHEMA . 'favorite' );
  395. define ( 'ACTIVITY_CREATE', NAMESPACE_ACTIVITY_SCHEMA . 'create' );
  396. define ( 'ACTIVITY_WIN', NAMESPACE_ACTIVITY_SCHEMA . 'win' );
  397. define ( 'ACTIVITY_LOSE', NAMESPACE_ACTIVITY_SCHEMA . 'lose' );
  398. define ( 'ACTIVITY_TIE', NAMESPACE_ACTIVITY_SCHEMA . 'tie' );
  399. define ( 'ACTIVITY_COMPLETE', NAMESPACE_ACTIVITY_SCHEMA . 'complete' );
  400. define ( 'ACTIVITY_POKE', NAMESPACE_ZOT . '/activity/poke' );
  401. define ( 'ACTIVITY_MOOD', NAMESPACE_ZOT . '/activity/mood' );
  402. define ( 'ACTIVITY_OBJ_COMMENT', NAMESPACE_ACTIVITY_SCHEMA . 'comment' );
  403. define ( 'ACTIVITY_OBJ_NOTE', NAMESPACE_ACTIVITY_SCHEMA . 'note' );
  404. define ( 'ACTIVITY_OBJ_PERSON', NAMESPACE_ACTIVITY_SCHEMA . 'person' );
  405. define ( 'ACTIVITY_OBJ_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'photo' );
  406. define ( 'ACTIVITY_OBJ_P_PHOTO', NAMESPACE_ACTIVITY_SCHEMA . 'profile-photo' );
  407. define ( 'ACTIVITY_OBJ_ALBUM', NAMESPACE_ACTIVITY_SCHEMA . 'photo-album' );
  408. define ( 'ACTIVITY_OBJ_EVENT', NAMESPACE_ACTIVITY_SCHEMA . 'event' );
  409. define ( 'ACTIVITY_OBJ_GROUP', NAMESPACE_ACTIVITY_SCHEMA . 'group' );
  410. define ( 'ACTIVITY_OBJ_GAME', NAMESPACE_ACTIVITY_SCHEMA . 'game' );
  411. define ( 'ACTIVITY_OBJ_TAGTERM', NAMESPACE_ZOT . '/activity/tagterm' );
  412. define ( 'ACTIVITY_OBJ_PROFILE', NAMESPACE_ZOT . '/activity/profile' );
  413. define ( 'ACTIVITY_OBJ_THING', NAMESPACE_ZOT . '/activity/thing' );
  414. define ( 'ACTIVITY_OBJ_LOCATION',NAMESPACE_ZOT . '/activity/location' );
  415. define ( 'ACTIVITY_OBJ_FILE', NAMESPACE_ZOT . '/activity/file' );
  416. /**
  417. * item weight for query ordering
  418. */
  419. define ( 'GRAVITY_PARENT', 0);
  420. define ( 'GRAVITY_LIKE', 3);
  421. define ( 'GRAVITY_COMMENT', 6);
  422. /**
  423. * Account Flags
  424. */
  425. define ( 'ACCOUNT_OK', 0x0000 );
  426. define ( 'ACCOUNT_UNVERIFIED', 0x0001 );
  427. define ( 'ACCOUNT_BLOCKED', 0x0002 );
  428. define ( 'ACCOUNT_EXPIRED', 0x0004 );
  429. define ( 'ACCOUNT_REMOVED', 0x0008 );
  430. define ( 'ACCOUNT_PENDING', 0x0010 );
  431. /**
  432. * Account roles
  433. */
  434. define ( 'ACCOUNT_ROLE_ALLOWCODE', 0x0001 );
  435. define ( 'ACCOUNT_ROLE_SYSTEM', 0x0002 );
  436. define ( 'ACCOUNT_ROLE_DEVELOPER', 0x0004 );
  437. define ( 'ACCOUNT_ROLE_ADMIN', 0x1000 );
  438. /**
  439. * Item visibility
  440. */
  441. define ( 'ITEM_VISIBLE', 0x0000);
  442. //define ( 'ITEM_HIDDEN', 0x0001);
  443. define ( 'ITEM_BLOCKED', 0x0002);
  444. define ( 'ITEM_MODERATED', 0x0004);
  445. define ( 'ITEM_SPAM', 0x0008);
  446. //define ( 'ITEM_DELETED', 0x0010);
  447. define ( 'ITEM_UNPUBLISHED', 0x0020);
  448. //define ( 'ITEM_WEBPAGE', 0x0040); // is a static web page, not a conversational item
  449. define ( 'ITEM_DELAYED_PUBLISH', 0x0080);
  450. define ( 'ITEM_BUILDBLOCK', 0x0100); // Named thusly to make sure nobody confuses this with ITEM_BLOCKED
  451. //define ( 'ITEM_PDL', 0x0200); // Page Description Language - e.g. Comanche
  452. define ( 'ITEM_BUG', 0x0400); // Is a bug, can be used by the internal bug tracker
  453. define ( 'ITEM_PENDING_REMOVE', 0x0800); // deleted, notification period has lapsed
  454. define ( 'ITEM_DOC', 0x1000); // hubzilla only, define here so that item import does the right thing
  455. define ( 'ITEM_TYPE_POST', 0 );
  456. define ( 'ITEM_TYPE_BLOCK', 1 );
  457. define ( 'ITEM_TYPE_PDL', 2 );
  458. define ( 'ITEM_TYPE_WEBPAGE', 3 );
  459. define ( 'ITEM_TYPE_BUG', 4 );
  460. define ( 'ITEM_TYPE_DOC', 5 );
  461. define ( 'ITEM_IS_STICKY', 1000 );
  462. define ( 'DBTYPE_MYSQL', 0 );
  463. define ( 'DBTYPE_POSTGRES', 1 );
  464. /**
  465. *
  466. * Reverse the effect of magic_quotes_gpc if it is enabled.
  467. * Please disable magic_quotes_gpc so we don't have to do this.
  468. * See http://php.net/manual/en/security.magicquotes.disabling.php
  469. *
  470. */
  471. function startup() {
  472. error_reporting(E_ERROR | E_WARNING | E_PARSE);
  473. // Some hosting providers block/disable this
  474. @set_time_limit(0);
  475. if(function_exists ('ini_set')) {
  476. // This has to be quite large to deal with embedded private photos
  477. @ini_set('pcre.backtrack_limit', 500000);
  478. // Use cookies to store the session ID on the client side
  479. @ini_set('session.use_only_cookies', 1);
  480. // Disable transparent Session ID support
  481. @ini_set('session.use_trans_sid', 0);
  482. }
  483. if (get_magic_quotes_gpc()) {
  484. $process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
  485. while (list($key, $val) = each($process)) {
  486. foreach ($val as $k => $v) {
  487. unset($process[$key][$k]);
  488. if (is_array($v)) {
  489. $process[$key][stripslashes($k)] = $v;
  490. $process[] = &$process[$key][stripslashes($k)];
  491. } else {
  492. $process[$key][stripslashes($k)] = stripslashes($v);
  493. }
  494. }
  495. }
  496. unset($process);
  497. }
  498. }
  499. class ZotlabsAutoloader {
  500. static public function loader($className) {
  501. $filename = str_replace('\\', '/', $className) . ".php";
  502. if (file_exists($filename)) {
  503. include($filename);
  504. if (class_exists($className)) {
  505. return TRUE;
  506. }
  507. }
  508. return FALSE;
  509. }
  510. }
  511. /**
  512. * class miniApp
  513. *
  514. * this is a transient structure which is needed to convert the $a->config settings
  515. * from older (existing) htconfig files which used a global App ($a) into the updated App structure
  516. * which is now static (although currently constructed at startup). We are only converting
  517. * 'system' config settings.
  518. */
  519. class miniApp {
  520. public $config = array('system' => array());
  521. public function convert() {
  522. if($this->config['system']) {
  523. foreach($this->config['system'] as $k => $v)
  524. App::$config['system'][$k] = $v;
  525. }
  526. }
  527. }
  528. /**
  529. * class: App
  530. *
  531. * @brief Our main application structure for the life of this page.
  532. *
  533. * Primarily deals with the URL that got us here
  534. * and tries to make some sense of it, and
  535. * stores our page contents and config storage
  536. * and anything else that might need to be passed around
  537. * before we spit the page out.
  538. *
  539. */
  540. class App {
  541. public static $install = false; // true if we are installing the software
  542. public static $account = null; // account record of the logged-in account
  543. public static $channel = null; // channel record of the current channel of the logged-in account
  544. public static $observer = null; // xchan record of the page observer
  545. public static $profile_uid = 0; // If applicable, the channel_id of the "page owner"
  546. public static $poi = null; // "person of interest", generally a referenced connection
  547. private static $oauth_key = null; // consumer_id of oauth request, if used
  548. public static $layout = array(); // Comanche parsed template
  549. public static $pdl = null; // Comanche page description
  550. private static $perms = null; // observer permissions
  551. private static $widgets = array(); // widgets for this page
  552. public static $groups;
  553. public static $language;
  554. public static $langsave;
  555. public static $plugins_admin;
  556. public static $module_loaded = false;
  557. public static $query_string;
  558. public static $config; // config cache
  559. public static $page;
  560. public static $profile;
  561. public static $user;
  562. public static $cid;
  563. public static $contact;
  564. public static $contacts;
  565. public static $content;
  566. public static $data = array();
  567. public static $error = false;
  568. public static $cmd;
  569. public static $argv;
  570. public static $argc;
  571. public static $module;
  572. public static $pager;
  573. public static $strings;
  574. public static $stringsave; // used in push_lang() and pop_lang()
  575. public static $hooks;
  576. public static $timezone;
  577. public static $interactive = true;
  578. public static $plugins;
  579. private static $apps = array();
  580. public static $identities;
  581. public static $css_sources = array();
  582. public static $js_sources = array();
  583. public static $theme_info = array();
  584. public static $is_sys = false;
  585. public static $nav_sel;
  586. public static $is_mobile = false;
  587. public static $is_tablet = false;
  588. public static $category;
  589. // Allow themes to control internal parameters
  590. // by changing App values in theme.php
  591. public static $sourcename = '';
  592. public static $videowidth = 425;
  593. public static $videoheight = 350;
  594. public static $force_max_items = 0;
  595. public static $theme_thread_allow = true;
  596. /**
  597. * @brief An array for all theme-controllable parameters
  598. *
  599. * Mostly unimplemented yet. Only options 'template_engine' and
  600. * beyond are used.
  601. */
  602. private static $theme = array(
  603. 'sourcename' => '',
  604. 'videowidth' => 425,
  605. 'videoheight' => 350,
  606. 'force_max_items' => 0,
  607. 'thread_allow' => true,
  608. 'stylesheet' => '',
  609. 'template_engine' => 'smarty3',
  610. );
  611. /**
  612. * @brief An array of registered template engines ('name'=>'class name')
  613. */
  614. public static $template_engines = array();
  615. /**
  616. * @brief An array of instanced template engines ('name'=>'instance')
  617. */
  618. public static $template_engine_instance = array();
  619. private static $ldelim = array(
  620. 'internal' => '',
  621. 'smarty3' => '{{'
  622. );
  623. private static $rdelim = array(
  624. 'internal' => '',
  625. 'smarty3' => '}}'
  626. );
  627. // These represent the URL which was used to access the page
  628. private static $scheme;
  629. private static $hostname;
  630. private static $path;
  631. // This is our standardised URL - regardless of what was used
  632. // to access the page
  633. private static $baseurl;
  634. private static $meta;
  635. /**
  636. * App constructor.
  637. */
  638. function init() {
  639. // we'll reset this after we read our config file
  640. date_default_timezone_set('UTC');
  641. self::$config = array('system'=>array());
  642. self::$page = array();
  643. self::$pager= array();
  644. self::$query_string = '';
  645. startup();
  646. set_include_path(
  647. 'include' . PATH_SEPARATOR
  648. . 'library' . PATH_SEPARATOR
  649. . 'library/langdet' . PATH_SEPARATOR
  650. . '.' );
  651. self::$scheme = 'http';
  652. if(x($_SERVER,'HTTPS') && $_SERVER['HTTPS'])
  653. self::$scheme = 'https';
  654. elseif(x($_SERVER,'SERVER_PORT') && (intval($_SERVER['SERVER_PORT']) == 443))
  655. self::$scheme = 'https';
  656. if(x($_SERVER,'SERVER_NAME')) {
  657. self::$hostname = $_SERVER['SERVER_NAME'];
  658. if(x($_SERVER,'SERVER_PORT') && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443)
  659. self::$hostname .= ':' . $_SERVER['SERVER_PORT'];
  660. /**
  661. * Figure out if we are running at the top of a domain
  662. * or in a sub-directory and adjust accordingly
  663. */
  664. $path = trim(dirname($_SERVER['SCRIPT_NAME']),'/\\');
  665. if(isset($path) && strlen($path) && ($path != self::$path))
  666. self::$path = $path;
  667. }
  668. set_include_path("include/self::$hostname" . PATH_SEPARATOR . get_include_path());
  669. if((x($_SERVER,'QUERY_STRING')) && substr($_SERVER['QUERY_STRING'], 0, 2) === "q=") {
  670. self::$query_string = substr($_SERVER['QUERY_STRING'], 2);
  671. // removing trailing / - maybe a nginx problem
  672. if (substr(self::$query_string, 0, 1) == "/")
  673. self::$query_string = substr(self::$query_string, 1);
  674. }
  675. if(x($_GET,'q'))
  676. self::$cmd = trim($_GET['q'],'/\\');
  677. // unix style "homedir"
  678. if(substr(self::$cmd, 0, 1) === '~')
  679. self::$cmd = 'channel/' . substr(self::$cmd, 1);
  680. /*
  681. * Break the URL path into C style argc/argv style arguments for our
  682. * modules. Given "http://example.com/module/arg1/arg2", self::$argc
  683. * will be 3 (integer) and self::$argv will contain:
  684. * [0] => 'module'
  685. * [1] => 'arg1'
  686. * [2] => 'arg2'
  687. *
  688. * There will always be one argument. If provided a naked domain
  689. * URL, self::$argv[0] is set to "home".
  690. */
  691. self::$argv = explode('/', self::$cmd);
  692. self::$argc = count(self::$argv);
  693. if ((array_key_exists('0', self::$argv)) && strlen(self::$argv[0])) {
  694. self::$module = str_replace(".", "_", self::$argv[0]);
  695. self::$module = str_replace("-", "_", self::$module);
  696. } else {
  697. self::$argc = 1;
  698. self::$argv = array('home');
  699. self::$module = 'home';
  700. }
  701. /*
  702. * See if there is any page number information, and initialise
  703. * pagination
  704. */
  705. self::$pager['page'] = ((x($_GET,'page') && intval($_GET['page']) > 0) ? intval($_GET['page']) : 1);
  706. self::$pager['itemspage'] = 60;
  707. self::$pager['start'] = (self::$pager['page'] * self::$pager['itemspage']) - self::$pager['itemspage'];
  708. if(self::$pager['start'] < 0)
  709. self::$pager['start'] = 0;
  710. self::$pager['total'] = 0;
  711. /*
  712. * Detect mobile devices
  713. */
  714. $mobile_detect = new Mobile_Detect();
  715. self::$is_mobile = $mobile_detect->isMobile();
  716. self::$is_tablet = $mobile_detect->isTablet();
  717. self::head_set_icon('/images/hz-32.png');
  718. BaseObject::set_app($this);
  719. /*
  720. * register template engines
  721. */
  722. $dc = get_declared_classes();
  723. foreach ($dc as $k) {
  724. if (in_array("ITemplateEngine", class_implements($k))){
  725. self::register_template_engine($k);
  726. }
  727. }
  728. spl_autoload_register('ZotlabsAutoloader::loader');
  729. self::$meta= new Zotlabs\Web\HttpMeta();
  730. }
  731. public static function get_baseurl($ssl = false) {
  732. if(is_array(self::$config)
  733. && array_key_exists('system',self::$config)
  734. && is_array(self::$config['system'])
  735. && array_key_exists('baseurl',self::$config['system'])
  736. && strlen(self::$config['system']['baseurl'])) {
  737. $url = self::$config['system']['baseurl'];
  738. $url = trim($url,'\\/');
  739. return $url;
  740. }
  741. $scheme = self::$scheme;
  742. self::$baseurl = $scheme . "://" . self::$hostname . ((isset(self::$path) && strlen(self::$path)) ? '/' . self::$path : '' );
  743. return self::$baseurl;
  744. }
  745. public static function set_baseurl($url) {
  746. if(is_array(self::$config)
  747. && array_key_exists('system',self::$config)
  748. && is_array(self::$config['system'])
  749. && array_key_exists('baseurl',self::$config['system'])
  750. && strlen(self::$config['system']['baseurl'])) {
  751. $url = self::$config['system']['baseurl'];
  752. $url = trim($url,'\\/');
  753. }
  754. $parsed = @parse_url($url);
  755. self::$baseurl = $url;
  756. if($parsed) {
  757. self::$scheme = $parsed['scheme'];
  758. self::$hostname = $parsed['host'];
  759. if(x($parsed,'port'))
  760. self::$hostname .= ':' . $parsed['port'];
  761. if(x($parsed,'path'))
  762. self::$path = trim($parsed['path'],'\\/');
  763. }
  764. }
  765. public static function get_scheme() {
  766. return self::$scheme;
  767. }
  768. public static function get_hostname() {
  769. return self::$hostname;
  770. }
  771. public static function set_hostname($h) {
  772. self::$hostname = $h;
  773. }
  774. public static function set_path($p) {
  775. self::$path = trim(trim($p), '/');
  776. }
  777. public static function get_path() {
  778. return self::$path;
  779. }
  780. public static function set_account($acct) {
  781. self::$account = $acct;
  782. }
  783. public static function get_account() {
  784. return self::$account;
  785. }
  786. public static function set_channel($channel) {
  787. self::$channel = $channel;
  788. }
  789. public static function get_channel() {
  790. return self::$channel;
  791. }
  792. public static function set_observer($xchan) {
  793. self::$observer = $xchan;
  794. }
  795. public static function get_observer() {
  796. return self::$observer;
  797. }
  798. public static function set_perms($perms) {
  799. self::$perms = $perms;
  800. }
  801. public static function get_perms() {
  802. return self::$perms;
  803. }
  804. public static function set_oauth_key($consumer_id) {
  805. self::$oauth_key = $consumer_id;
  806. }
  807. public static function get_oauth_key() {
  808. return self::$oauth_key;
  809. }
  810. public static function get_apps() {
  811. return self::$apps;
  812. }
  813. public static function set_apps($arr) {
  814. self::$apps = $arr;
  815. }
  816. public static function set_groups($g) {
  817. self::$groups = $g;
  818. }
  819. public static function get_groups() {
  820. return self::$groups;
  821. }
  822. public static function set_pager_total($n) {
  823. self::$pager['total'] = intval($n);
  824. }
  825. public static function set_pager_itemspage($n) {
  826. self::$pager['itemspage'] = ((intval($n) > 0) ? intval($n) : 0);
  827. self::$pager['start'] = (self::$pager['page'] * self::$pager['itemspage']) - self::$pager['itemspage'];
  828. }
  829. public static function build_pagehead() {
  830. $user_scalable = ((local_channel()) ? get_pconfig(local_channel(),'system','user_scalable') : 1);
  831. if ($user_scalable === false)
  832. $user_scalable = 1;
  833. $preload_images = ((local_channel()) ? get_pconfig(local_channel(),'system','preload_images') : 0);
  834. if ($preload_images === false)
  835. $preload_images = 0;
  836. $interval = ((local_channel()) ? get_pconfig(local_channel(),'system','update_interval') : 80000);
  837. if($interval < 10000)
  838. $interval = 80000;
  839. if(! x(self::$page,'title'))
  840. self::$page['title'] = self::$config['system']['sitename'];
  841. if(! self::$meta->get_field('og:title'))
  842. self::$meta->set('og:title',self::$page['title']);
  843. self::$meta->set('generator', Zotlabs\Project\System::get_platform_name());
  844. /* put the head template at the beginning of page['htmlhead']
  845. * since the code added by the modules frequently depends on it
  846. * being first
  847. */
  848. $tpl = get_markup_template('head.tpl');
  849. self::$page['htmlhead'] = replace_macros($tpl, array(
  850. '$preload_images' => $preload_images,
  851. '$user_scalable' => $user_scalable,
  852. '$query' => urlencode(self::$query_string),
  853. '$baseurl' => self::get_baseurl(),
  854. '$local_channel' => local_channel(),
  855. '$metas' => self::$meta->get(),
  856. '$update_interval' => $interval,
  857. 'osearch' => sprintf( t('Search %1$s (%2$s)','opensearch'), Zotlabs\Project\System::get_site_name(), t('$Projectname','opensearch')),
  858. '$icon' => head_get_icon(),
  859. '$head_css' => head_get_css(),
  860. '$head_js' => head_get_js(),
  861. '$js_strings' => js_strings(),
  862. '$zid' => get_my_address(),
  863. '$channel_id' => self::$profile['uid'],
  864. )) . self::$page['htmlhead'];
  865. // always put main.js at the end
  866. self::$page['htmlhead'] .= head_get_main_js();
  867. }
  868. /**
  869. * register template engine class
  870. * if $name is "", is used class static property $class::$name
  871. * @param string $class
  872. * @param string $name
  873. */
  874. public static function register_template_engine($class, $name = '') {
  875. if ($name === ""){
  876. $v = get_class_vars( $class );
  877. if(x($v, "name")) $name = $v['name'];
  878. }
  879. if ($name === ""){
  880. echo "template engine <tt>$class</tt> cannot be registered without a name.\n";
  881. killme();
  882. }
  883. self::$template_engines[$name] = $class;
  884. }
  885. /**
  886. * return template engine instance. If $name is not defined,
  887. * return engine defined by theme, or default
  888. *
  889. * @param string $name Template engine name
  890. *
  891. * @return object Template Engine instance
  892. */
  893. public static function template_engine($name = ''){
  894. if ($name !== "") {
  895. $template_engine = $name;
  896. } else {
  897. $template_engine = 'smarty3';
  898. if (x(self::$theme, 'template_engine')) {
  899. $template_engine = self::$theme['template_engine'];
  900. }
  901. }
  902. if (isset(self::$template_engines[$template_engine])){
  903. if(isset(self::$template_engine_instance[$template_engine])){
  904. return self::$template_engine_instance[$template_engine];
  905. } else {
  906. $class = self::$template_engines[$template_engine];
  907. $obj = new $class;
  908. self::$template_engine_instance[$template_engine] = $obj;
  909. return $obj;
  910. }
  911. }
  912. echo "template engine <tt>$template_engine</tt> is not registered!\n"; killme();
  913. }
  914. /**
  915. * @brief Returns the active template engine.
  916. *
  917. * @return string
  918. */
  919. public static function get_template_engine() {
  920. return self::$theme['template_engine'];
  921. }
  922. public static function set_template_engine($engine = 'smarty3') {
  923. self::$theme['template_engine'] = $engine;
  924. }
  925. public static function get_template_ldelim($engine = 'smarty3') {
  926. return self::$ldelim[$engine];
  927. }
  928. public static function get_template_rdelim($engine = 'smarty3') {
  929. return self::$rdelim[$engine];
  930. }
  931. public static function head_set_icon($icon) {
  932. self::$data['pageicon'] = $icon;
  933. }
  934. public static function head_get_icon() {
  935. $icon = self::$data['pageicon'];
  936. if(! strpos($icon,'://'))
  937. $icon = z_root() . $icon;
  938. return $icon;
  939. }
  940. } // End App class
  941. /**
  942. * @brief Retrieve the App structure.
  943. *
  944. * Useful in functions which require it but don't get it passed to them
  945. *
  946. * @return App
  947. */
  948. function get_app() {
  949. global $a;
  950. return $a;
  951. }
  952. /**
  953. * @brief Multi-purpose function to check variable state.
  954. *
  955. * Usage: x($var) or $x($array, 'key')
  956. *
  957. * returns false if variable/key is not set
  958. * if variable is set, returns 1 if has 'non-zero' value, otherwise returns 0.
  959. * e.g. x('') or x(0) returns 0;
  960. *
  961. * @param string|array $s variable to check
  962. * @param string $k key inside the array to check
  963. *
  964. * @return bool|int
  965. */
  966. function x($s, $k = null) {
  967. if($k != null) {
  968. if((is_array($s)) && (array_key_exists($k, $s))) {
  969. if($s[$k])
  970. return (int) 1;
  971. return (int) 0;
  972. }
  973. return false;
  974. }
  975. else {
  976. if(isset($s)) {
  977. if($s) {
  978. return (int) 1;
  979. }
  980. return (int) 0;
  981. }
  982. return false;
  983. }
  984. }
  985. // called from db initialisation if db is dead.
  986. function system_unavailable() {
  987. include('include/system_unavailable.php');
  988. system_down();
  989. killme();
  990. }
  991. function clean_urls() {
  992. global $a;
  993. // if(App::$config['system']['clean_urls'])
  994. return true;
  995. // return false;
  996. }
  997. function z_path() {
  998. global $a;
  999. $base = z_root();
  1000. if(! clean_urls())
  1001. $base .= '/?q=';
  1002. return $base;
  1003. }
  1004. /**
  1005. * @brief Returns the baseurl.
  1006. *
  1007. * @see App::get_baseurl()
  1008. *
  1009. * @return string
  1010. */
  1011. function z_root() {
  1012. global $a;
  1013. return App::get_baseurl();
  1014. }
  1015. /**
  1016. * @brief Return absolute URL for given $path.
  1017. *
  1018. * @param string $path
  1019. *
  1020. * @return string
  1021. */
  1022. function absurl($path) {
  1023. if(strpos($path, '/') === 0)
  1024. return z_path() . $path;
  1025. return $path;
  1026. }
  1027. function os_mkdir($path, $mode = 0777, $recursive = false) {
  1028. $oldumask = @umask(0);
  1029. $result = @mkdir($path, $mode, $recursive);
  1030. @umask($oldumask);
  1031. return $result;
  1032. }
  1033. /**
  1034. * @brief Function to check if request was an AJAX (xmlhttprequest) request.
  1035. *
  1036. * @return boolean
  1037. */
  1038. function is_ajax() {
  1039. return (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest');
  1040. }
  1041. // Primarily involved with database upgrade, but also sets the
  1042. // base url for use in cmdline programs which don't have
  1043. // $_SERVER variables, and synchronising the state of installed plugins.
  1044. function check_config(&$a) {
  1045. $build = get_config('system','db_version');
  1046. if(! intval($build))
  1047. $build = set_config('system','db_version',DB_UPDATE_VERSION);
  1048. $saved = get_config('system','urlverify');
  1049. if(! $saved)
  1050. set_config('system','urlverify',bin2hex(z_root()));
  1051. if(($saved) && ($saved != bin2hex(z_root()))) {
  1052. // our URL changed. Do something.
  1053. $oldurl = hex2bin($saved);
  1054. logger('Baseurl changed!');
  1055. $oldhost = substr($oldurl, strpos($oldurl, '//') + 2);
  1056. $host = substr(z_root(), strpos(z_root(), '//') + 2);
  1057. $is_ip_addr = ((preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$host)) ? true : false);
  1058. $was_ip_addr = ((preg_match("/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/",$oldhost)) ? true : false);
  1059. // only change the url to an ip address if it was already an ip and not a dns name
  1060. if((! $is_ip_addr) || ($is_ip_addr && $was_ip_addr)) {
  1061. fix_system_urls($oldurl,z_root());
  1062. set_config('system', 'urlverify', bin2hex(z_root()));
  1063. }
  1064. else
  1065. logger('Attempt to change baseurl from a DNS name to an IP address was refused.');
  1066. }
  1067. // This will actually set the url to the one stored in .htconfig, and ignore what
  1068. // we're passing - unless we are installing and it has never been set.
  1069. App::set_baseurl(z_root());
  1070. // Make sure each site has a system channel. This is now created on install
  1071. // so we just need to keep this around a couple of weeks until the hubs that
  1072. // already exist have one
  1073. $syschan_exists = get_sys_channel();
  1074. if (! $syschan_exists)
  1075. create_sys_channel();
  1076. if($build != DB_UPDATE_VERSION) {
  1077. $stored = intval($build);
  1078. if(! $stored) {
  1079. logger('Critical: check_config unable to determine database schema version');
  1080. return;
  1081. }
  1082. $current = intval(DB_UPDATE_VERSION);
  1083. if(($stored < $current) && file_exists('install/update.php')) {
  1084. load_config('database');
  1085. // We're reporting a different version than what is currently installed.
  1086. // Run any existing update scripts to bring the database up to current.
  1087. require_once('install/update.php');
  1088. // make sure that boot.php and update.php are the same release, we might be
  1089. // updating right this very second and the correct version of the update.php
  1090. // file may not be here yet. This can happen on a very busy site.
  1091. if(DB_UPDATE_VERSION == UPDATE_VERSION) {
  1092. for($x = $stored; $x < $current; $x ++) {
  1093. if(function_exists('update_r' . $x)) {
  1094. // There could be a lot of processes running or about to run.
  1095. // We want exactly one process to run the update command.
  1096. // So store the fact that we're taking responsibility
  1097. // after first checking to see if somebody else already has.
  1098. // If the update fails or times-out completely you may need to
  1099. // delete the config entry to try again.
  1100. if(get_config('database','update_r' . $x))
  1101. break;
  1102. set_config('database','update_r' . $x, '1');
  1103. // call the specific update
  1104. $func = 'update_r' . $x;
  1105. $retval = $func();
  1106. if($retval) {
  1107. // Prevent sending hundreds of thousands of emails by creating
  1108. // a lockfile.
  1109. $lockfile = 'store/[data]/mailsent';
  1110. if ((file_exists($lockfile)) && (filemtime($lockfile) > (time() - 86400)))
  1111. return;
  1112. @unlink($lockfile);
  1113. //send the administrator an e-mail
  1114. file_put_contents($lockfile, $x);
  1115. $email_tpl = get_intltext_template("update_fail_eml.tpl");
  1116. $email_msg = replace_macros($email_tpl, array(
  1117. '$sitename' => App::$config['system']['sitename'],
  1118. '$siteurl' => z_root(),
  1119. '$update' => $x,
  1120. '$error' => sprintf( t('Update %s failed. See error logs.'), $x)
  1121. ));
  1122. $subject = email_header_encode(sprintf(t('Update Error at %s'), z_root()));
  1123. mail(App::$config['system']['admin_email'], $subject, $email_msg,
  1124. 'From: Administrator' . '@' . $_SERVER['SERVER_NAME'] . "\n"
  1125. . 'Content-type: text/plain; charset=UTF-8' . "\n"
  1126. . 'Content-transfer-encoding: 8bit' );
  1127. //try the logger
  1128. logger('CRITICAL: Update Failed: ' . $x);
  1129. }
  1130. else
  1131. set_config('database','update_r' . $x, 'success');
  1132. }
  1133. }
  1134. set_config('system','db_version', DB_UPDATE_VERSION);
  1135. }
  1136. }
  1137. }
  1138. /**
  1139. *
  1140. * Synchronise plugins:
  1141. *
  1142. * App::$config['system']['addon'] contains a comma-separated list of names
  1143. * of plugins/addons which are used on this system.
  1144. * Go through the database list of already installed addons, and if we have
  1145. * an entry, but it isn't in the config list, call the unload procedure
  1146. * and mark it uninstalled in the database (for now we'll remove it).
  1147. * Then go through the config list and if we have a plugin that isn't installed,
  1148. * call the install procedure and add it to the database.
  1149. *
  1150. */
  1151. $r = q("SELECT * FROM addon WHERE installed = 1");
  1152. if($r)
  1153. $installed = $r;
  1154. else
  1155. $installed = array();
  1156. $plugins = get_config('system', 'addon');
  1157. $plugins_arr = array();
  1158. if($plugins)
  1159. $plugins_arr = explode(',', str_replace(' ', '', $plugins));
  1160. App::$plugins = $plugins_arr;
  1161. $installed_arr = array();
  1162. if(count($installed)) {
  1163. foreach($installed as $i) {
  1164. if(! in_array($i['name'], $plugins_arr)) {
  1165. unload_plugin($i['name']);
  1166. }
  1167. else {
  1168. $installed_arr[] = $i['name'];
  1169. }
  1170. }
  1171. }
  1172. if(count($plugins_arr)) {
  1173. foreach($plugins_arr as $p) {
  1174. if(! in_array($p, $installed_arr)) {
  1175. load_plugin($p);
  1176. }
  1177. }
  1178. }
  1179. load_hooks();
  1180. check_cron_broken();
  1181. }
  1182. function fix_system_urls($oldurl, $newurl) {
  1183. require_once('include/crypto.php');
  1184. logger('fix_system_urls: renaming ' . $oldurl . ' to ' . $newurl);
  1185. // Basically a site rename, but this can happen if you change from http to https for instance - even if the site name didn't change
  1186. // This should fix URL changes on our site, but other sites will end up with orphan hublocs which they will try to contact and will
  1187. // cause wasted communications.
  1188. // What we need to do after fixing this up is to send a revocation of the old URL to every other site that we communicate with so
  1189. // that they can clean up their hubloc tables (this includes directories).
  1190. // It's a very expensive operation so you don't want to have to do it often or after your site gets to be large.
  1191. $r = q("select xchan.*, hubloc.* from xchan left join hubloc on xchan_hash = hubloc_hash where hubloc_url like '%s'",
  1192. dbesc($oldurl . '%')
  1193. );
  1194. if($r) {
  1195. foreach($r as $rr) {
  1196. $channel_address = substr($rr['hubloc_addr'],0,strpos($rr['hubloc_addr'],'@'));
  1197. // get the associated channel. If we don't have a local channel, do nothing for this entry.
  1198. $c = q("select * from channel where channel_hash = '%s' limit 1",
  1199. dbesc($rr['hubloc_hash'])
  1200. );
  1201. if(! $c)
  1202. continue;
  1203. $parsed = @parse_url($newurl);
  1204. if(! $parsed)
  1205. continue;
  1206. $newhost = $parsed['host'];
  1207. // sometimes parse_url returns unexpected results.
  1208. if(strpos($newhost,'/') !== false)
  1209. $newhost = substr($newhost,0,strpos($newhost,'/'));
  1210. $rhs = $newhost . (($parsed['port']) ? ':' . $parsed['port'] : '');
  1211. // paths aren't going to work. You have to be at the (sub)domain root
  1212. // . (($parsed['path']) ? $parsed['path'] : '');
  1213. // The xchan_url might point to another nomadic identity clone
  1214. $replace_xchan_url = ((strpos($rr['xchan_url'],$oldurl) !== false) ? true : false);
  1215. $x = q("update xchan set xchan_addr = '%s', xchan_url = '%s', xchan_connurl = '%s', xchan_follow = '%s', xchan_connpage = '%s', xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s', xchan_photo_date = '%s' where xchan_hash = '%s'",
  1216. dbesc($channel_address . '@' . $rhs),
  1217. dbesc(($replace_xchan_url) ? str_replace($oldurl,$newurl,$rr['xchan_url']) : $rr['xchan_url']),
  1218. dbesc(str_replace($oldurl,$newurl,$rr['xchan_connurl'])),
  1219. dbesc(str_replace($oldurl,$newurl,$rr['xchan_follow'])),
  1220. dbesc(str_replace($oldurl,$newurl,$rr['xchan_connpage'])),
  1221. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_l'])),
  1222. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_m'])),
  1223. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_s'])),
  1224. dbesc(datetime_convert()),
  1225. dbesc($rr['xchan_hash'])
  1226. );
  1227. $y = q("update hubloc set hubloc_addr = '%s', hubloc_url = '%s', hubloc_url_sig = '%s', hubloc_host = '%s', hubloc_callback = '%s' where hubloc_hash = '%s' and hubloc_url = '%s'",
  1228. dbesc($channel_address . '@' . $rhs),
  1229. dbesc($newurl),
  1230. dbesc(base64url_encode(rsa_sign($newurl,$c[0]['channel_prvkey']))),
  1231. dbesc($newhost),
  1232. dbesc($newurl . '/post'),
  1233. dbesc($rr['xchan_hash']),
  1234. dbesc($oldurl)
  1235. );
  1236. $z = q("update profile set photo = '%s', thumb = '%s' where uid = %d",
  1237. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_l'])),
  1238. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_m'])),
  1239. intval($c[0]['channel_id'])
  1240. );
  1241. proc_run('php', 'include/notifier.php', 'refresh_all', $c[0]['channel_id']);
  1242. }
  1243. }
  1244. // now replace any remote xchans whose photos are stored locally (which will be most if not all remote xchans)
  1245. $r = q("select * from xchan where xchan_photo_l like '%s'",
  1246. dbesc($oldurl . '%')
  1247. );
  1248. if($r) {
  1249. foreach($r as $rr) {
  1250. $x = q("update xchan set xchan_photo_l = '%s', xchan_photo_m = '%s', xchan_photo_s = '%s' where xchan_hash = '%s'",
  1251. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_l'])),
  1252. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_m'])),
  1253. dbesc(str_replace($oldurl,$newurl,$rr['xchan_photo_s'])),
  1254. dbesc($rr['xchan_hash'])
  1255. );
  1256. }
  1257. }
  1258. }
  1259. // wrapper for adding a login box. If $register == true provide a registration
  1260. // link. This will most always depend on the value of App::$config['system']['register_policy'].
  1261. // returns the complete html for inserting into the page
  1262. function login($register = false, $form_id = 'main-login', $hiddens=false) {
  1263. $a = get_app();
  1264. $o = '';
  1265. $reg = false;
  1266. $reglink = get_config('system', 'register_link');
  1267. if(! strlen($reglink))
  1268. $reglink = 'register';
  1269. $reg = array(
  1270. 'title' => t('Create an account to access services and applications within the Hubzilla'),
  1271. 'desc' => t('Register'),
  1272. 'link' => (($register) ? $reglink : 'pubsites')
  1273. );
  1274. $dest_url = z_root() . '/' . App::$query_string;
  1275. if(local_channel()) {
  1276. $tpl = get_markup_template("logout.tpl");
  1277. }
  1278. else {
  1279. $tpl = get_markup_template("login.tpl");
  1280. if(strlen(App::$query_string))
  1281. $_SESSION['login_return_url'] = App::$query_string;
  1282. }
  1283. $o .= replace_macros($tpl,array(
  1284. '$dest_url' => $dest_url,
  1285. '$logout' => t('Logout'),
  1286. '$login' => t('Login'),
  1287. '$form_id' => $form_id,
  1288. '$lname' => array('username', t('Email') , '', ''),
  1289. '$lpassword' => array('password', t('Password'), '', ''),
  1290. '$remember_me' => array('remember_me', t('Remember me'), '', '',array(t('No'),t('Yes'))),
  1291. '$hiddens' => $hiddens,
  1292. '$register' => $reg,
  1293. '$lostpass' => t('Forgot your password?'),
  1294. '$lostlink' => t('Password Reset'),
  1295. ));
  1296. call_hooks('login_hook', $o);
  1297. return $o;
  1298. }
  1299. /**
  1300. * @brief Used to end the current process, after saving session state.
  1301. */
  1302. function killme() {
  1303. exit;
  1304. }
  1305. /**
  1306. * @brief Redirect to another URL and terminate this process.
  1307. */
  1308. function goaway($s) {
  1309. header("Location: $s");
  1310. killme();
  1311. }
  1312. /**
  1313. * @brief Returns the entity id of locally logged in account or false.
  1314. *
  1315. * Returns numeric account_id if authenticated or 0. It is possible to be
  1316. * authenticated and not connected to a channel.
  1317. *
  1318. * @return int|bool account_id or false
  1319. */
  1320. function get_account_id() {
  1321. if(intval($_SESSION['account_id']))
  1322. return intval($_SESSION['account_id']);
  1323. if(App::$account)
  1324. return intval(App::$account['account_id']);
  1325. return false;
  1326. }
  1327. /**
  1328. * @brief Returns the entity id (channel_id) of locally logged in channel or false.
  1329. *
  1330. * Returns authenticated numeric channel_id if authenticated and connected to
  1331. * a channel or 0. Sometimes referred to as $uid in the code.
  1332. *
  1333. * Before 2.1 this function was called local_user().
  1334. *
  1335. * @since 2.1
  1336. * @return int|bool channel_id or false
  1337. */
  1338. function local_channel() {
  1339. if((x($_SESSION, 'authenticated')) && (x($_SESSION, 'uid')))
  1340. return intval($_SESSION['uid']);
  1341. return false;
  1342. }
  1343. /**
  1344. * local_user() got deprecated and replaced by local_channel().
  1345. *
  1346. * @deprecated since v2.1, use local_channel()
  1347. * @see local_channel()
  1348. */
  1349. function local_user() {
  1350. logger('local_user() is DEPRECATED, use local_channel()');
  1351. return local_channel();
  1352. }
  1353. /**
  1354. * @brief Returns a xchan_hash (visitor_id) of remote authenticated visitor
  1355. * or false.
  1356. *
  1357. * Returns authenticated string hash of Red global identifier (xchan_hash), if
  1358. * authenticated via remote auth, or an empty string.
  1359. *
  1360. * Before 2.1 this function was called remote_user().
  1361. *
  1362. * @since 2.1
  1363. * @return string|bool visitor_id or false
  1364. */
  1365. function remote_channel() {
  1366. if((x($_SESSION, 'authenticated')) && (x($_SESSION, 'visitor_id')))
  1367. return $_SESSION['visitor_id'];
  1368. return false;
  1369. }
  1370. /**
  1371. * remote_user() got deprecated and replaced by remote_channel().
  1372. *
  1373. * @deprecated since v2.1, use remote_channel()
  1374. * @see remote_channel()
  1375. */
  1376. function remote_user() {
  1377. logger('remote_user() is DEPRECATED, use remote_channel()');
  1378. return remote_channel();
  1379. }
  1380. /**
  1381. * Contents of $s are displayed prominently on the page the next time
  1382. * a page is loaded. Usually used for errors or alerts.
  1383. *
  1384. * @param string $s Text to display
  1385. */
  1386. function notice($s) {
  1387. $a = get_app();
  1388. if(! x($_SESSION, 'sysmsg')) $_SESSION['sysmsg'] = array();
  1389. // ignore duplicated error messages which haven't yet been displayed
  1390. // - typically seen as multiple 'permission denied' messages
  1391. // as a result of auto-reloading a protected page with &JS=1
  1392. if(in_array($s,$_SESSION['sysmsg']))
  1393. return;
  1394. if(App::$interactive) {
  1395. $_SESSION['sysmsg'][] = $s;
  1396. }
  1397. }
  1398. /**
  1399. * Contents of $s are displayed prominently on the page the next time a page is
  1400. * loaded. Usually used for information.
  1401. * For error and alerts use notice().
  1402. *
  1403. * @param string $s Text to display
  1404. */
  1405. function info($s) {
  1406. $a = get_app();
  1407. if(! x($_SESSION, 'sysmsg_info')) $_SESSION['sysmsg_info'] = array();
  1408. if(App::$interactive)
  1409. $_SESSION['sysmsg_info'][] = $s;
  1410. }
  1411. /**
  1412. * @brief Wrapper around config to limit the text length of an incoming message
  1413. *
  1414. * @return int
  1415. */
  1416. function get_max_import_size() {
  1417. return(intval(get_config('system', 'max_import_size')));
  1418. }
  1419. /**
  1420. *
  1421. * Wrap calls to proc_close(proc_open()) and call hook
  1422. * so plugins can take part in process :)
  1423. *
  1424. * args:
  1425. * $cmd program to run
  1426. * next args are passed as $cmd command line
  1427. *
  1428. * e.g.: proc_run("ls","-la","/tmp");
  1429. *
  1430. * $cmd and string args are surrounded with ""
  1431. */
  1432. function proc_run($cmd){
  1433. $a = get_app();
  1434. $args = func_get_args();
  1435. $newargs = array();
  1436. if(! count($args))
  1437. return;
  1438. // expand any arrays
  1439. foreach($args as $arg) {
  1440. if(is_array($arg)) {
  1441. foreach($arg as $n) {
  1442. $newargs[] = $n;
  1443. }
  1444. }
  1445. else
  1446. $newargs[] = $arg;
  1447. }
  1448. $args = $newargs;
  1449. $arr = array('args' => $args, 'run_cmd' => true);
  1450. call_hooks("proc_run", $arr);
  1451. if(! $arr['run_cmd'])
  1452. return;
  1453. if(count($args) && $args[0] === 'php')
  1454. $args[0] = ((x(App::$config,'system')) && (x(App::$config['system'],'php_path')) && (strlen(App::$config['system']['php_path'])) ? App::$config['system']['php_path'] : 'php');
  1455. for($x = 0; $x < count($args); $x++)
  1456. $args[$x] = escapeshellarg($args[$x]);
  1457. $cmdline = implode($args," ");
  1458. if(is_windows()) {
  1459. $cwd = getcwd();
  1460. $cmd = "cmd /c start \"title\" /D \"$cwd\" /b $cmdline";
  1461. proc_close(proc_open($cmd, array(), $foo));
  1462. }
  1463. else {
  1464. if(get_config('system','use_proc_open'))
  1465. proc_close(proc_open($cmdline ." &", array(), $foo));
  1466. else
  1467. exec($cmdline . ' > /dev/null &');
  1468. }
  1469. }
  1470. /**
  1471. * @brief Checks if we are running on M$ Windows.
  1472. *
  1473. * @return bool true if we run on M$ Windows
  1474. */
  1475. function is_windows() {
  1476. return ((strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') ? true : false);
  1477. }
  1478. function current_theme(){
  1479. $app_base_themes = array('redbasic');
  1480. $a = get_app();
  1481. $page_theme = null;
  1482. // Find the theme that belongs to the channel whose stuff we are looking at
  1483. if(App::$profile_uid && App::$profile_uid != local_channel()) {
  1484. $r = q("select channel_theme from channel where channel_id = %d limit 1",
  1485. intval(App::$profile_uid)
  1486. );
  1487. if($r)
  1488. $page_theme = $r[0]['channel_theme'];
  1489. }
  1490. if(array_key_exists('theme', App::$layout) && App::$layout['theme'])
  1491. $page_theme = App::$layout['theme'];
  1492. // Allow folks to over-rule channel themes and always use their own on their own site.
  1493. // The default is for channel themes to take precedence over your own on pages belonging
  1494. // to that channel.
  1495. if($page_theme && local_channel() && App::$profile_uid && local_channel() != App::$profile_uid) {
  1496. if(get_pconfig(local_channel(),'system','always_my_theme'))
  1497. $page_theme = null;
  1498. }
  1499. $is_mobile = App::$is_mobile || App::$is_tablet;
  1500. $standard_system_theme = ((isset(App::$config['system']['theme'])) ? App::$config['system']['theme'] : '');
  1501. $standard_theme_name = ((isset($_SESSION) && x($_SESSION,'theme')) ? $_SESSION['theme'] : $standard_system_theme);
  1502. if($is_mobile) {
  1503. if(isset($_SESSION['show_mobile']) && !$_SESSION['show_mobile']) {
  1504. $system_theme = $standard_system_theme;
  1505. $theme_name = $standard_theme_name;
  1506. }
  1507. else {
  1508. $system_theme = ((isset(App::$config['system']['mobile_theme'])) ? App::$config['system']['mobile_theme'] : '');
  1509. $theme_name = ((isset($_SESSION) && x($_SESSION,'mobile_theme')) ? $_SESSION['mobile_theme'] : $system_theme);
  1510. if($theme_name === '' || $theme_name === '---' ) {
  1511. // user has selected to have the mobile theme be the same as the normal one
  1512. $system_theme = $standard_system_theme;
  1513. $theme_name = $standard_theme_name;
  1514. }
  1515. }
  1516. }
  1517. else {
  1518. $system_theme = $standard_system_theme;
  1519. $theme_name = $standard_theme_name;
  1520. if($page_theme)
  1521. $theme_name = $page_theme;
  1522. }
  1523. if($theme_name &&
  1524. (file_exists('view/theme/' . $theme_name . '/css/style.css') ||
  1525. file_exists('view/theme/' . $theme_name . '/php/style.php')))
  1526. return($theme_name);
  1527. foreach($app_base_themes as $t) {
  1528. if(file_exists('view/theme/' . $t . '/css/style.css') ||
  1529. file_exists('view/theme/' . $t . '/php/style.php'))
  1530. return($t);
  1531. }
  1532. $fallback = array_merge(glob('view/theme/*/css/style.css'),glob('view/theme/*/php/style.php'));
  1533. if(count($fallback))
  1534. return (str_replace('view/theme/','', substr($fallback[0],0,-10)));
  1535. }
  1536. /**
  1537. * @brief Return full URL to theme which is currently in effect.
  1538. *
  1539. * Provide a sane default if nothing is chosen or the specified theme does not exist.
  1540. *
  1541. * @param bool $installing default false
  1542. *
  1543. * @return string
  1544. */
  1545. function current_theme_url($installing = false) {
  1546. global $a;
  1547. $t = current_theme();
  1548. $opts = '';
  1549. $opts = ((App::$profile_uid) ? '?f=&puid=' . App::$profile_uid : '');
  1550. $opts .= ((x(App::$layout,'schema')) ? '&schema=' . App::$layout['schema'] : '');
  1551. if(file_exists('view/theme/' . $t . '/php/style.php'))
  1552. return('view/theme/' . $t . '/php/style.pcss' . $opts);
  1553. return('view/theme/' . $t . '/css/style.css');
  1554. }
  1555. /**
  1556. * @brief Check if current user has admin role.
  1557. *
  1558. * Check if the current user has ACCOUNT_ROLE_ADMIN.
  1559. *
  1560. * @return bool true if user is an admin
  1561. */
  1562. function is_site_admin() {
  1563. $a = get_app();
  1564. if($_SESSION['delegate'])
  1565. return false;
  1566. if((intval($_SESSION['authenticated']))
  1567. && (is_array(App::$account))
  1568. && (App::$account['account_roles'] & ACCOUNT_ROLE_ADMIN))
  1569. return true;
  1570. return false;
  1571. }
  1572. /**
  1573. * @brief Check if current user has developer role.
  1574. *
  1575. * Check if the current user has ACCOUNT_ROLE_DEVELOPER.
  1576. *
  1577. * @return bool true if user is a developer
  1578. */
  1579. function is_developer() {
  1580. $a = get_app();
  1581. if((intval($_SESSION['authenticated']))
  1582. && (is_array(App::$account))
  1583. && (App::$account['account_roles'] & ACCOUNT_ROLE_DEVELOPER))
  1584. return true;
  1585. return false;
  1586. }
  1587. function load_contact_links($uid) {
  1588. $a = get_app();
  1589. $ret = array();
  1590. if(! $uid || x(App::$contacts,'empty'))
  1591. return;
  1592. // logger('load_contact_links');
  1593. $r = q("SELECT abook_id, abook_flags, abook_my_perms, abook_their_perms, xchan_hash, xchan_photo_m, xchan_name, xchan_url from abook left join xchan on abook_xchan = xchan_hash where abook_channel = %d ",
  1594. intval($uid)
  1595. );
  1596. if($r) {
  1597. foreach($r as $rr){
  1598. $ret[$rr['xchan_hash']] = $rr;
  1599. }
  1600. }
  1601. else
  1602. $ret['empty'] = true;
  1603. App::$contacts = $ret;
  1604. }
  1605. /**
  1606. * @brief Returns querystring as string from a mapped array.
  1607. *
  1608. * @param array $params mapped array with query parameters
  1609. * @param string $name of parameter, default null
  1610. *
  1611. * @return string
  1612. */
  1613. function build_querystring($params, $name = null) {
  1614. $ret = '';
  1615. foreach($params as $key => $val) {
  1616. if(is_array($val)) {
  1617. if($name === null) {
  1618. $ret .= build_querystring($val, $key);
  1619. } else {
  1620. $ret .= build_querystring($val, $name . "[$key]");
  1621. }
  1622. } else {
  1623. $val = urlencode($val);
  1624. if($name != null) {
  1625. $ret .= $name . "[$key]" . "=$val&";
  1626. } else {
  1627. $ret .= "$key=$val&";
  1628. }
  1629. }
  1630. }
  1631. return $ret;
  1632. }
  1633. // much better way of dealing with c-style args
  1634. function argc() {
  1635. return App::$argc;
  1636. }
  1637. function argv($x) {
  1638. if(array_key_exists($x,App::$argv))
  1639. return App::$argv[$x];
  1640. return '';
  1641. }
  1642. function dba_timer() {
  1643. return microtime(true);
  1644. }
  1645. /**
  1646. * @brief Returns xchan_hash from the observer.
  1647. *
  1648. * @return string Empty if no observer, otherwise xchan_hash from observer
  1649. */
  1650. function get_observer_hash() {
  1651. $observer = App::get_observer();
  1652. if(is_array($observer))
  1653. return $observer['xchan_hash'];
  1654. return '';
  1655. }
  1656. /**
  1657. * Returns the complete URL of the current page, e.g.: http(s)://something.com/network
  1658. *
  1659. * Taken from http://webcheatsheet.com/php/get_current_page_url.php
  1660. */
  1661. function curPageURL() {
  1662. $pageURL = 'http';
  1663. if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
  1664. $pageURL .= "://";
  1665. if ($_SERVER["SERVER_PORT"] != "80" && $_SERVER["SERVER_PORT"] != "443") {
  1666. $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
  1667. } else {
  1668. $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
  1669. }
  1670. return $pageURL;
  1671. }
  1672. /**
  1673. * @brief Returns a custom navigation by name???
  1674. *
  1675. * If no $navname provided load default page['nav']
  1676. *
  1677. * @todo not fully implemented yet
  1678. *
  1679. * @param App $a global application object
  1680. * @param string $navname
  1681. *
  1682. * @return mixed
  1683. */
  1684. function get_custom_nav(&$a, $navname) {
  1685. if (! $navname)
  1686. return App::$page['nav'];
  1687. // load custom nav menu by name here
  1688. }
  1689. /**
  1690. * @brief Loads a page definition file for a module.
  1691. *
  1692. * If there is no parsed Comanche template already load a module's pdl file
  1693. * and parse it with Comanche.
  1694. *
  1695. * @param App &$a global application object
  1696. */
  1697. function load_pdl(&$a) {
  1698. require_once('include/comanche.php');
  1699. if (! count(App::$layout)) {
  1700. $arr = array('module' => App::$module, 'layout' => '');
  1701. call_hooks('load_pdl',$arr);
  1702. $layout = $arr['layout'];
  1703. $n = 'mod_' . App::$module . '.pdl' ;
  1704. $u = comanche_get_channel_id();
  1705. if($u)
  1706. $s = get_pconfig($u, 'system', $n);
  1707. if(! $s)
  1708. $s = $layout;
  1709. if((! $s) && (($p = theme_include($n)) != ''))
  1710. $s = @file_get_contents($p);
  1711. if($s) {
  1712. comanche_parser($a, $s);
  1713. App::$pdl = $s;
  1714. }
  1715. }
  1716. }
  1717. function exec_pdl(&$a) {
  1718. require_once('include/comanche.php');
  1719. if(App::$pdl) {
  1720. comanche_parser($a, App::$pdl,1);
  1721. }
  1722. }
  1723. /**
  1724. * @brief build the page.
  1725. *
  1726. * Build the page - now that we have all the components
  1727. *
  1728. * @param App &$a global application object
  1729. */
  1730. function construct_page(&$a) {
  1731. exec_pdl($a);
  1732. $comanche = ((count(App::$layout)) ? true : false);
  1733. require_once(theme_include('theme_init.php'));
  1734. $installing = false;
  1735. if (App::$module == 'setup') {
  1736. $installing = true;
  1737. } else {
  1738. nav($a);
  1739. }
  1740. if ($comanche) {
  1741. if (App::$layout['nav']) {
  1742. App::$page['nav'] = get_custom_nav($a, App::$layout['nav']);
  1743. }
  1744. }
  1745. if (($p = theme_include(current_theme() . '.js')) != '')
  1746. head_add_js($p);
  1747. if (($p = theme_include('mod_' . App::$module . '.php')) != '')
  1748. require_once($p);
  1749. require_once('include/js_strings.php');
  1750. if (x(App::$page, 'template_style'))
  1751. head_add_css(App::$page['template_style'] . '.css');
  1752. else
  1753. head_add_css(((x(App::$page, 'template')) ? App::$page['template'] : 'default' ) . '.css');
  1754. head_add_css('mod_' . App::$module . '.css');
  1755. head_add_css(current_theme_url($installing));
  1756. head_add_js('mod_' . App::$module . '.js');
  1757. App::build_pagehead();
  1758. if(App::$page['pdl_content']) {
  1759. App::$page['content'] = comanche_region($a,App::$page['content']);
  1760. }
  1761. // Let's say we have a comanche declaration '[region=nav][/region][region=content]$nav $content[/region]'.
  1762. // The text 'region=' identifies a section of the layout by that name. So what we want to do here is leave
  1763. // App::$page['nav'] empty and put the default content from App::$page['nav'] and App::$page['section']
  1764. // into a new region called App::$data['content']. It is presumed that the chosen layout file for this comanche page
  1765. // has a '<content>' element instead of a '<section>'.
  1766. // This way the Comanche layout can include any existing content, alter the layout by adding stuff around it or changing the
  1767. // layout completely with a new layout definition, or replace/remove existing content.
  1768. if($comanche) {
  1769. $arr = array('module' => App::$module, 'layout' => App::$layout);
  1770. call_hooks('construct_page', $arr);
  1771. App::$layout = $arr['layout'];
  1772. foreach(App::$layout as $k => $v) {
  1773. if((strpos($k, 'region_') === 0) && strlen($v)) {
  1774. if(strpos($v, '$region_') !== false) {
  1775. $v = preg_replace_callback('/\$region_([a-zA-Z0-9]+)/ism', 'comanche_replace_region', $v);
  1776. }
  1777. // And a couple of convenience macros
  1778. if(strpos($v, '$htmlhead') !== false) {
  1779. $v = str_replace('$htmlhead', App::$page['htmlhead'], $v);
  1780. }
  1781. if(strpos($v, '$nav') !== false) {
  1782. $v = str_replace('$nav', App::$page['nav'], $v);
  1783. }
  1784. if(strpos($v, '$content') !== false) {
  1785. $v = str_replace('$content', App::$page['content'], $v);
  1786. }
  1787. App::$page[substr($k, 7)] = $v;
  1788. }
  1789. }
  1790. }
  1791. if(App::$is_mobile || App::$is_tablet) {
  1792. if(isset($_SESSION['show_mobile']) && !$_SESSION['show_mobile']) {
  1793. $link = z_root() . '/toggle_mobile?f=&address=' . curPageURL();
  1794. }
  1795. else {
  1796. $link = z_root() . '/toggle_mobile?f=&off=1&address=' . curPageURL();
  1797. }
  1798. if ((isset($_SESSION) && $_SESSION['mobile_theme'] !='' && $_SESSION['mobile_theme'] !='---' ) ||
  1799. (isset(App::$config['system']['mobile_theme']) && !isset($_SESSION['mobile_theme']))) {
  1800. App::$page['footer'] .= replace_macros(get_markup_template("toggle_mobile_footer.tpl"), array(
  1801. '$toggle_link' => $link,
  1802. '$toggle_text' => t('toggle mobile')
  1803. ));
  1804. }
  1805. }
  1806. $page = App::$page;
  1807. $profile = App::$profile;
  1808. header("Content-type: text/html; charset=utf-8");
  1809. // security headers - see https://securityheaders.io
  1810. if(App::get_scheme() === 'https' && App::$config['system']['transport_security_header'])
  1811. header("Strict-Transport-Security: max-age=31536000");
  1812. if(App::$config['system']['content_security_policy'])
  1813. header("Content-Security-Policy: script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'");
  1814. if(App::$config['system']['x_security_headers']) {
  1815. header("X-Frame-Options: SAMEORIGIN");
  1816. header("X-Xss-Protection: 1; mode=block;");
  1817. header("X-Content-Type-Options: nosniff");
  1818. }
  1819. if(App::$config['system']['public_key_pins']) {
  1820. header("Public-Key-Pins: " . App::$config['system']['public_key_pins']);
  1821. }
  1822. require_once(theme_include(
  1823. ((x(App::$page, 'template')) ? App::$page['template'] : 'default' ) . '.php' )
  1824. );
  1825. }
  1826. /**
  1827. * @brief Returns Hubzilla's root directory.
  1828. *
  1829. * @return string
  1830. */
  1831. function appdirpath() {
  1832. return dirname(__FILE__);
  1833. }
  1834. /**
  1835. * @brief Set a pageicon.
  1836. *
  1837. * @param string $icon
  1838. */
  1839. function head_set_icon($icon) {
  1840. global $a;
  1841. App::$data['pageicon'] = $icon;
  1842. // logger('head_set_icon: ' . $icon);
  1843. }
  1844. /**
  1845. * @brief Get the pageicon.
  1846. *
  1847. * @return string absolut path to pageicon
  1848. */
  1849. function head_get_icon() {
  1850. global $a;
  1851. $icon = App::$data['pageicon'];
  1852. if(! strpos($icon, '://'))
  1853. $icon = z_root() . $icon;
  1854. return $icon;
  1855. }
  1856. /**
  1857. * @brief Return the Realm of the directory.
  1858. *
  1859. * @return string
  1860. */
  1861. function get_directory_realm() {
  1862. if($x = get_config('system', 'directory_realm'))
  1863. return $x;
  1864. return DIRECTORY_REALM;
  1865. }
  1866. /**
  1867. * @brief Return the primary directory server.
  1868. *
  1869. * @return string
  1870. */
  1871. function get_directory_primary() {
  1872. $dirmode = intval(get_config('system','directory_mode'));
  1873. if($dirmode == DIRECTORY_MODE_STANDALONE || $dirmode == DIRECTORY_MODE_PRIMARY) {
  1874. return z_root();
  1875. }
  1876. if($x = get_config('system', 'directory_primary'))
  1877. return $x;
  1878. return DIRECTORY_FALLBACK_MASTER;
  1879. }
  1880. /**
  1881. * @brief return relative date of last completed poller execution.
  1882. */
  1883. function get_poller_runtime() {
  1884. $t = get_config('system', 'lastpoll');
  1885. return relative_date($t);
  1886. }
  1887. function z_get_upload_dir() {
  1888. $upload_dir = get_config('system','uploaddir');
  1889. if(! $upload_dir)
  1890. $upload_dir = ini_get('upload_tmp_dir');
  1891. if(! $upload_dir)
  1892. $upload_dir = sys_get_temp_dir();
  1893. return $upload_dir;
  1894. }
  1895. function z_get_temp_dir() {
  1896. $temp_dir = get_config('system','tempdir');
  1897. if(! $temp_dir)
  1898. $temp_dir = sys_get_temp_dir();
  1899. return $upload_dir;
  1900. }
  1901. function z_check_cert() {
  1902. $a = get_app();
  1903. if(strpos(z_root(),'https://') !== false) {
  1904. $x = z_fetch_url(z_root() . '/siteinfo/json');
  1905. if(! $x['success']) {
  1906. $recurse = 0;
  1907. $y = z_fetch_url(z_root() . '/siteinfo/json',false,$recurse,array('novalidate' => true));
  1908. if($y['success'])
  1909. cert_bad_email();
  1910. }
  1911. }
  1912. }
  1913. /**
  1914. * @brief Send email to admin if server has an invalid certificate.
  1915. *
  1916. * If a Hubzilla hub is available over https it must have a publicly valid
  1917. * certificate.
  1918. */
  1919. function cert_bad_email() {
  1920. $a = get_app();
  1921. $email_tpl = get_intltext_template("cert_bad_eml.tpl");
  1922. $email_msg = replace_macros($email_tpl, array(
  1923. '$sitename' => App::$config['system']['sitename'],
  1924. '$siteurl' => z_root(),
  1925. '$error' => t('Website SSL certificate is not valid. Please correct.')
  1926. ));
  1927. $subject = email_header_encode(sprintf(t('[hubzilla] Website SSL error for %s'), App::get_hostname()));
  1928. mail(App::$config['system']['admin_email'], $subject, $email_msg,
  1929. 'From: Administrator' . '@' . App::get_hostname() . "\n"
  1930. . 'Content-type: text/plain; charset=UTF-8' . "\n"
  1931. . 'Content-transfer-encoding: 8bit' );
  1932. }
  1933. /**
  1934. * @brief Send warnings every 3-5 days if cron is not running.
  1935. */
  1936. function check_cron_broken() {
  1937. $t = get_config('system','lastpollcheck');
  1938. if(! $t) {
  1939. // never checked before. Start the timer.
  1940. set_config('system','lastpollcheck',datetime_convert());
  1941. return;
  1942. }
  1943. if($t > datetime_convert('UTC','UTC','now - 3 days')) {
  1944. // Wait for 3 days before we do anything so as not to swamp the admin with messages
  1945. return;
  1946. }
  1947. $d = get_config('system','lastpoll');
  1948. if(($d) && ($d > datetime_convert('UTC','UTC','now - 3 days'))) {
  1949. // Scheduled tasks have run successfully in the last 3 days.
  1950. set_config('system','lastpollcheck',datetime_convert());
  1951. return;
  1952. }
  1953. $a = get_app();
  1954. $email_tpl = get_intltext_template("cron_bad_eml.tpl");
  1955. $email_msg = replace_macros($email_tpl, array(
  1956. '$sitename' => App::$config['system']['sitename'],
  1957. '$siteurl' => z_root(),
  1958. '$error' => t('Cron/Scheduled tasks not running.'),
  1959. '$lastdate' => (($d)? $d : t('never'))
  1960. ));
  1961. $subject = email_header_encode(sprintf(t('[hubzilla] Cron tasks not running on %s'), App::get_hostname()));
  1962. mail(App::$config['system']['admin_email'], $subject, $email_msg,
  1963. 'From: Administrator' . '@' . App::get_hostname() . "\n"
  1964. . 'Content-type: text/plain; charset=UTF-8' . "\n"
  1965. . 'Content-transfer-encoding: 8bit' );
  1966. set_config('system','lastpollcheck',datetime_convert());
  1967. return;
  1968. }