1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8if (basename($_SERVER['SCRIPT_NAME']) === basename(__FILE__)) {
9	die('This script may only be included.');
10}
11
12// need to rebuild because they were created in tiki-setup and just removed due to clear cache
13// we need to create upfront in case codemirror is used later on.
14require_once("lib/codemirror_tiki/tiki_codemirror.php");
15createCodemirrorModes();
16
17// Javascript auto-detection
18//   (to be able to generate non-javascript code if there is no javascript, when noscript tag is not useful enough)
19//   It uses cookies instead of session vars to keep the correct value after a session timeout
20
21$js_cookie = getCookie('javascript_enabled');
22
23if ($prefs['disableJavascript'] == 'y') {
24	$prefs['javascript_enabled'] = 'n';
25} elseif (! empty($js_cookie)) {
26	// Update the pref with the cookie value
27	$prefs['javascript_enabled'] = 'y';
28	if ($js_cookie !== 'y') {		// if it's not 'y' then it's the expiry in ms
29		setcookie('javascript_enabled', 'y', $js_cookie / 1000);
30	}
31	setCookieSection('javascript_enabled_detect', '', '', time() - 3600);	// remove the test cookie
32} else {
33	if (isset($_COOKIE['runs_before_js_detect'])) {	// pre-tiki 14 method detected, delete both test cookies (reloading here caused redirect a loop in some case)
34		setcookie('runs_before_js_detect', '', time() - 3600);
35		setcookie('javascript_enabled_detect', '', time() - 3600);
36	}
37	$prefs['javascript_enabled'] = '';
38}
39
40// the first and second time, we should not trust the absence of javascript_enabled cookie yet,
41// as it could be a redirection and the js will not get a chance to run yet, so we wait until the third run,
42// assuming that js is on before then
43$javascript_enabled_detect = getCookie('javascript_enabled_detect', '', '0');
44
45// Cookie Consent: setCookieSection uses the session tiki_cookie_jar to simulate cookies,
46// so check that $feature_no_cookie is not true because cookies are not really set when using cookie_consent_feature
47// and so javascript will get disabled by mistake
48
49if (empty($javascript_enabled_detect) && $feature_no_cookie) {
50	$prefs['javascript_enabled'] = 'y';					// assume javascript should be enabled while cookie consent is pending
51} elseif ($prefs['javascript_enabled'] === '' && $prefs['disableJavascript'] != 'y' && $javascript_enabled_detect < 3) {
52	// Set the cookie to 'y', through javascript - expires: approx. 1 year
53	$prefs['javascript_enabled'] = 'y';											// temporarily enable to we output the test js
54	$plus_one_year = ($tikilib->now + 365 * 24 * 3600) * 1000;		// ms
55	$headerlib->add_js("setCookieBrowser('javascript_enabled', '{$plus_one_year}', '', new Date({$plus_one_year}));", 0);		// setCookieBrowser does not use the tiki_cookie_jar
56
57	if (strpos($_SERVER['PHP_SELF'], 'tiki-download') === false &&
58			strpos($_SERVER['PHP_SELF'], 'tiki-ajax_services.php') === false &&
59			strpos($_SERVER['PHP_SELF'], 'tiki-login.php') === false &&
60			strpos($_SERVER['PHP_SELF'], 'tiki-install.php') === false) {
61		$javascript_enabled_detect++;
62		if ($prefs['javascript_assume_enabled'] != 'y') {
63			setCookieSection('javascript_enabled_detect', $javascript_enabled_detect, '', $plus_one_year / 1000);
64		}
65	}
66} elseif ($js_cookie !== 'y') {	// no js cookie detected
67	$prefs['javascript_enabled'] = 'n';
68}
69
70if ($prefs['javascript_enabled'] == 'n') {
71	// disable js dependant features
72	$prefs['feature_tabs'] = 'n';
73	$prefs['feature_jquery'] = 'n';
74	$prefs['feature_shadowbox'] = 'n';
75	$prefs['feature_wysiwyg'] = 'n';
76	$prefs['feature_ajax'] = 'n';
77	$prefs['calendar_fullcalendar'] = 'n';
78	// assign short variable for use in templates
79	$smarty->assign('js', 0);
80	//for use in setting tags for css menus as fallback for action dropdowns in case of no javascript
81	$smarty->assign('libeg', '<li>');
82	$smarty->assign('liend', '</li>');
83}
84
85if ($prefs['javascript_enabled'] == 'y') {	// we have JavaScript
86	// assign short variable for use in templates
87	$smarty->assign('js', 1);
88	//for use in setting tags for css menus as fallback for action dropdowns in case of no javascript
89	$smarty->assign('libeg', '');
90	$smarty->assign('liend', '');
91
92	$prefs['feature_jquery'] = 'y';	// just in case
93
94	// load translations lang object from /lang/xx/language.js if there
95	if (file_exists('lang/' . $prefs['language'] . '/language.js')) {
96		// after the usual lib includes (up to 10) but before custom.js (50)
97		$headerlib
98			->add_jsfile_late('lang/' . $prefs['language'] . '/language.js')
99			->add_js("$.lang = '" . $prefs['language'] . "';");
100	}
101
102
103	/** Use custom.js in lang dir if there **/
104	$language = $prefs['language'];
105	if (is_file("lang/$language/custom.js")) {
106		TikiLib::lib('header')->add_jsfile_late("lang/$language/custom.js");	// before styles custom.js
107	}
108
109	if (! empty($tikidomain) && is_file("lang/$language/$tikidomain/custom.js")) {		// Note: lang tikidomain dirs not created automatically
110		TikiLib::lib('header')->add_jsfile_late("lang/$language/$tikidomain/custom.js");
111	}
112
113
114	/** Use custom.js in themes or options dir if there **/
115	$themelib = TikiLib::lib('theme');
116	//consider Admin Theme
117	if (! empty($prefs['theme_admin']) && ($section === 'admin' || empty($section))) {		// use admin theme if set
118		$custom_js = $themelib->get_theme_path($prefs['theme_admin'], $prefs['theme_option_admin'], 'custom.js');
119	} else {
120		$custom_js = $themelib->get_theme_path($prefs['theme'], $prefs['theme_option'], 'custom.js');
121	}
122	if (! empty($custom_js)) {
123		$headerlib->add_jsfile($custom_js);
124	} else {															// there's no custom.js in the current theme or option
125		$custom_js = $themelib->get_theme_path('', '', 'custom.js');		// so use one in the root of /themes if there
126		if (! empty($custom_js)) {
127			$headerlib->add_jsfile($custom_js);
128		}
129	}
130
131
132
133	// setup timezone array
134	$tz = TikiDate::getTimezoneAbbreviations();
135	$headerlib->add_js(
136		'
137try {
138	var timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
139	setCookie("local_tz", timezone);
140} catch (e) {}
141
142// this is used by tiki-confirm.js checkTimeout, so needs to be always set
143var now = new Date();
144
145if (! timezone) {
146	function inArray(item, array) {
147		for (var i in array) {
148			if (array[i] === item) {
149				return i;
150			}
151		}
152		return false;
153	}
154	var allTimeZoneCodes = ' . json_encode(array_map("strtoupper", $tz)) . ';
155	var now_string = now.toString();
156	var offsethours = - now.getTimezoneOffset() / 60;
157	setCookie("local_tzoffset", offsethours);
158	var m = now_string.match(/[ \(]([A-Z]{3,6})[ \)]?[ \d]*$/);	// try three or more char tz first at the end or just before the year
159	if (!m) {
160		m = now_string.match(/[ \(]([A-Z]{1,6})[ \)]?[ \d]*$/);	// might be a "military" one if not
161	}
162	if (m) {
163		m = m[1];
164	} else {	// IE (sometimes) gives UTC +offset instead of the abbreviation
165		// sadly this workaround will fail for non-whole hour offsets
166		var hours = - now.getTimezoneOffset() / 60;
167		m = "GMT" + (hours > 0 ? "+" : "") + hours;
168	}
169	// Etc/GMT+ is equivalent to GMT-
170	if (m.substring(0,4) == "GMT+") {
171		m = "Etc/GMT-" + m.substring(4);
172		setCookie("local_tz", m);
173	}
174	if (m.substring(0,4) == "GMT-") {
175		m = "Etc/GMT+" + m.substring(4);
176		setCookie("local_tz", m);
177	}
178	if (inArray(m, allTimeZoneCodes)) {
179		setCookie("local_tz", m);
180	}
181}
182',
183		2
184	);
185
186	$jqueryTiki['ui'] = $prefs['feature_jquery_ui'] === 'y' ? true : false;
187	$jqueryTiki['ui_theme'] = $prefs['feature_jquery_ui_theme'];
188	$jqueryTiki['tooltips'] = $prefs['feature_jquery_tooltips'] === 'y' ? true : false;
189	$jqueryTiki['autocomplete'] = $prefs['feature_jquery_autocomplete'] === 'y' ? true : false;
190	$jqueryTiki['superfish'] = $prefs['feature_jquery_superfish'] === 'y' ? true : false;
191	$jqueryTiki['reflection'] = $prefs['feature_jquery_reflection'] === 'y' ? true : false;
192	$jqueryTiki['tablesorter'] = $prefs['feature_jquery_tablesorter'] === 'y' ? true : false;
193	$jqueryTiki['colorbox'] = $prefs['feature_shadowbox'] === 'y' ? true : false;
194	$jqueryTiki['cboxCurrent'] = "{current} / {total}";
195	$jqueryTiki['sheet'] = $prefs['feature_sheet'] === 'y' ? true : false;
196	$jqueryTiki['carousel'] = $prefs['feature_jquery_carousel'] === 'y' ? true : false;
197	$jqueryTiki['validate'] = $prefs['feature_jquery_validation'] === 'y' ? true : false;
198	$jqueryTiki['zoom'] = $prefs['feature_jquery_zoom'] === 'y' ? true : false;
199
200	// Default effect
201	$jqueryTiki['effect'] = $prefs['jquery_effect'];
202	// "horizontal" | "vertical" etc
203	$jqueryTiki['effect_direction'] = $prefs['jquery_effect_direction'];
204	// "slow" | "normal" | "fast" | milliseconds (int) ]
205	$jqueryTiki['effect_speed'] = $prefs['jquery_effect_speed'] === 'normal' ? '400' : $prefs['jquery_effect_speed'];
206	$jqueryTiki['effect_tabs'] = $prefs['jquery_effect_tabs'];		// Different effect for tabs
207	$jqueryTiki['effect_tabs_direction'] = $prefs['jquery_effect_tabs_direction'];
208	$jqueryTiki['effect_tabs_speed'] = $prefs['jquery_effect_tabs_speed'] === 'normal' ? '400' : $prefs['jquery_effect_tabs_speed'];
209	$jqueryTiki['home_file_gallery'] = $prefs['home_file_gallery'];
210
211	$jqueryTiki['autosave'] = $prefs['ajax_autosave'] === 'y' ? true : false;
212	$jqueryTiki['sefurl'] = $prefs['feature_sefurl'] === 'y' ? true : false;
213	$jqueryTiki['ajax'] = $prefs['feature_ajax'] === 'y' ? true : false;
214	$jqueryTiki['syntaxHighlighter'] = $prefs['feature_syntax_highlighter'] === 'y' ? true : false;
215	$jqueryTiki['chosen'] = $prefs['jquery_ui_chosen'] === 'y' ? true : false;
216	$jqueryTiki['chosen_sortable'] = $prefs['jquery_ui_chosen_sortable'] === 'y' ? true : false;
217	$jqueryTiki['mapTileSets'] = $tikilib->get_preference('geo_tilesets', ['openstreetmap'], true);
218	$jqueryTiki['infoboxTypes'] = Services_Object_Controller::supported();
219	$jqueryTiki['googleStreetView'] = $prefs['geo_google_streetview'] === 'y' ? true : false;
220	$jqueryTiki['googleStreetViewOverlay'] = $prefs['geo_google_streetview_overlay'] === 'y' ? true : false;
221	$jqueryTiki['googleMapsAPIKey'] = $prefs['gmap_key'];
222	$jqueryTiki['structurePageRepeat'] = $prefs['page_n_times_in_a_structure'] === 'y' ? true : false;
223	$jqueryTiki['mobile'] = $prefs['mobile_mode'] === 'y' ? true : false;
224	$jqueryTiki['no_cookie'] = false;
225	$jqueryTiki['language'] = $prefs['language'];
226	$jqueryTiki['useInlineComment'] = $prefs['feature_inline_comments'] === 'y' ? true : false;
227	$jqueryTiki['useInlineAnnotations'] = $prefs['comments_inline_annotator'] === 'y' ? true : false;
228	$jqueryTiki['helpurl'] = $prefs['feature_help'] === 'y' ? $prefs['helpurl'] : '';
229	$jqueryTiki['shortDateFormat'] = $prefs['short_date_format_js'];
230	$jqueryTiki['shortTimeFormat'] = $prefs['short_time_format_js'];
231	$jqueryTiki['username'] = $user;
232	$jqueryTiki['userRealName'] = TikiLib::lib('user')->clean_user($user);
233	$jqueryTiki['userAvatar'] = $base_url . TikiLib::lib('userprefs')->get_public_avatar_path($user);
234	$jqueryTiki['autoToc_inline'] = $prefs['wiki_inline_auto_toc'] === 'y' ? true : false;
235	$jqueryTiki['autoToc_pos'] = $prefs['wiki_toc_pos'];
236	$jqueryTiki['autoToc_offset'] = $prefs['wiki_toc_offset'];
237	$jqueryTiki['bingMapsAPIKey'] = $prefs['geo_bingmaps_key'];
238	$jqueryTiki['nextzenAPIKey'] = $prefs['geo_nextzen_key'];
239	$jqueryTiki['numericFieldScroll'] = $prefs['unified_numeric_field_scroll'];
240	//set at 4 hours if empty
241	$jqueryTiki['securityTimeout'] = !empty($prefs['site_security_timeout']) ? $prefs['site_security_timeout']
242		: TikiLib::lib('access')->getDefaultTimeout();
243
244	if (empty($object)) {
245		$object = current_object();
246	}
247	$jqueryTiki['current_object'] = $object;
248
249
250	if ($prefs['feature_calendar'] === 'y') {
251		$calendarlib = TikiLib::lib('calendar');
252		$jqueryTiki['firstDayofWeek'] = $calendarlib->firstDayofWeek();
253	}
254
255	$js = '
256// JS Object to hold prefs for jq
257var jqueryTiki = ' . json_encode($jqueryTiki, JSON_UNESCAPED_SLASHES) . "\n";
258
259	if ($prefs['feature_syntax_highlighter'] !== 'y') {
260		// add a dummy syntaxHighlighter object as it seems to be used all over the place without checking for the feature
261		$js .= '
262var syntaxHighlighter = {
263	ready: function(textarea, settings) { return null; },
264	sync: function(textarea) { return null; },
265	add: function(editor, $input, none, skipResize) { return null; },
266	remove: function($input) { return null; },
267	get: function($input) { return null; },
268	fullscreen: function(textarea) { return null; },
269	find: function(textareaEditor, val) { return null; },
270	searchCursor: [],
271	replace: function(textareaEditor, val, replaceVal) { return null; },
272	insertAt: function(textareaEditor, replaceString, perLine, blockLevel) { return null; }
273};
274';
275	}
276
277	if ($prefs['jquery_ui_modals_draggable'] === 'y') {
278		$js .= '
279$(document).on("shown.bs.modal", function (event) {
280	$(event.target).find(".modal-dialog")
281		.css({left: "", top: ""})
282		.draggable({
283			 handle: ".modal-header",
284			 cursor: "grabbing"
285		});
286});
287';
288		$headerlib->add_css('.modal-header {cursor: grab}');
289	}
290
291	if ($prefs['jquery_ui_modals_resizable'] === 'y') {
292		$js .= '
293$(document).on("tiki.modal.redraw", function (event) {
294	var $modalContent = $(event.target);
295	if (! $modalContent.is(".modal-content")) {
296		$modalContent = $modalContent.find(".modal-content")
297	}
298	if ($modalContent.is(".ui-resizable")) {
299		$modalContent.resizable( "destroy" );
300	}
301	$modalContent
302		.css({width: "", height: ""})
303		.resizable({
304			minHeight: 100,
305			minWidth: 200
306		})
307		.find(".modal-body").css({
308			"overflow": "auto"
309		});
310});';
311	}
312
313	$headerlib->add_js($js);
314}
315
316if ($prefs['feature_ajax'] != 'y') {
317	$prefs['ajax_autosave'] = 'n';
318}
319