PageRenderTime 89ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 1ms

/core/inc/bigtree/admin.php

https://github.com/philp/BigTree-CMS
PHP | 5582 lines | 2839 code | 674 blank | 2069 comment | 667 complexity | 0afe53e60456baae952d671ba41e975a MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1
  1. <?
  2. /*
  3. Class: BigTreeAdmin
  4. The main class used by the admin for manipulating and retrieving data.
  5. */
  6. class BigTreeAdmin {
  7. var $PerPage = 15;
  8. // !View Types
  9. var $ViewTypes = array(
  10. "searchable" => "Searchable List",
  11. "draggable" => "Draggable List",
  12. "images" => "Image List",
  13. "grouped" => "Grouped List",
  14. "images-grouped" => "Grouped Image List"
  15. );
  16. // !Reserved Column Names
  17. var $ReservedColumns = array(
  18. "id",
  19. "position",
  20. "archived",
  21. "approved"
  22. );
  23. // !View Actions
  24. var $ViewActions = array(
  25. "approve" => array(
  26. "key" => "approved",
  27. "name" => "Approve",
  28. "class" => "icon_approve icon_approve_on"
  29. ),
  30. "archive" => array(
  31. "key" => "archived",
  32. "name" => "Archive",
  33. "class" => "icon_archive"
  34. ),
  35. "feature" => array(
  36. "key" => "featured",
  37. "name" => "Feature",
  38. "class" => "icon_feature icon_feature_on"
  39. ),
  40. "edit" => array(
  41. "key" => "id",
  42. "name" => "Edit",
  43. "class" => "icon_edit"
  44. ),
  45. "delete" => array(
  46. "key" => "id",
  47. "name" => "Delete",
  48. "class" => "icon_delete"
  49. )
  50. );
  51. /*
  52. Constructor:
  53. Initializes the user's permissions.
  54. */
  55. function __construct() {
  56. if (isset($_SESSION["bigtree"]["email"])) {
  57. $this->ID = $_SESSION["bigtree"]["id"];
  58. $this->User = $_SESSION["bigtree"]["email"];
  59. $this->Level = $_SESSION["bigtree"]["level"];
  60. $this->Name = $_SESSION["bigtree"]["name"];
  61. $this->Permissions = $_SESSION["bigtree"]["permissions"];
  62. } elseif (isset($_COOKIE["bigtree"]["email"])) {
  63. $user = mysql_escape_string($_COOKIE["bigtree"]["email"]);
  64. $pass = mysql_escape_string($_COOKIE["bigtree"]["password"]);
  65. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE email = '$user' AND password = '$pass'"));
  66. if ($f) {
  67. $this->ID = $f["id"];
  68. $this->User = $user;
  69. $this->Level = $f["level"];
  70. $this->Name = $f["name"];
  71. $this->Permissions = json_decode($f["permissions"],true);
  72. $_SESSION["bigtree"]["id"] = $f["id"];
  73. $_SESSION["bigtree"]["email"] = $f["email"];
  74. $_SESSION["bigtree"]["level"] = $f["level"];
  75. $_SESSION["bigtree"]["name"] = $f["name"];
  76. $_SESSION["bigtree"]["permissions"] = $this->Permissions;
  77. }
  78. }
  79. }
  80. /*
  81. Function: archivePage
  82. Archives a page.
  83. Parameters:
  84. page - Either a page id or page entry.
  85. Returns:
  86. true if successful. false if the logged in user doesn't have permission.
  87. See Also:
  88. <archivePageChildren>
  89. */
  90. function archivePage($page) {
  91. global $cms;
  92. if (is_array($page)) {
  93. $page = mysql_real_escape_string($page["id"]);
  94. } else {
  95. $page = mysql_real_escape_string($page);
  96. }
  97. $access = $this->getPageAccessLevel($page);
  98. if ($access == "p" && $this->canModifyChildren($cms->getPage($page))) {
  99. sqlquery("UPDATE bigtree_pages SET archived = 'on' WHERE id = '$page'");
  100. $this->archivePageChildren($page);
  101. $this->growl("Pages","Archived Page");
  102. $this->track("bigtree_pages",$page,"archived");
  103. return true;
  104. }
  105. return false;
  106. }
  107. /*
  108. Function: archivePageChildren
  109. Archives a page's children and sets the archive status to inherited.
  110. Parameters:
  111. page - A page id.
  112. See Also:
  113. <archivePage>
  114. */
  115. function archivePageChildren($page) {
  116. $page = mysql_real_escape_string($page);
  117. $q = sqlquery("SELECT * FROM bigtree_pages WHERE parent = '$page'");
  118. while ($f = sqlfetch($q)) {
  119. if (!$f["archived"]) {
  120. sqlquery("UPDATE bigtree_pages SET archived = 'on', archived_inherited = 'on' WHERE id = '".$f["id"]."'");
  121. $this->track("bigtree_pages",$f["id"],"archived");
  122. $this->archivePageChildren($f["id"]);
  123. }
  124. }
  125. }
  126. /*
  127. Function: autoIPL
  128. Automatically converts links to internal page links.
  129. Parameters:
  130. html - A string of contents that may contain URLs
  131. Returns:
  132. A string with hard links converted into internal page links.
  133. */
  134. function autoIPL($html) {
  135. // If this string is actually just a URL, IPL it.
  136. if (substr($html,0,7) == "http://" || substr($html,0,8) == "https://") {
  137. $html = $this->makeIPL($html);
  138. // Otherwise, switch all the image srcs and javascripts srcs and whatnot to {wwwroot}.
  139. } else {
  140. $html = preg_replace_callback('/href="([^"]*)"/',create_function('$matches','
  141. global $cms;
  142. $href = str_replace("{wwwroot}",$GLOBALS["www_root"],$matches[1]);
  143. if (strpos($href,$GLOBALS["www_root"]) !== false) {
  144. $command = explode("/",rtrim(str_replace($GLOBALS["www_root"],"",$href),"/"));
  145. list($navid,$commands) = $cms->getNavId($command);
  146. $page = $cms->getPage($navid,false);
  147. if ($navid && (!$commands[0] || substr($page["template"],0,6) == "module" || substr($commands[0],0,1) == "#")) {
  148. $href = "ipl://".$navid."//".base64_encode(json_encode($commands));
  149. }
  150. }
  151. $href = str_replace($GLOBALS["www_root"],"{wwwroot}",$href);
  152. return \'href="\'.$href.\'"\';'
  153. ),$html);
  154. $html = str_replace($GLOBALS["www_root"],"{wwwroot}",$html);
  155. }
  156. return $html;
  157. }
  158. /*
  159. Function: canAccessGroup
  160. Returns whether or not the logged in user can access a module group.
  161. Utility for form field types / views -- we already know module group permissions are enabled so we skip some overhead
  162. Parameters:
  163. module - A module entry.
  164. group - A group id.
  165. Returns:
  166. true if the user can access this group, otherwise false.
  167. */
  168. function canAccessGroup($module,$group) {
  169. if ($this->Level > 0) {
  170. return true;
  171. }
  172. $id = $module["id"];
  173. if ($this->Permissions["module"][$id] && $this->Permissions["module"][$id] != "n") {
  174. return true;
  175. }
  176. if (is_array($this->Permissions["module_gbp"][$id])) {
  177. $gp = $this->Permissions["module_gbp"][$id][$group];
  178. if ($gp && $gp != "n") {
  179. return true;
  180. }
  181. }
  182. return false;
  183. }
  184. /*
  185. Function: canModifyChildren
  186. Checks whether the logged in user can modify all child pages or a page.
  187. Assumes we already know that we're a publisher of the parent.
  188. Parameters:
  189. page - The page entry to check children for.
  190. Returns:
  191. true if the user can modify all the page children, otherwise false.
  192. */
  193. function canModifyChildren($page) {
  194. if ($this->Level > 0) {
  195. return true;
  196. }
  197. $q = sqlquery("SELECT id FROM bigtree_pages WHERE path LIKE '".mysql_real_escape_string($page["path"])."%'");
  198. while ($f = sqlfetch($q)) {
  199. $perm = $this->Permissions["page"][$f["id"]];
  200. if ($perm == "n" || $perm == "e") {
  201. return false;
  202. }
  203. }
  204. return true;
  205. }
  206. /*
  207. Function: changePassword
  208. Changes a user's password via a password change hash and redirects to a success page.
  209. Paramters:
  210. hash - The unique hash generated by <forgotPassword>.
  211. password - The user's new password.
  212. See Also:
  213. <forgotPassword>
  214. */
  215. function changePassword($hash,$password) {
  216. global $config;
  217. $hash = mysql_real_escape_string($hash);
  218. $user = sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE change_password_hash = '$hash'"));
  219. $phpass = new PasswordHash($config["password_depth"], TRUE);
  220. $password = mysql_real_escape_string($phpass->HashPassword($password));
  221. sqlquery("UPDATE bigtree_users SET password = '$password', change_password_hash = '' WHERE id = '".$user["id"]."'");
  222. header("Location: ".$GLOBALS["admin_root"]."login/reset-success/");
  223. die();
  224. }
  225. /*
  226. Function: checkAccess
  227. Determines whether the logged in user has access to a module or not.
  228. Parameters:
  229. module - Either a module id or module entry.
  230. Returns:
  231. true if the user can access the module, otherwise false.
  232. */
  233. function checkAccess($module) {
  234. if (is_array($module)) {
  235. $module = $module["id"];
  236. }
  237. if ($this->Level > 0) {
  238. return true;
  239. }
  240. if ($this->Permissions["module"][$module] && $this->Permissions["module"][$module] != "n") {
  241. return true;
  242. }
  243. if (is_array($this->Permissions["module_gbp"][$module])) {
  244. foreach ($this->Permissions["module_gbp"][$module] as $p) {
  245. if ($p != "n") {
  246. return true;
  247. }
  248. }
  249. }
  250. return false;
  251. }
  252. /*
  253. Function: checkHTML
  254. Checks a block of HTML for broken links/images
  255. Parameters:
  256. relative_path - The starting path of the page containing the HTML (so that relative links, i.e. "good/" know where to begin)
  257. html - A string of HTML
  258. external - Whether to check external links (slow) or not
  259. Returns:
  260. An array of errors.
  261. */
  262. function checkHTML($relative_path,$html,$external = false) {
  263. if (!$html) {
  264. return array();
  265. }
  266. $errors = array();
  267. $doc = new DOMDocument();
  268. $doc->loadHTML($html);
  269. // Check A tags.
  270. $links = $doc->getElementsByTagName("a");
  271. foreach ($links as $link) {
  272. $href = $link->getAttribute("href");
  273. $href = str_replace(array("{wwwroot}","%7Bwwwroot%7D"),$GLOBALS["www_root"],$href);
  274. if (substr($href,0,4) == "http" && strpos($href,$GLOBALS["www_root"]) === false) {
  275. // External link, not much we can do but alert that it's dead
  276. if ($external) {
  277. if (strpos($href,"#") !== false)
  278. $href = substr($href,0,strpos($href,"#")-1);
  279. if (!$this->urlExists($href)) {
  280. $errors["a"][] = $href;
  281. }
  282. }
  283. } elseif (substr($href,0,6) == "ipl://") {
  284. if (!$this->iplExists($href)) {
  285. $errors["a"][] = $href;
  286. }
  287. } elseif (substr($href,0,7) == "mailto:" || substr($href,0,1) == "#" || substr($href,0,5) == "data:") {
  288. // Don't do anything, it's a page mark, data URI, or email address
  289. } elseif (substr($href,0,4) == "http") {
  290. // It's a local hard link
  291. if (!$this->urlExists($href)) {
  292. $errors["a"][] = $href;
  293. }
  294. } else {
  295. // Local file.
  296. $local = $relative_path.$href;
  297. if (!$this->urlExists($local)) {
  298. $errors["a"][] = $local;
  299. }
  300. }
  301. }
  302. // Check IMG tags.
  303. $images = $doc->getElementsByTagName("img");
  304. foreach ($images as $image) {
  305. $href = $image->getAttribute("src");
  306. $href = str_replace(array("{wwwroot}","%7Bwwwroot%7D"),$GLOBALS["www_root"],$href);
  307. if (substr($href,0,4) == "http" && strpos($href,$GLOBALS["www_root"]) === false) {
  308. // External link, not much we can do but alert that it's dead
  309. if ($external) {
  310. if (!$this->urlExists($href)) {
  311. $errors["img"][] = $href;
  312. }
  313. }
  314. } elseif (substr($href,0,6) == "ipl://") {
  315. if (!$this->iplExists($href)) {
  316. $errors["a"][] = $href;
  317. }
  318. } elseif (substr($href,0,5) == "data:") {
  319. // Do nothing, it's a data URI
  320. } elseif (substr($href,0,4) == "http") {
  321. // It's a local hard link
  322. if (!$this->urlExists($href)) {
  323. $errors["img"][] = $href;
  324. }
  325. } else {
  326. // Local file.
  327. $local = $relative_path.$href;
  328. if (!$this->urlExists($local)) {
  329. $errors["img"][] = $local;
  330. }
  331. }
  332. }
  333. return array($errors);
  334. }
  335. /*
  336. Function: clearCache
  337. Removes all files in the cache directory.
  338. */
  339. function clearCache() {
  340. $d = opendir($GLOBALS["server_root"]."cache/");
  341. while ($f = readdir($d)) {
  342. if ($f != "." && $f != ".." && !is_dir($GLOBALS["server_root"]."cache/".$f)) {
  343. unlink($GLOBALS["server_root"]."cache/".$f);
  344. }
  345. }
  346. }
  347. /*
  348. Function: createCallout
  349. Creates a callout and its files.
  350. Parameters:
  351. id - The id.
  352. name - The name.
  353. description - The description.
  354. level - Access level (0 for everyone, 1 for administrators, 2 for developers).
  355. resources - An array of resources.
  356. */
  357. function createCallout($id,$name,$description,$level,$resources) {
  358. // If we're creating a new file, let's populate it with some convenience things to show what resources are available.
  359. $file_contents = '<?
  360. /*
  361. Resources Available:
  362. ';
  363. $cached_types = $this->getCachedFieldTypes();
  364. $types = $cached_types["callout"];
  365. $clean_resources = array();
  366. foreach ($resources as $resource) {
  367. if ($resource["id"] && $resource["id"] != "type") {
  368. $options = json_decode($resource["options"],true);
  369. foreach ($options as $key => $val) {
  370. if ($key != "title" && $key != "id" && $key != "type") {
  371. $resource[$key] = $val;
  372. }
  373. }
  374. $file_contents .= ' $'.$resource["id"].' = '.$resource["title"].' - '.$types[$resource["type"]]."\n";
  375. $resource["id"] = htmlspecialchars($resource["id"]);
  376. $resource["title"] = htmlspecialchars($resource["title"]);
  377. $resource["subtitle"] = htmlspecialchars($resource["subtitle"]);
  378. unset($resource["options"]);
  379. $clean_resources[] = $resource;
  380. }
  381. }
  382. $file_contents .= ' */
  383. ?>';
  384. // Clean up the post variables
  385. $id = mysql_real_escape_string(htmlspecialchars($id));
  386. $name = mysql_real_escape_string(htmlspecialchars($name));
  387. $description = mysql_real_escape_string(htmlspecialchars($description));
  388. $level = mysql_real_escape_string($level);
  389. $resources = mysql_real_escape_string(json_encode($clean_resources));
  390. if (!file_exists($GLOBALS["server_root"]."templates/callouts/".$id.".php")) {
  391. file_put_contents($GLOBALS["server_root"]."templates/callouts/".$id.".php",$file_contents);
  392. chmod($GLOBALS["server_root"]."templates/callouts/".$id.".php",0777);
  393. }
  394. sqlquery("INSERT INTO bigtree_callouts (`id`,`name`,`description`,`resources`,`level`) VALUES ('$id','$name','$description','$resources','$level')");
  395. }
  396. /*
  397. Function: createFeed
  398. Creates a feed.
  399. Parameters:
  400. name - The name.
  401. description - The description.
  402. table - The data table.
  403. type - The feed type.
  404. options - The feed type options.
  405. fields - The fields.
  406. Returns:
  407. The route to the new feed.
  408. */
  409. function createFeed($name,$description,$table,$type,$options,$fields) {
  410. global $cms;
  411. // Options were encoded before submitting the form, so let's get them back.
  412. $options = json_decode($options,true);
  413. if (is_array($options)) {
  414. foreach ($options as &$option) {
  415. $option = str_replace($www_root,"{wwwroot}",$option);
  416. }
  417. }
  418. // Get a unique route!
  419. $route = $cms->urlify($name);
  420. $x = 2;
  421. $oroute = $route;
  422. $f = $cms->getFeedByRoute($route);
  423. while ($f) {
  424. $route = $oroute."-".$x;
  425. $f = $cms->getFeedByRoute($route);
  426. $x++;
  427. }
  428. // Fix stuff up for the db.
  429. $name = mysql_real_escape_string(htmlspecialchars($name));
  430. $description = mysql_real_escape_string(htmlspecialchars($description));
  431. $table = mysql_real_escape_string($table);
  432. $type = mysql_real_escape_string($type);
  433. $options = mysql_real_escape_string(json_encode($options));
  434. $fields = mysql_real_escape_string(json_encode($fields));
  435. $route = mysql_real_escape_string($route);
  436. sqlquery("INSERT INTO bigtree_feeds (`route`,`name`,`description`,`type`,`table`,`fields`,`options`) VALUES ('$route','$name','$description','$type','$table','$fields','$options')");
  437. return $route;
  438. }
  439. /*
  440. Function: createFieldType
  441. Creates a field type and its files.
  442. Parameters:
  443. id - The id of the field type.
  444. name - The name.
  445. pages - Whether it can be used as a page resource or not ("on" is yes)
  446. modules - Whether it can be used as a module resource or not ("on" is yes)
  447. callouts - Whether it can be used as a callout resource or not ("on" is yes)
  448. */
  449. function createFieldType($id,$name,$pages,$modules,$callouts) {
  450. $id = mysql_real_escape_string($id);
  451. $name = mysql_real_escape_string(htmlspecialchars($name));
  452. $author = mysql_real_escape_string($this->Name);
  453. $pages = mysql_real_escape_string($pages);
  454. $modules = mysql_real_escape_string($modules);
  455. $callouts = mysql_real_escape_string($callouts);
  456. $file = "$id.php";
  457. sqlquery("INSERT INTO bigtree_field_types (`id`,`name`,`pages`,`modules`,`callouts`) VALUES ('$id','$name','$pages','$modules','$callouts')");
  458. // Make the files for draw and process and options if they don't exist.
  459. if (!file_exists($GLOBALS["server_root"]."custom/admin/form-field-types/draw/$file")) {
  460. BigTree::touchFile($GLOBALS["server_root"]."custom/admin/form-field-types/draw/$file");
  461. file_put_contents($GLOBALS["server_root"]."custom/admin/form-field-types/draw/$file",'<? include BigTree::path("admin/form-field-types/draw/text.php"); ?>');
  462. chmod($GLOBALS["server_root"]."custom/admin/form-field-types/draw/$file",0777);
  463. }
  464. if (!file_exists($GLOBALS["server_root"]."custom/admin/form-field-types/process/$file")) {
  465. BigTree::touchFile($GLOBALS["server_root"]."custom/admin/form-field-types/process/$file");
  466. file_put_contents($GLOBALS["server_root"]."custom/admin/form-field-types/process/$file",'<? $value = $data[$key]; ?>');
  467. chmod($GLOBALS["server_root"]."custom/admin/form-field-types/process/$file",0777);
  468. }
  469. if (!file_exists($GLOBALS["server_root"]."custom/admin/ajax/developer/field-options/$file")) {
  470. BigTree::touchFile($GLOBALS["server_root"]."custom/admin/ajax/developer/field-options/$file");
  471. chmod($GLOBALS["server_root"]."custom/admin/ajax/developer/field-options/$file",0777);
  472. }
  473. unlink($GLOBALS["server_root"]."cache/form-field-types.btc");
  474. }
  475. /*
  476. Function: createMessage
  477. Creates a message in message center.
  478. Parameters:
  479. subject - The subject line.
  480. message - The message.
  481. recipients - The recipients.
  482. in_response_to - The message being replied to.
  483. */
  484. function createMessage($subject,$message,$recipients,$in_response_to = 0) {
  485. // Clear tags out of the subject, sanitize the message body of XSS attacks.
  486. $subject = mysql_real_escape_string(htmlspecialchars(strip_tags($subject)));
  487. $message = mysql_real_escape_string(strip_tags($message,"<p><b><strong><em><i><a>"));
  488. $in_response_to = mysql_real_escape_string($in_response_to);
  489. // We build the send_to field this way so that we don't have to create a second table of recipients.
  490. // Is it faster database wise using a LIKE over a JOIN? I don't know, but it makes for one less table.
  491. $send_to = "|";
  492. foreach ($recipients as $r) {
  493. // Make sure they actually put in a number and didn't try to screw with the $_POST
  494. $send_to .= intval($r)."|";
  495. }
  496. $send_to = mysql_real_escape_string($send_to);
  497. sqlquery("INSERT INTO bigtree_messages (`sender`,`recipients`,`subject`,`message`,`date`,`response_to`) VALUES ('".$this->ID."','$send_to','$subject','$message',NOW(),'$in_response_to')");
  498. }
  499. /*
  500. Function: createModule
  501. Creates a module and its class file.
  502. Parameters:
  503. name - The name of the module.
  504. group - The group for the module.
  505. class - The module class to create.
  506. table - The table this module relates to.
  507. permissions - The group-based permissions.
  508. Returns:
  509. The new module id.
  510. */
  511. function createModule($name,$group,$class,$table,$permissions) {
  512. global $cms;
  513. // Find an available module route.
  514. $route = $cms->urlify($name);
  515. // Go through the hard coded modules
  516. $existing = array();
  517. $d = opendir($GLOBALS["server_root"]."core/admin/modules/");
  518. while ($f = readdir($d)) {
  519. if ($f != "." && $f != "..") {
  520. $existing[] = $f;
  521. }
  522. }
  523. // Go through the directories (really ajax, css, images, js)
  524. $d = opendir($GLOBALS["server_root"]."core/admin/");
  525. while ($f = readdir($d)) {
  526. if ($f != "." && $f != "..") {
  527. $existing[] = $f;
  528. }
  529. }
  530. // Go through the hard coded pages
  531. $d = opendir($GLOBALS["server_root"]."core/admin/pages/");
  532. while ($f = readdir($d)) {
  533. if ($f != "." && $f != "..") {
  534. // Drop the .php
  535. $existing[] = substr($f,0,-4);
  536. }
  537. }
  538. // Go through already created modules
  539. $q = sqlquery("SELECT route FROM bigtree_modules");
  540. while ($f = sqlfetch($q)) {
  541. $existing[] = $f["route"];
  542. }
  543. // Get a unique route
  544. $x = 2;
  545. $oroute = $route;
  546. while (in_array($route,$existing)) {
  547. $route = $oroute."-".$x;
  548. $x++;
  549. }
  550. $name = mysql_real_escape_string(htmlspecialchars($name));
  551. $route = mysql_real_escape_string($route);
  552. $class = mysql_real_escape_string($class);
  553. $group = mysql_real_escape_string($group);
  554. $gbp = mysql_real_escape_string(json_encode($permissions));
  555. sqlquery("INSERT INTO bigtree_modules (`name`,`route`,`class`,`group`,`gbp`) VALUES ('$name','$route','$class','$group','$gbp')");
  556. $id = sqlid();
  557. if ($class) {
  558. // Create class module.
  559. $f = fopen($GLOBALS["server_root"]."custom/inc/modules/$route.php","w");
  560. fwrite($f,"<?\n");
  561. fwrite($f," class $class extends BigTreeModule {\n");
  562. fwrite($f,"\n");
  563. fwrite($f,' var $Table = "'.$table.'";'."\n");
  564. fwrite($f,' var $Module = "'.$id.'";'."\n");
  565. fwrite($f," }\n");
  566. fwrite($f,"?>\n");
  567. fclose($f);
  568. chmod($GLOBALS["server_root"]."custom/inc/modules/$route.php",0777);
  569. // Remove cached class list.
  570. unlink($GLOBALS["server_root"]."cache/module-class-list.btc");
  571. }
  572. return $id;
  573. }
  574. /*
  575. Function: createModuleAction
  576. Creates a module action.
  577. Parameters:
  578. module - The module to create an action for.
  579. name - The name of the action.
  580. route - The action route.
  581. in_nav - Whether the action is in the navigation.
  582. icon - The icon class for the action.
  583. form - Optional auto module form id.
  584. view - Optional auto module view id.
  585. */
  586. function createModuleAction($module,$name,$route,$in_nav,$icon,$form = 0,$view = 0) {
  587. $module = mysql_real_escape_string($module);
  588. $route = mysql_real_escape_string(htmlspecialchars($route));
  589. $in_nav = mysql_real_escape_string($in_nav);
  590. $icon = mysql_real_escape_string($icon);
  591. $name = mysql_real_escape_string(htmlspecialchars($name));
  592. $form = mysql_real_escape_string($form);
  593. $view = mysql_real_escape_string($view);
  594. $oroute = $route;
  595. $x = 2;
  596. while ($f = sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '$module' AND route = '$route'"))) {
  597. $route = $oroute."-".$x;
  598. $x++;
  599. }
  600. sqlquery("INSERT INTO bigtree_module_actions (`module`,`name`,`route`,`in_nav`,`class`,`form`,`view`) VALUES ('$module','$name','$route','$in_nav','$icon','$form','$view')");
  601. }
  602. /*
  603. Function: createModuleForm
  604. Creates a module form.
  605. Parameters:
  606. title - The title of the form.
  607. table - The table for the form data.
  608. fields - The form fields.
  609. javascript - Optional Javascript file to include in the form.
  610. css - Optional CSS file to include in the form.
  611. callback - Optional callback function to run after the form processes.
  612. default_position - Default position for entries to the form (if the view is positioned).
  613. Returns:
  614. The new form id.
  615. */
  616. function createModuleForm($title,$table,$fields,$javascript = "",$css = "",$callback = "",$default_position = "") {
  617. $title = mysql_real_escape_string(htmlspecialchars($title));
  618. $table = mysql_real_escape_string($table);
  619. $fields = mysql_real_escape_string(json_encode($fields));
  620. $javascript - mysql_real_escape_string(htmlspecialchars($javascript));
  621. $css - mysql_real_escape_string(htmlspecialchars($css));
  622. $callback - mysql_real_escape_string($callback);
  623. $default_position - mysql_real_escape_string($default_position);
  624. sqlquery("INSERT INTO bigtree_module_forms (`title`,`table`,`fields`,`javascript`,`css`,`callback`,`default_position`) VALUES ('$title','$table','$fields','$javascript','$css','$callback','$default_position')");
  625. return sqlid();
  626. }
  627. /*
  628. Function: createModuleGroup
  629. Creates a module group.
  630. Parameters:
  631. name - The name of the group.
  632. package - The (optional) package id the group originated from.
  633. Returns:
  634. The id of the newly created group.
  635. */
  636. function createModuleGroup($name,$in_nav,$package = 0) {
  637. global $cms;
  638. $name = mysql_real_escape_string($name);
  639. $packge = mysql_real_escape_string($package);
  640. // Get a unique route
  641. $x = 2;
  642. $route = $cms->urlify($name);
  643. $oroute = $route;
  644. while ($this->getModuleGroupByRoute($route)) {
  645. $route = $oroute."-".$x;
  646. $x++;
  647. }
  648. // Just to be safe
  649. $route = mysql_real_escape_string($route);
  650. sqlquery("INSERT INTO bigtree_module_groups (`name`,`route`,`in_nav`,`package`) VALUES ('$name','$route','$in_nav','$package')");
  651. return sqlid();
  652. }
  653. /*
  654. Function: createModuleView
  655. Creates a module view.
  656. Parameters:
  657. title - View title.
  658. description - Description.
  659. table - Data table.
  660. type - View type.
  661. options - View options array.
  662. fields - Field array.
  663. actions - Actions array.
  664. suffix - Add/Edit suffix.
  665. uncached - Don't cache the view.
  666. preview_url - Optional preview URL.
  667. Returns:
  668. The id for view.
  669. */
  670. function createModuleView($title,$description,$table,$type,$options,$fields,$actions,$suffix,$uncached = "",$preview_url = "") {
  671. $title = mysql_real_escape_string(htmlspecialchars($title));
  672. $description = mysql_real_escape_string(htmlspecialchars($description));
  673. $table = mysql_real_escape_string($table);
  674. $type = mysql_real_escape_string($type);
  675. $options = mysql_real_escape_string(json_encode($options));
  676. $fields = mysql_real_escape_string(json_encode($fields));
  677. $actions = mysql_real_escape_string(json_encode($actions));
  678. $suffix = mysql_real_escape_string($suffix);
  679. $uncached = mysql_real_escape_string($uncached);
  680. $preview_url = mysql_real_escape_string(htmlspecialchars($preview_url));
  681. sqlquery("INSERT INTO bigtree_module_views (`title`,`description`,`type`,`fields`,`actions`,`table`,`options`,`suffix`,`uncached`,`preview_url`) VALUES ('$title','$description','$type','$fields','$actions','$table','$options','$suffix','$uncached','$preview_url')");
  682. return sqlid();
  683. }
  684. /*
  685. Function: createPage
  686. Creates a page.
  687. Does not check permissions.
  688. Parameters:
  689. data - An array of page information.
  690. Returns:
  691. The id of the newly created page.
  692. */
  693. function createPage($data) {
  694. global $cms;
  695. // Loop through the posted data, make sure no session hijacking is done.
  696. foreach ($data as $key => $val) {
  697. if (substr($key,0,1) != "_") {
  698. if (is_array($val)) {
  699. $$key = mysql_real_escape_string(json_encode($val));
  700. } else {
  701. $$key = mysql_real_escape_string($val);
  702. }
  703. }
  704. }
  705. // If there's an external link, make sure it's a relative URL
  706. if ($external) {
  707. $external = $this->makeIPL($external);
  708. }
  709. // Who knows what they may have put in for a route, so we're not going to use the mysql_real_escape_string version.
  710. $route = $data["route"];
  711. if (!$route) {
  712. // If they didn't specify a route use the navigation title
  713. $route = $cms->urlify($data["nav_title"]);
  714. } else {
  715. // Otherwise sanitize the one they did provide.
  716. $route = $cms->urlify($route);
  717. }
  718. // We need to figure out a unique route for the page. Make sure it doesn't match a directory in /site/
  719. $original_route = $route;
  720. $x = 2;
  721. // Reserved paths.
  722. if ($parent == 0) {
  723. while (file_exists($GLOBALS["server_root"]."site/".$route."/")) {
  724. $route = $original_route."-".$x;
  725. $x++;
  726. }
  727. }
  728. // Make sure it doesn't have the same route as any of its siblings.
  729. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_pages WHERE `route` = '$route' AND parent = '$parent'"));
  730. while ($f) {
  731. $route = $original_route."-".$x;
  732. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_pages WHERE `route` = '$route' AND parent = '$parent'"));
  733. $x++;
  734. }
  735. // If we have a parent, get the full navigation path, otherwise, just use this route as the path since it's top level.
  736. if ($parent) {
  737. $path = $this->getFullNavigationPath($parent)."/".$route;
  738. } else {
  739. $path = $route;
  740. }
  741. // If we set a publish at date, make it the proper MySQL format.
  742. if ($publish_at) {
  743. $publish_at = "'".date("Y-m-d",strtotime($publish_at))."'";
  744. } else {
  745. $publish_at = "NULL";
  746. }
  747. // If we set an expiration date, make it the proper MySQL format.
  748. if ($expire_at) {
  749. $expire_at = "'".date("Y-m-d",strtotime($expire_at))."'";
  750. } else {
  751. $expire_at = "NULL";
  752. }
  753. // Make the title, navigation title, description, keywords, and external link htmlspecialchar'd -- these are all things we'll be echoing in the HTML so we might as well make them valid now instead of at display time.
  754. $title = htmlspecialchars($title);
  755. $nav_title = htmlspecialchars($nav_title);
  756. $meta_description = htmlspecialchars($meta_description);
  757. $meta_keywords = htmlspecialchars($meta_keywords);
  758. $external = htmlspecialchars($external);
  759. // Make the page!
  760. sqlquery("INSERT INTO bigtree_pages (`parent`,`nav_title`,`route`,`path`,`in_nav`,`title`,`template`,`external`,`new_window`,`resources`,`callouts`,`meta_keywords`,`meta_description`,`last_edited_by`,`created_at`,`updated_at`,`publish_at`,`expire_at`,`max_age`) VALUES ('$parent','$nav_title','$route','$path','$in_nav','$title','$template','$external','$new_window','$resources','$callouts','$meta_keywords','$meta_description','".$this->ID."',NOW(),NOW(),$publish_at,$expire_at,'$max_age')");
  761. $id = sqlid();
  762. // Handle tags
  763. if (is_array($data["_tags"])) {
  764. foreach ($data["_tags"] as $tag) {
  765. sqlquery("INSERT INTO bigtree_tags_rel (`module`,`entry`,`tag`) VALUES ('0','$id','$tag')");
  766. }
  767. }
  768. // If there was an old page that had previously used this path, dump its history so we can take over the path.
  769. sqlquery("DELETE FROM bigtree_route_history WHERE old_route = '$path'");
  770. // Dump the cache, we don't really know how many pages may be showing this now in their nav.
  771. $this->clearCache();
  772. // Let search engines know this page now exists.
  773. $this->pingSearchEngines();
  774. // Audit trail.
  775. $this->track("bigtree_pages",$id,"created");
  776. return $id;
  777. }
  778. /*
  779. Function: createPendingChange
  780. Creates a pending change.
  781. Parameters:
  782. table - The table the change applies to.
  783. item_id - The entry the change applies to's id.
  784. changes - The changes to the fields in the entry.
  785. mtm_changes - Many to Many changes.
  786. tags_changes - Tags changes.
  787. module - The module id for the change.
  788. Returns:
  789. The change id.
  790. */
  791. function createPendingChange($table,$item_id,$changes,$mtm_changes = array(),$tags_changes = array(),$module = 0) {
  792. $table = mysql_real_escape_string($table);
  793. $item_id = mysql_real_escape_string($item_id);
  794. $changes = mysql_real_escape_string(json_encode($changes));
  795. $mtm_changes = mysql_real_escape_string(json_encode($mtm_changes));
  796. $tags_changes = mysql_real_escape_string(json_encode($tags_changes));
  797. $module = mysql_real_escape_string($module);
  798. sqlquery("INSERT INTO bigtree_pending_changes (`user`,`date`,`table`,`item_id`,`changes`,`mtm_changes`,`tags_changes`,`module`) VALUES ('".$this->ID."',NOW(),'$table','$item_id','$changes','$mtm_changes','$tags_changes','$module')");
  799. return sqlid();
  800. }
  801. /*
  802. Function: createPendingPage
  803. Creates a pending page entry in bigtree_pending_changes
  804. Parameters:
  805. data - An array of page information.
  806. Returns:
  807. The id of the pending change.
  808. */
  809. function createPendingPage($data) {
  810. global $cms;
  811. // Make a relative URL for external links.
  812. if ($data["external"]) {
  813. $data["external"] = $this->makeIPL($data["external"]);
  814. }
  815. // Save the tags, then dump them from the saved changes array.
  816. $tags = mysql_real_escape_string(json_encode($data["_tags"]));
  817. unset($data["_tags"]);
  818. // Make the nav title, title, external link, keywords, and description htmlspecialchar'd for displaying on the front end / the form again.
  819. $data["nav_title"] = htmlspecialchars($data["nav_title"]);
  820. $data["title"] = htmlspecialchars($data["title"]);
  821. $data["external"] = htmlspecialchars($data["external"]);
  822. $data["meta_keywords"] = htmlspecialchars($data["meta_keywords"]);
  823. $data["meta_description"] = htmlspecialchars($data["meta_description"]);
  824. $parent = mysql_real_escape_string($data["parent"]);
  825. // JSON encode the changes and stick them in the database.
  826. unset($data["MAX_FILE_SIZE"]);
  827. unset($data["ptype"]);
  828. $data = mysql_real_escape_string(json_encode($data));
  829. sqlquery("INSERT INTO bigtree_pending_changes (`user`,`date`,`title`,`table`,`changes`,`tags_changes`,`type`,`module`,`pending_page_parent`) VALUES ('".$this->ID."',NOW(),'New Page Created','bigtree_pages','$data','$tags','NEW','','$parent')");
  830. $id = sqlid();
  831. // Audit trail
  832. $this->track("bigtree_pages","p$id","created-pending");
  833. return $id;
  834. }
  835. /*
  836. Function: createResource
  837. Creates a resource.
  838. Parameters:
  839. folder - The folder to place it in.
  840. file - The file path.
  841. name - The file name.
  842. type - The file type.
  843. is_image - Whether the resource is an image.
  844. height - The image height (if it's an image).
  845. width - The image width (if it's an image).
  846. thumbs - An array of thumbnails (if it's an image).
  847. list_thumb_margin - The margin for the list thumbnail (if it's an image).
  848. Returns:
  849. The new resource id.
  850. */
  851. function createResource($folder,$file,$name,$type,$is_image = "",$height = 0,$width = 0,$thumbs = array(),$list_thumb_margin = 0) {
  852. $folder = mysql_real_escape_string($folder);
  853. $file = mysql_real_escape_string($file);
  854. $name = mysql_real_escape_string(htmlspecialchars($name));
  855. $type = mysql_real_escape_string($type);
  856. $is_image = mysql_real_escape_string($is_image);
  857. $height = intval($height);
  858. $width = intval($width);
  859. $thumbs = mysql_real_escape_string(json_encode($thumbs));
  860. $list_thumb_margin = intval($list_thumb_margin);
  861. sqlquery("INSERT INTO bigtree_resources (`file`,`date`,`name`,`type`,`folder`,`is_image`,`height`,`width`,`thumbs`,`list_thumb_margin`) VALUES ('$file',NOW(),'$name','$type','$folder','$is_image','$height','$width','$thumbs','$list_thumb_margin')");
  862. return sqlid();
  863. }
  864. /*
  865. Function: createResourceFolder
  866. Creates a resource folder.
  867. Checks permissions.
  868. Paremeters:
  869. parent - The parent folder.
  870. name - The name of the new folder.
  871. Returns:
  872. The new folder id.
  873. */
  874. function createResourceFolder($parent,$name) {
  875. $perm = $this->getResourceFolderPermission($parent);
  876. if ($perm != "p") {
  877. die("You don't have permission to make a folder here.");
  878. }
  879. $parent = mysql_real_escape_string($parent);
  880. $name = mysql_real_escape_string(htmlspecialchars($name));
  881. sqlquery("INSERT INTO bigtree_resource_folders (`name`,`parent`) VALUES ('$name','$parent')");
  882. return sqlid();
  883. }
  884. /*
  885. Function: createSetting
  886. Creates a setting.
  887. Parameters:
  888. data - An array of settings information. Available fields: "id", "name", "description", "type", "locked", "module", "encrypted", "system"
  889. Returns:
  890. True if successful, false if a setting already exists with the ID given.
  891. */
  892. function createSetting($data) {
  893. // Avoid _SESSION hijacking.
  894. foreach ($data as $key => $val) {
  895. if (substr($key,0,1) != "_" && !is_array($val)) {
  896. $$key = mysql_real_escape_string(htmlspecialchars($val));
  897. }
  898. }
  899. // We don't want this encoded since it's a WYSIWYG field.
  900. $description = mysql_real_escape_string($data["description"]);
  901. // See if there's already a setting with this ID
  902. $r = sqlrows(sqlquery("SELECT id FROM bigtree_settings WHERE id = '$id'"));
  903. if ($r) {
  904. return false;
  905. }
  906. sqlquery("INSERT INTO bigtree_settings (`id`,`name`,`description`,`type`,`locked`,`encrypted`,`system`) VALUES ('$id','$name','$description','$type','$locked','$encrypted','$system')");
  907. // Audit trail.
  908. $this->track("bigtree_settings",$id,"created");
  909. return true;
  910. }
  911. /*
  912. Function: createTag
  913. Creates a new tag, or returns the id of an existing one.
  914. Parameters:
  915. tag - The tag.
  916. Returns:
  917. If the tag exists, returns the existing tag's id.
  918. Otherwise, returns the new tag id.
  919. */
  920. function createTag($tag) {
  921. global $cms;
  922. $tag = strtolower(html_entity_decode($tag));
  923. // Check if the tag exists already.
  924. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_tags WHERE tag = '".mysql_real_escape_string($tag)."'"));
  925. if (!$f) {
  926. $meta = metaphone($tag);
  927. $route = $cms->urlify($tag);
  928. $oroute = $route;
  929. $x = 2;
  930. while ($f = sqlfetch(sqlquery("SELECT * FROM bigtree_tags WHERE route = '$route'"))) {
  931. $route = $oroute."-".$x;
  932. $x++;
  933. }
  934. sqlquery("INSERT INTO bigtree_tags (`tag`,`metaphone`,`route`) VALUES ('".mysql_real_escape_string($tag)."','$meta','$route')");
  935. $id = sqlid();
  936. } else {
  937. $id = $f["id"];
  938. }
  939. return $id;
  940. }
  941. /*
  942. Function: createTemplate
  943. Creates a template and its default files/directories.
  944. Paremeters:
  945. id - Id for the template.
  946. name - Name
  947. description - Description
  948. routed - Basic ("") or Routed ("on")
  949. level - Access level (0 for everyone, 1 for administrators, 2 for developers)
  950. module - Related module id
  951. image - Image
  952. callouts_enabled - "on" for yes
  953. resources - An array of resources
  954. */
  955. function createTemplate($id,$name,$description,$routed,$level,$module,$image,$callouts_enabled,$resources) {
  956. // If we're creating a new file, let's populate it with some convenience things to show what resources are available.
  957. $file_contents = "<?\n /*\n Resources Available:\n";
  958. $types = $this->getCachedFieldTypes();
  959. $types = $types["template"];
  960. $clean_resources = array();
  961. foreach ($resources as $resource) {
  962. if ($resource["id"]) {
  963. $options = json_decode($resource["options"],true);
  964. foreach ($options as $key => $val) {
  965. if ($key != "title" && $key != "id" && $key != "type") {
  966. $resource[$key] = $val;
  967. }
  968. }
  969. $file_contents .= ' $'.$resource["id"].' = '.$resource["title"].' - '.$types[$resource["type"]]."\n";
  970. $resource["id"] = htmlspecialchars($resource["id"]);
  971. $resource["title"] = htmlspecialchars($resource["title"]);
  972. $resource["subtitle"] = htmlspecialchars($resource["subtitle"]);
  973. unset($resource["options"]);
  974. $clean_resources[] = $resource;
  975. }
  976. }
  977. $file_contents .= ' */
  978. ?>';
  979. if ($routed == "on") {
  980. if (!file_exists($GLOBALS["server_root"]."templates/routed/".$id)) {
  981. mkdir($GLOBALS["server_root"]."templates/routed/".$id);
  982. chmod($GLOBALS["server_root"]."templates/routed/".$id,0777);
  983. }
  984. if (!file_exists($GLOBALS["server_root"]."templates/routed/".$id."/default.php")) {
  985. file_put_contents($GLOBALS["server_root"]."templates/routed/".$id."/default.php",$file_contents);
  986. chmod($GLOBALS["server_root"]."templates/routed/".$id."/default.php",0777);
  987. }
  988. } else {
  989. if (!file_exists($GLOBALS["server_root"]."templates/basic/".$id.".php")) {
  990. file_put_contents($GLOBALS["server_root"]."templates/basic/".$id.".php",$file_contents);
  991. chmod($GLOBALS["server_root"]."templates/basic/".$id.".php",0777);
  992. }
  993. }
  994. $id = mysql_real_escape_string($id);
  995. $name = mysql_real_escape_string(htmlspecialchars($name));
  996. $description = mysql_real_escape_string(htmlspecialchars($description));
  997. $module = mysql_real_escape_string($module);
  998. $resources = mysql_real_escape_string(json_encode($clean_resources));
  999. $image = mysql_real_escape_string($image);
  1000. $level = mysql_real_escape_string($level);
  1001. $callouts_enabled = mysql_real_escape_string($callouts_enabled);
  1002. $routed = mysql_real_escape_string($routed);
  1003. sqlquery("INSERT INTO bigtree_templates (`id`,`name`,`module`,`resources`,`image`,`description`,`level`,`callouts_enabled`,`routed`) VALUES ('$id','$name','$module','$resources','$image','$description','$level','$callouts_enabled','$routed')");
  1004. }
  1005. /*
  1006. Function: createUser
  1007. Creates a user.
  1008. Checks for developer access.
  1009. Parameters:
  1010. data - An array of user data. ("email", "password", "name", "company", "level", "permissions")
  1011. Returns:
  1012. id of the newly created user or false if a user already exists with the provided email.
  1013. */
  1014. function createUser($data) {
  1015. global $config;
  1016. // Safely go through the post data
  1017. foreach ($data as $key => $val) {
  1018. if (substr($key,0,1) != "_" && !is_array($val)) {
  1019. $$key = mysql_real_escape_string($val);
  1020. }
  1021. }
  1022. // See if the user already exists
  1023. $r = sqlrows(sqlquery("SELECT * FROM bigtree_users WHERE email = '$email'"));
  1024. if ($r > 0) {
  1025. return false;
  1026. }
  1027. $permissions = mysql_real_escape_string(json_encode($data["permissions"]));
  1028. // If the user is trying to create a developer user and they're not a developer, then… no.
  1029. if ($level > $this->Level) {
  1030. $level = $this->Level;
  1031. }
  1032. // Hash the password.
  1033. $phpass = new PasswordHash($config["password_depth"], TRUE);
  1034. $password = mysql_real_escape_string($phpass->HashPassword($data["password"]));
  1035. sqlquery("INSERT INTO bigtree_users (`email`,`password`,`name`,`company`,`level`,`permissions`) VALUES ('$email','$password','$name','$company','$level','$permissions')");
  1036. $id = sqlid();
  1037. // Audit trail.
  1038. $this->track("bigtree_users",$id,"created");
  1039. return $id;
  1040. }
  1041. /*
  1042. Function: deleteCallout
  1043. Deletes a callout and removes its file.
  1044. Parameters:
  1045. id - The id of the callout.
  1046. */
  1047. function deleteCallout($id) {
  1048. $id = mysql_real_escape_string($id);
  1049. sqlquery("DELETE FROM bigtree_callouts WHERE id = '$id'");
  1050. unlink($GLOBALS["server_root"]."templates/callouts/$id.php");
  1051. }
  1052. /*
  1053. Function: deleteFeed
  1054. Deletes a feed.
  1055. Parameters:
  1056. id - The id of the feed.
  1057. */
  1058. function deleteFeed($id) {
  1059. $id = mysql_real_escape_string($id);
  1060. sqlquery("DELETE FROM bigtree_feeds WHERE id = '$id'");
  1061. }
  1062. /*
  1063. Function: deleteFieldType
  1064. Deletes a field type and erases its files.
  1065. Parameters:
  1066. id - The id of the field type.
  1067. */
  1068. function deleteFieldType($id) {
  1069. unlink($GLOBALS["server_root"]."custom/admin/form-field-types/draw/$id.php");
  1070. unlink($GLOBALS["server_root"]."custom/admin/form-field-types/process/$id.php");
  1071. sqlquery("DELETE FROM bigtree_field_types WHERE id = '".mysql_real_escape_string($id)."'");
  1072. }
  1073. /*
  1074. Function: deleteModule
  1075. Deletes a module.
  1076. Parameters:
  1077. id - The id of the module.
  1078. */
  1079. function deleteModule($id) {
  1080. $id = mysql_real_escape_string($id);
  1081. // Get info and delete the class.
  1082. $module = $this->getModule($id);
  1083. unlink($GLOBALS["server_root"]."custom/inc/modules/".$module["route"].".php");
  1084. // Delete all the related auto module actions
  1085. $actions = $this->getModuleActions($id);
  1086. foreach ($actions as $action) {
  1087. if ($action["form"]) {
  1088. sqlquery("DELETE FROM bigtree_module_forms WHERE id = '".$action["form"]."'");
  1089. }
  1090. if ($action["view"]) {
  1091. sqlquery("DELETE FROM bigtree_module_views WHERE id = '".$action["view"]."'");
  1092. }
  1093. }
  1094. // Delete actions
  1095. sqlquery("DELETE FROM bigtree_module_actions WHERE module = '$id'");
  1096. // Delete the module
  1097. sqlquery("DELETE FROM bigtree_modules WHERE id = '$id'");
  1098. }
  1099. /*
  1100. Function: deleteModuleAction
  1101. Deletes a module action.
  1102. Also deletes the related form or view if no other action is using it.
  1103. Parameters:
  1104. id - The id of the action to delete.
  1105. */
  1106. function deleteModuleAction($id) {
  1107. $id = mysql_real_escape_string($id);
  1108. $a = $this->getModuleAction($id);
  1109. if ($a["form"]) {
  1110. // Only delete the auto-ness if it's the only one using it.
  1111. if (sqlrows(sqlquery("SELECT * FROM bigtree_module_actions WHERE form = '".$a["form"]."'")) == 1) {
  1112. sqlquery("DELETE FROM bigtree_module_forms WHERE id = '".$a["form"]."'");
  1113. }
  1114. }
  1115. if ($a["view"]) {
  1116. // Only delete the auto-ness if it's the only one using it.
  1117. if (sqlrows(sqlquery("SELECT * FROM bigtree_module_actions WHERE view = '".$a["view"]."'")) == 1) {
  1118. sqlquery("DELETE FROM bigtree_module_views WHERE id = '".$a["view"]."'");
  1119. }
  1120. }
  1121. sqlquery("DELETE FROM bigtree_module_actions WHERE id = '$id'");
  1122. }
  1123. /*
  1124. Function: deleteModuleForm
  1125. Deletes a module form and its related actions.
  1126. Parameters:
  1127. id - The id of the module form.
  1128. */
  1129. function deleteModuleForm($id) {
  1130. $id = mysql_real_escape_string($id);
  1131. sqlquery("DELETE FROM bigtree_module_forms WHERE id = '$id'");
  1132. sqlquery("DELETE FROM bigtree_module_actions WHERE form = '$id'");
  1133. }
  1134. /*
  1135. Function: deleteModuleGroup
  1136. Deletes a module group. Sets modules in the group to Misc.
  1137. Parameters:
  1138. id - The id of the module group.
  1139. */
  1140. function deleteModuleGroup($id) {
  1141. $id = mysql_real_escape_string($id);
  1142. sqlquery("DELETE FROM bigtree_module_groups WHERE id = '$id'");
  1143. sqlquery("UPDATE bigtree_modules SET `group` = '0' WHERE `group` = '$id'");
  1144. }
  1145. /*
  1146. Function: deleteModuleView
  1147. Deletes a module view and its related actions.
  1148. Parameters:
  1149. id - The id of the module view.
  1150. */
  1151. function deleteModuleView($id) {
  1152. $id = mysql_real_escape_string($id);
  1153. sqlquery("DELETE FROM bigtree_module_views WHERE id = '$id'");
  1154. sqlquery("DELETE FROM bigtree_module_actions WHERE view = '$id'");
  1155. }
  1156. /*
  1157. Function: deletePage
  1158. Deletes a page or a pending page.
  1159. Checks permissions.
  1160. Parameters:
  1161. page - A page id or a pending page id prefixed with a "p"
  1162. Returns:
  1163. true if successful. Stops page execution if permission issues occur.
  1164. */
  1165. function deletePage($page) {
  1166. global $cms;
  1167. $page = mysql_real_escape_string($page);
  1168. $r = $this->getPageAccessLevel($page);
  1169. if ($r == "p" && $this->canModifyChildren($cms->getPage($page))) {
  1170. // If the page isn't numeric it's most likely prefixed by the "p" so it's pending.
  1171. if (!is_numeric($page)) {
  1172. sqlquery("DELETE FROM bigtree_pending_changes WHERE id = '".mysql_real_escape_string(substr($page,1))."'");
  1173. $this->growl("Pages","Deleted Page");
  1174. $this->track("bigtree_pages","p$page","deleted-pending");
  1175. } else {
  1176. sqlquery("DELETE FROM bigtree_pages WHERE id = '$page'");
  1177. // Delete the children as well.
  1178. $this->deletePageChildren($page);
  1179. $this->growl("Pages","Deleted Page");
  1180. $this->track("bigtree_pages",$page,"deleted");
  1181. }
  1182. return true;
  1183. }
  1184. $this->stop("You do not have permission to delete this page.");
  1185. }
  1186. /*
  1187. Function: deletePageChildren
  1188. Deletes the children of a page and recurses downward.
  1189. Does not check permissions.
  1190. Parameters:
  1191. id - The parent id to delete children for.
  1192. */
  1193. function deletePageChildren($id) {
  1194. $q = sqlquery("SELECT * FROM bigtree_pages WHERE parent = '$id'");
  1195. while ($f = sqlfetch($q)) {
  1196. $this->deletePageChildren($f["id"]);
  1197. }
  1198. sqlquery("DELETE FROM bigtree_pages WHERE parent = '$id'");
  1199. $this->track("bigtree_pages",$id,"deleted");
  1200. }
  1201. /*
  1202. Function: deletePageDraft
  1203. Deletes a page draft.
  1204. Checks permissions.
  1205. Parameters:
  1206. id - The page id to delete the draft for.
  1207. */
  1208. function deletePageDraft($id) {
  1209. $id = mysql_real_escape_string($id);
  1210. // Get the version, check if the user has access to the page the version refers to.
  1211. $access = $this->getPageAccessLevel($id);
  1212. if ($access != "p") {
  1213. $this->stop("You must be a publisher to manage revisions.");
  1214. }
  1215. // Delete draft copy
  1216. sqlquery("DELETE FROM bigtree_pending_changes WHERE `table` = 'bigtree_pages' AND `item_id` = '$id'");
  1217. }
  1218. /*
  1219. Function: deletePageRevision
  1220. Deletes a page revision.
  1221. Checks permissions.
  1222. Parameters:
  1223. id - The page version id.
  1224. */
  1225. function deletePageRevision($id) {
  1226. // Get the version, check if the user has access to the page the version refers to.
  1227. $revision = $this->getPageRevision($id);
  1228. $access = $this->getPageAccessLevel($revision["page"]);
  1229. if ($access != "p") {
  1230. $this->stop("You must be a publisher to manage revisions.");
  1231. }
  1232. // Delete the revision
  1233. sqlquery("DELETE FROM bigtree_page_revisions WHERE id = '".$revision["id"]."'");
  1234. }
  1235. /*
  1236. Function: deletePendingChange
  1237. Deletes a pending change.
  1238. Parameters:
  1239. id - The id of the change.
  1240. */
  1241. function deletePendingChange($id) {
  1242. $id = mysql_real_escape_string($id);
  1243. sqlquery("DELETE FROM bigtree_pending_changes WHERE id = '$id'");
  1244. }
  1245. /*
  1246. Function: deleteSetting
  1247. Deletes a setting.
  1248. Parameters:
  1249. id - The id of the setting.
  1250. */
  1251. function deleteSetting($id) {
  1252. $id = mysql_real_escape_string($id);
  1253. sqlquery("DELETE FROM bigtree_settings WHERE id = '$id'");
  1254. }
  1255. /*
  1256. Function: deleteTemplate
  1257. Deletes a template.
  1258. Parameters:
  1259. id - The id of the template.
  1260. */
  1261. function deleteTemplate($id) {
  1262. $id = mysql_real_escape_string($id);
  1263. sqlquery("DELETE FROM bigtree_templates WHERE id = '$id'");
  1264. }
  1265. /*
  1266. Function: deleteUser
  1267. Deletes a user.
  1268. Checks for developer access.
  1269. Parameters:
  1270. id - The user id to delete.
  1271. Returns:
  1272. true if successful. false if the logged in user does not have permission to delete the user.
  1273. */
  1274. function deleteUser($id) {
  1275. $id = mysql_real_escape_string($id);
  1276. // If this person has higher access levels than the person trying to update them, fail.
  1277. $current = $this->getUser($id);
  1278. if ($current["level"] > $this->Level) {
  1279. return false;
  1280. }
  1281. sqlquery("DELETE FROM bigtree_users WHERE id = '$id'");
  1282. // Audit trail
  1283. $this->track("bigtree_users",$id,"deleted");
  1284. return true;
  1285. }
  1286. /*
  1287. Function: doesModuleEditActionExist
  1288. Determines whether there is already an edit action for a module.
  1289. Parameters:
  1290. module - The module id to check.
  1291. Returns:
  1292. 1 or 0, for true or false.
  1293. */
  1294. function doesModuleEditActionExist($module) {
  1295. return sqlrows(sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '".mysql_real_escape_string($module)."' AND route = 'edit'"));
  1296. }
  1297. /*
  1298. Function: doesModuleLandingActionExist
  1299. Determines whether there is already a landing action for a module.
  1300. Parameters:
  1301. module - The module id to check.
  1302. Returns:
  1303. 1 or 0, for true or false.
  1304. */
  1305. function doesModuleLandingActionExist($module) {
  1306. return sqlrows(sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '".mysql_real_escape_string($module)."' AND route = ''"));
  1307. }
  1308. /*
  1309. Function: emailDailyDigest
  1310. Sends out a daily digest email to all who have subscribed.
  1311. */
  1312. function emailDailyDigest() {
  1313. $qusers = sqlquery("SELECT * FROM bigtree_users where daily_digest = 'on'");
  1314. while ($user = sqlfetch($qusers)) {
  1315. $changes = $this->getPendingChanges($user["id"]);
  1316. $alerts = $this->getContentAlerts($user["id"]);
  1317. // Start building the email
  1318. $body = "BigTree Daily Digest\n";
  1319. $body .= "====================\n";
  1320. $body .= $GLOBALS["admin_root"]."\n\n";
  1321. if (is_array($alerts) && count($alerts)) {
  1322. $body .= "Content Age Alerts\n";
  1323. $body .= "------------------\n\n";
  1324. foreach ($alerts as $alert) {
  1325. $body .= $alert["nav_title"]." - ".$alert["current_age"]." Days Old\n";
  1326. $body .= $GLOBALS["www_root"].$alert["path"]."/\n";
  1327. $body .= $GLOBALS["admin_root"]."pages/edit/".$alert["id"]."/\n\n";
  1328. }
  1329. }
  1330. if (count($changes)) {
  1331. $body .= "Pending Changes\n";
  1332. $body .= "---------------\n\n";
  1333. foreach ($changes as $change) {
  1334. if ($change["title"]) {
  1335. $body .= $change["title"];
  1336. } else {
  1337. $body .= $change["mod"]["name"]." - ";
  1338. if ($change["type"] == "NEW") {
  1339. $body .= "Addition";
  1340. } elseif ($change["type"] == "EDIT") {
  1341. $body .= "Edit";
  1342. }
  1343. }
  1344. $body .= "\n".$change["user"]["name"]." has submitted this change request.\n";
  1345. $body .= $this->getChangeEditLink($change)."\n\n";
  1346. }
  1347. }
  1348. if (count($alerts) || count($changes)) {
  1349. mail($user["email"],"BigTree Daily Digest",$body,"From: BigTree Digest <mailer@bigtreecms.com>");
  1350. }
  1351. }
  1352. }
  1353. /*
  1354. Function: forgotPassword
  1355. Creates a new password change hash and sends an email to the user.
  1356. Parameters:
  1357. email - The user's email address
  1358. Returns:
  1359. Redirects if the email address was found, returns false if the user doesn't exist.
  1360. See Also:
  1361. <changePassword>
  1362. */
  1363. function forgotPassword($email) {
  1364. $email = mysql_real_escape_string($email);
  1365. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE email = '$email'"));
  1366. if (!$f) {
  1367. return false;
  1368. }
  1369. $hash = mysql_real_escape_string(md5(md5(md5(uniqid("bigtree-hash".microtime(true))))));
  1370. sqlquery("UPDATE bigtree_users SET change_password_hash = '$hash' WHERE id = '".$f["id"]."'");
  1371. mail($email,"Reset Your Password","A user with the IP address ".$_SERVER["REMOTE_ADDR"]." has requested to reset your password.\n\nIf this was you, please click the link below:\n".$GLOBALS["admin_root"]."login/reset-password/$hash/","From: no-reply@bigtreecms.com");
  1372. header("Location: ".$GLOBALS["admin_root"]."login/forgot-success/");
  1373. die();
  1374. }
  1375. /*
  1376. Function: get404Total
  1377. Get the total number of 404s of a certain type.
  1378. Parameters:
  1379. type - The type to retrieve the count for (301, ignored, 404)
  1380. Returns:
  1381. The number of 404s in the table of the given type.
  1382. */
  1383. function get404Total($type) {
  1384. if ($type == "404") {
  1385. $total = sqlfetch(sqlquery("SELECT COUNT(id) AS `total` FROM bigtree_404s WHERE ignored = '' AND redirect_url = ''"));
  1386. } elseif ($type == "301") {
  1387. $total = sqlfetch(sqlquery("SELECT COUNT(id) AS `total` FROM bigtree_404s WHERE ignored = '' AND redirect_url != ''"));
  1388. } elseif ($type == "ignored") {
  1389. $total = sqlfetch(sqlquery("SELECT COUNT(id) AS `total` FROM bigtree_404s WHERE ignored = 'on'"));
  1390. }
  1391. return $total["total"];
  1392. }
  1393. /*
  1394. Function: getAccessGroups
  1395. Returns a list of all groups the logged in user has access to in a module.
  1396. Parameters:
  1397. module - A module id or module entry.
  1398. Returns:
  1399. An array of groups if a user has limited access to a module or "true" if the user has access to all groups.
  1400. */
  1401. function getAccessGroups($module) {
  1402. if ($this->Level > 0) {
  1403. return true;
  1404. }
  1405. if (is_array($module)) {
  1406. $module = $module["id"];
  1407. }
  1408. if ($this->Permissions["module"][$module] && $this->Permissions["module"][$module] != "n") {
  1409. return true;
  1410. }
  1411. $groups = array();
  1412. if (is_array($this->Permissions["module_gbp"][$module])) {
  1413. foreach ($this->Permissions["module_gbp"][$module] as $group => $permission) {
  1414. if ($permission && $permission != "n") {
  1415. $groups[] = $group;
  1416. }
  1417. }
  1418. }
  1419. return $groups;
  1420. }
  1421. /*
  1422. Function: getAccessLevel
  1423. Returns the permission level for a given module and item.
  1424. Parameters:
  1425. module - The module id or entry to check access for.
  1426. item - (optional) The item of the module to check access for.
  1427. table - (optional) The group based table.
  1428. Returns:
  1429. The permission level for the given item or module (if item was not passed).
  1430. See Also:
  1431. <getCachedAccessLevel>
  1432. */
  1433. function getAccessLevel($module,$item = array(),$table = "") {
  1434. if ($this->Level > 0) {
  1435. return "p";
  1436. }
  1437. $id = is_array($module) ? $module["id"] : $module;
  1438. $perm = $this->Permissions["module"][$id];
  1439. // If group based permissions aren't on or we're a publisher of this module it's an easy solution… or if we're not even using the table.
  1440. if (!$item || !$module["gbp"]["enabled"] || $perm == "p" || $table != $module["gbp"]["table"]) {
  1441. return $perm;
  1442. }
  1443. if (is_array($this->Permissions["module_gbp"][$id])) {
  1444. $gv = $item[$module["gbp"]["group_field"]];
  1445. $gp = $this->Permissions["module_gbp"][$id][$gv];
  1446. if ($gp != "n") {
  1447. return $gp;
  1448. }
  1449. }
  1450. return $perm;
  1451. }
  1452. /*
  1453. Function: getActionClass
  1454. Returns the button class for the given action and item.
  1455. Parameters:
  1456. action - The action for the item (edit, feature, approve, etc)
  1457. item - The entry to check the action for.
  1458. Returns:
  1459. Class name for the <a> tag.
  1460. For example, if the item is already featured, this returns "icon_featured icon_featured_on" for the "feature" action.
  1461. If the item isn't already featured, it would simply return "icon_featured" for the "feature" action.
  1462. */
  1463. function getActionClass($action,$item) {
  1464. $class = "";
  1465. if ($item["bigtree_pending"] && $action != "edit" && $action != "delete") {
  1466. return "icon_disabled";
  1467. }
  1468. if ($action == "feature") {
  1469. $class = "icon_feature";
  1470. if ($item["featured"]) {
  1471. $class .= " icon_feature_on";
  1472. }
  1473. }
  1474. if ($action == "edit") {
  1475. $class = "icon_edit";
  1476. }
  1477. if ($action == "delete") {
  1478. $class = "icon_delete";
  1479. }
  1480. if ($action == "approve") {
  1481. $class = "icon_approve";
  1482. if ($item["approved"]) {
  1483. $class .= " icon_approve_on";
  1484. }
  1485. }
  1486. if ($action == "archive") {
  1487. $class = "icon_archive";
  1488. if ($item["archived"]) {
  1489. $class .= " icon_archive_on";
  1490. }
  1491. }
  1492. if ($action == "preview") {
  1493. $class = "icon_preview";
  1494. }
  1495. return $class;
  1496. }
  1497. /*
  1498. Function: getArchivedNavigationByParent
  1499. Returns an alphabetic list of navigation that is archived under the given parent.
  1500. Parameters:
  1501. parent - The ID of the parent page
  1502. Returns:
  1503. An array of page entries.
  1504. */
  1505. function getArchivedNavigationByParent($parent) {
  1506. $nav = array();
  1507. $q = sqlquery("SELECT id,nav_title as title,parent,external,new_window,template,publish_at,expire_at,path FROM bigtree_pages WHERE parent = '$parent' AND archived = 'on' ORDER BY nav_title asc");
  1508. while ($nav_item = sqlfetch($q)) {
  1509. $nav_item["external"] = str_replace("{wwwroot}",$GLOBALS["www_root"],$nav_item["external"]);
  1510. $nav[] = $nav_item;
  1511. }
  1512. return $nav;
  1513. }
  1514. /*
  1515. Function: getAutoModuleActions
  1516. Return a list of module forms and views.
  1517. Used by the API for reconstructing forms and views.
  1518. Parameters:
  1519. module - The module id to pull forms/views for.
  1520. Returns:
  1521. An array of module actions with "form" and "view" columns replaced with form and view data.
  1522. See Also:
  1523. <BigTreeAutoModule.getForm>
  1524. <BigTreeAutoModule.getView>
  1525. */
  1526. function getAutoModuleActions($module) {
  1527. $items = array();
  1528. $id = mysql_real_escape_string($module);
  1529. $q = sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '$id' AND (form != 0 OR view != 0) AND in_nav = 'on' ORDER BY position DESC, id ASC");
  1530. while ($f = sqlfetch($q)) {
  1531. if ($f["form"]) {
  1532. $f["form"] = BigTreeAutoModule::getForm($f["form"]);
  1533. $f["type"] = "form";
  1534. } elseif ($f["view"]) {
  1535. $f["view"] = BigTreeAutoModule::getView($f["view"]);
  1536. $f["type"] = "view";
  1537. }
  1538. $items[] = $f;
  1539. }
  1540. return $items;
  1541. }
  1542. /*
  1543. Function: getBasicTemplates
  1544. Returns a list of non-routed templates ordered by position.
  1545. Returns:
  1546. An array of template entries.
  1547. */
  1548. function getBasicTemplates() {
  1549. $q = sqlquery("SELECT * FROM bigtree_templates WHERE level <= '".$this->Level."' ORDER BY position DESC, id ASC");
  1550. $items = array();
  1551. while ($f = sqlfetch($q)) {
  1552. if (!$f["routed"]) {
  1553. $items[] = $f;
  1554. }
  1555. }
  1556. return $items;
  1557. }
  1558. /*
  1559. Function: getCachedAccessLevel
  1560. Returns the permission level for a given module and cached view entry.
  1561. Parameters:
  1562. module - The module id or entry to check access for.
  1563. item - (optional) The item of the module to check access for.
  1564. table - (optional) The group based table.
  1565. Returns:
  1566. The permission level for the given item or module (if item was not passed).
  1567. See Also:
  1568. <getAccessLevel>
  1569. */
  1570. // Since cached items don't use their normal columns...
  1571. function getCachedAccessLevel($module,$item = array(),$table = "") {
  1572. if ($this->Level > 0) {
  1573. return "p";
  1574. }
  1575. $id = is_array($module) ? $module["id"] : $module;
  1576. $perm = $this->Permissions["module"][$id];
  1577. // If group based permissions aren't on or we're a publisher of this module it's an easy solution… or if we're not even using the table.
  1578. if (!$item || !$module["gbp"]["enabled"] || $perm == "p" || $table != $module["gbp"]["table"]) {
  1579. return $perm;
  1580. }
  1581. if (is_array($this->Permissions["module_gbp"][$id])) {
  1582. $gv = $item["gbp_field"];
  1583. $gp = $this->Permissions["module_gbp"][$id][$gv];
  1584. if ($gp != "n") {
  1585. return $gp;
  1586. }
  1587. }
  1588. return $perm;
  1589. }
  1590. /*
  1591. Function: getCachedFieldTypes
  1592. Caches available field types and returns them.
  1593. Returns:
  1594. Array of three arrays of field types (template, module, and callout).
  1595. */
  1596. function getCachedFieldTypes() {
  1597. // Used cached values if available, otherwise query the DB
  1598. if (file_exists($GLOBALS["server_root"]."cache/form-field-types.btc")) {
  1599. $types = json_decode(file_get_contents($GLOBALS["server_root"]."cache/form-field-types.btc"),true);
  1600. } else {
  1601. $types["module"] = array(
  1602. "text" => "Text",
  1603. "textarea" => "Text Area",
  1604. "html" => "HTML Area",
  1605. "upload" => "Upload",
  1606. "list" => "List",
  1607. "checkbox" => "Checkbox",
  1608. "date" => "Date Picker",
  1609. "time" => "Time Picker",
  1610. "photo-gallery" => "Photo Gallery",
  1611. "array" => "Array of Items",
  1612. "route" => "Generated Route",
  1613. "custom" => "Custom Function"
  1614. );
  1615. $types["template"] = array(
  1616. "text" => "Text",
  1617. "textarea" => "Text Area",
  1618. "html" => "HTML Area",
  1619. "upload" => "Upload",
  1620. "list" => "List",
  1621. "checkbox" => "Checkbox",
  1622. "date" => "Date Picker",
  1623. "time" => "Time Picker",
  1624. "photo-gallery" => "Photo Gallery",
  1625. "array" => "Array of Items",
  1626. "custom" => "Custom Function"
  1627. );
  1628. $types["callout"] = array(
  1629. "text" => "Text",
  1630. "textarea" => "Text Area",
  1631. "html" => "HTML Area",
  1632. "upload" => "Upload",
  1633. "list" => "List",
  1634. "checkbox" => "Checkbox",
  1635. "date" => "Date Picker",
  1636. "time" => "Time Picker",
  1637. "array" => "Array of Items",
  1638. "custom" => "Custom Function"
  1639. );
  1640. $q = sqlquery("SELECT * FROM bigtree_field_types ORDER BY name");
  1641. while ($f = sqlfetch($q)) {
  1642. if ($f["pages"]) {
  1643. $types["template"][$f["id"]] = $f["name"];
  1644. }
  1645. if ($f["modules"]) {
  1646. $types["module"][$f["id"]] = $f["name"];
  1647. }
  1648. if ($f["callouts"]) {
  1649. $types["callout"][$f["id"]] = $f["name"];
  1650. }
  1651. }
  1652. file_put_contents($GLOBALS["server_root"]."cache/form-field-types.btc",json_encode($types));
  1653. }
  1654. return $types;
  1655. }
  1656. /*
  1657. Function: getCallout
  1658. Returns a callout entry.
  1659. Parameters:
  1660. id - The id of the callout.
  1661. Returns:
  1662. A callout entry from bigtree_callouts with resources decoded.
  1663. */
  1664. function getCallout($id) {
  1665. $id = mysql_real_escape_string($id);
  1666. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_callouts WHERE id = '$id'"));
  1667. $item["resources"] = json_decode($item["resources"],true);
  1668. return $item;
  1669. }
  1670. /*
  1671. Function: getCallouts
  1672. Returns a list of callouts.
  1673. Parameters:
  1674. sort - The order to return the callouts. Defaults to positioned.
  1675. Returns:
  1676. An array of callout entries from bigtree_callouts.
  1677. */
  1678. function getCallouts($sort = "position DESC, id ASC") {
  1679. $callouts = array();
  1680. $q = sqlquery("SELECT * FROM bigtree_callouts ORDER BY $sort");
  1681. while ($f = sqlfetch($q)) {
  1682. $callouts[] = $f;
  1683. }
  1684. return $callouts;
  1685. }
  1686. /*
  1687. Function: getChange
  1688. Get a pending change.
  1689. Parameters:
  1690. id - The id of the pending change.
  1691. Returns:
  1692. A pending change entry from the bigtree_pending_changes table.
  1693. */
  1694. function getChange($id) {
  1695. return sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE id = '$id'"));
  1696. }
  1697. /*
  1698. Function: getChangeEditLink
  1699. Returns a link to where the item involved in the pending change can be edited.
  1700. Parameters:
  1701. change - The ID of the change or the change array from the database.
  1702. Returns:
  1703. A string containing a link to the admin.
  1704. */
  1705. function getChangeEditLink($change) {
  1706. if (!is_array($change)) {
  1707. $change = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE id = '$change'"));
  1708. }
  1709. if ($change["table"] == "bigtree_pages" && $change["item_id"]) {
  1710. return $GLOBALS["admin_root"]."pages/edit/".$change["item_id"]."/";
  1711. }
  1712. if ($change["table"] == "bigtree_pages") {
  1713. return $GLOBALS["admin_root"]."pages/edit/p".$change["id"]."/";
  1714. }
  1715. $modid = $change["module"];
  1716. $module = sqlfetch(sqlquery("SELECT * FROM bigtree_modules WHERE id = '$modid'"));
  1717. $form = sqlfetch(sqlquery("SELECT * FROM bigtree_module_forms WHERE `table` = '".$change["table"]."'"));
  1718. $action = sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE `form` = '".$form["id"]."' AND in_nav = ''"));
  1719. if (!$change["item_id"]) {
  1720. $change["item_id"] = "p".$change["id"];
  1721. }
  1722. if ($action) {
  1723. return $GLOBALS["admin_root"].$module["route"]."/".$action["route"]."/".$change["item_id"]."/";
  1724. } else {
  1725. return $GLOBALS["admin_root"].$module["route"]."/edit/".$change["item_id"]."/";
  1726. }
  1727. }
  1728. /*
  1729. Function: getContentAlerts
  1730. Gets a list of pages with content older than their Max Content Age that a user follows.
  1731. Parameters:
  1732. user - The user id to pull alerts for or a user entry.
  1733. Returns:
  1734. An array of arrays containing a page title, path, and id.
  1735. */
  1736. function getContentAlerts($user) {
  1737. if (is_array($user)) {
  1738. $user = $this->getUser($user["id"]);
  1739. } else {
  1740. $user = $this->getUser($user);
  1741. }
  1742. if (!is_array($user["alerts"])) {
  1743. return false;
  1744. }
  1745. $alerts = array();
  1746. // We're going to generate a list of pages the user cares about first to get their paths.
  1747. $where = array();
  1748. foreach ($user["alerts"] as $alert => $status) {
  1749. $where[] = "id = '".mysql_real_escape_string($alert)."'";
  1750. }
  1751. if (!count($where)) {
  1752. return false;
  1753. }
  1754. // If we care about the whole tree, skip the madness.
  1755. if ($alerts[0] == "on") {
  1756. $q = sqlquery("SELECT nav_title,id,path,updated_at,DATEDIFF('".date("Y-m-d")."',updated_at) AS current_age FROM bigtree_pages WHERE max_age > 0 AND DATEDIFF('".date("Y-m-d")."',updated_at) > max_age ORDER BY current_age DESC");
  1757. } else {
  1758. $paths = array();
  1759. $q = sqlquery("SELECT path FROM bigtree_pages WHERE ".implode(" OR ",$where));
  1760. while ($f = sqlfetch($q)) {
  1761. $paths[] = "path = '".mysql_real_escape_string($f["path"])."' OR path LIKE '".mysql_real_escape_string($f["path"])."/%'";
  1762. }
  1763. // Find all the pages that are old that contain our paths
  1764. $q = sqlquery("SELECT nav_title,id,path,updated_at,DATEDIFF('".date("Y-m-d")."',updated_at) AS current_age FROM bigtree_pages WHERE max_age > 0 AND (".implode(" OR ",$paths).") AND DATEDIFF('".date("Y-m-d")."',updated_at) > max_age ORDER BY current_age DESC");
  1765. }
  1766. while ($f = sqlfetch($q)) {
  1767. $alerts[] = $f;
  1768. }
  1769. return $alerts;
  1770. }
  1771. /*
  1772. Function: getFeeds
  1773. Returns a list of feeds.
  1774. Parameters:
  1775. sort - The sort direction, defaults to name.
  1776. Returns:
  1777. An array of feed elements from bigtree_feeds sorted by name.
  1778. */
  1779. function getFeeds($sort = "name ASC") {
  1780. $feeds = array();
  1781. $q = sqlquery("SELECT * FROM bigtree_feeds ORDER BY $sort");
  1782. while ($f = sqlfetch($q)) {
  1783. $feeds[] = $f;
  1784. }
  1785. return $feeds;
  1786. }
  1787. /*
  1788. Function: getFieldType
  1789. Returns a field type.
  1790. Parameters:
  1791. id - The id of the file type.
  1792. Returns:
  1793. A field type entry with the "files" column decoded.
  1794. */
  1795. function getFieldType($id) {
  1796. $id = mysql_real_escape_string($id);
  1797. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_field_types WHERE id = '$id'"));
  1798. if (!$item) {
  1799. return false;
  1800. }
  1801. return $item;
  1802. }
  1803. /*
  1804. Function: getFieldTypes
  1805. Returns a list of field types.
  1806. Parameters:
  1807. sort - The sort directon, defaults to name ASC.
  1808. Returns:
  1809. An array of entries from bigtree_field_types.
  1810. */
  1811. function getFieldTypes($sort = "name ASC") {
  1812. $types = array();
  1813. $q = sqlquery("SELECT * FROM bigtree_field_types ORDER BY $sort");
  1814. while ($f = sqlfetch($q)) {
  1815. $types[] = $f;
  1816. }
  1817. return $types;
  1818. }
  1819. /*
  1820. Function: getFullNavigationPath
  1821. Calculates the full navigation path for a given page ID.
  1822. Parameters:
  1823. id - The page ID to calculate the navigation path for.
  1824. Returns:
  1825. The navigation path (normally found in the "path" column in bigtree_pages).
  1826. */
  1827. function getFullNavigationPath($id, $path = array()) {
  1828. global $cms;
  1829. // We can change $GLOBALS["root_page"] to drive multiple sites from different branches of the Pages tree.
  1830. $root_page = isset($GLOBALS["root_page"]) ? $_GLOBALS["root_page"] : 0;
  1831. $f = sqlfetch(sqlquery("SELECT route,id,parent FROM bigtree_pages WHERE id = '$id'"));
  1832. $path[] = $cms->urlify($f["route"]);
  1833. if ($f["parent"] != $root_page && $f["parent"] != 0) {
  1834. return $this->getFullNavigationPath($f["parent"],$path);
  1835. }
  1836. $path = implode("/",array_reverse($path));
  1837. return $path;
  1838. }
  1839. /*
  1840. Function: getHiddenNavigationByParent
  1841. Returns an alphabetic list of navigation that is hidden under the given parent.
  1842. Parameters:
  1843. parent - The ID of the parent page
  1844. Returns:
  1845. An array of page entries.
  1846. */
  1847. function getHiddenNavigationByParent($parent) {
  1848. $nav = array();
  1849. $q = sqlquery("SELECT id,nav_title as title,parent,external,new_window,template,publish_at,expire_at,path FROM bigtree_pages WHERE parent = '$parent' AND in_nav = '' AND archived != 'on' ORDER BY nav_title asc");
  1850. while ($nav_item = sqlfetch($q)) {
  1851. $nav_item["external"] = str_replace("{wwwroot}",$GLOBALS["www_root"],$nav_item["external"]);
  1852. $nav[] = $nav_item;
  1853. }
  1854. return $nav;
  1855. }
  1856. /*
  1857. Function: getMessages
  1858. Returns all a user's messages.
  1859. Returns:
  1860. An array containing "sent", "read", and "unread" keys that contain an array of messages each.
  1861. */
  1862. function getMessages() {
  1863. $sent = array();
  1864. $read = array();
  1865. $unread = array();
  1866. $q = sqlquery("SELECT bigtree_messages.*, bigtree_users.name AS sender_name FROM bigtree_messages JOIN bigtree_users ON bigtree_messages.sender = bigtree_users.id WHERE sender = '".$this->ID."' OR recipients LIKE '%|".$this->ID."|%' ORDER BY date DESC");
  1867. while ($f = sqlfetch($q)) {
  1868. // If we're the sender put it in the sent array.
  1869. if ($f["sender"] == $this->ID) {
  1870. $sent[] = $f;
  1871. } else {
  1872. // If we've been marked read, put it in the read array.
  1873. if ($f["read_by"] && strpos("|".$this->ID."|",$f["read_by"]) !== false) {
  1874. $read[] = $f;
  1875. } else {
  1876. $unread[] = $f;
  1877. }
  1878. }
  1879. }
  1880. return array("sent" => $sent, "read" => $read, "unread" => $unread);
  1881. }
  1882. /*
  1883. Function: getMessage
  1884. Returns a message from message center.
  1885. Paramters:
  1886. id - The id of the message.
  1887. Returns:
  1888. An entry from bigtree_messages.
  1889. */
  1890. function getMessage($id) {
  1891. $message = sqlfetch(sqlquery("SELECT * FROM bigtree_messages WHERE id = '".mysql_real_escape_string($id)."'"));
  1892. if ($message["sender"] != $this->ID && strpos("|".$this->ID."|",$message["recipients"]) === false) {
  1893. $this->stop("This message was not sent by you, or to you.");
  1894. }
  1895. return $message;
  1896. }
  1897. /*
  1898. Function: getModule
  1899. Returns an entry from the bigtree_modules table.
  1900. Parameters:
  1901. id - The id of the module.
  1902. Returns:
  1903. A module entry with the "gbp" column decoded.
  1904. */
  1905. function getModule($id) {
  1906. $id = mysql_real_escape_string($id);
  1907. $module = sqlfetch(sqlquery("SELECT * FROM bigtree_modules WHERE id = '$id'"));
  1908. if (!$module) {
  1909. return false;
  1910. }
  1911. $module["gbp"] = json_decode($module["gbp"],true);
  1912. return $module;
  1913. }
  1914. /*
  1915. Function: getModuleAction
  1916. Returns an entry from the bigtree_module_actions table.
  1917. Parameters:
  1918. id - The id of the action.
  1919. Returns:
  1920. A module action entry.
  1921. */
  1922. function getModuleAction($id) {
  1923. $id = mysql_real_escape_string($id);
  1924. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE id = '$id'"));
  1925. }
  1926. /*
  1927. Function: getModuleActionByRoute
  1928. Returns an entry from the bigtree_module_actions table for the given module and route.
  1929. Parameters:
  1930. module - The module to lookup an action for.
  1931. route - The route of the action.
  1932. Returns:
  1933. A module action entry.
  1934. */
  1935. function getModuleActionByRoute($module,$route) {
  1936. $module = mysql_real_escape_string($module);
  1937. $route = mysql_real_escape_string($route);
  1938. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '$module' AND route = '$route'"));
  1939. }
  1940. /*
  1941. Function: getModuleActionForForm
  1942. Returns the related module action for an auto module form.
  1943. Parameters:
  1944. form - The id of a form or a form entry.
  1945. Returns:
  1946. A module action entry.
  1947. */
  1948. function getModuleActionForForm($form) {
  1949. if (is_array($form)) {
  1950. $form = mysql_real_escape_string($form["id"]);
  1951. } else {
  1952. $form = mysql_real_escape_string($form);
  1953. }
  1954. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE form = '$form'"));
  1955. }
  1956. /*
  1957. Function: getModuleActionForView
  1958. Returns the related module action for an auto module view.
  1959. Parameters:
  1960. view - The id of a view or a view entry.
  1961. Returns:
  1962. A module action entry.
  1963. */
  1964. function getModuleActionForView($view) {
  1965. if (is_array($form)) {
  1966. $view = mysql_real_escape_string($view["id"]);
  1967. } else {
  1968. $view = mysql_real_escape_string($view);
  1969. }
  1970. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE view = '$view'"));
  1971. }
  1972. /*
  1973. Function: getModuleActions
  1974. Returns a list of module actions in positioned order.
  1975. Parameters:
  1976. module - A module id or a module entry.
  1977. Returns:
  1978. An array of module action entries.
  1979. */
  1980. function getModuleActions($module) {
  1981. if (is_array($module)) {
  1982. $module = mysql_real_escape_string($module["id"]);
  1983. } else {
  1984. $module = mysql_real_escape_string($module);
  1985. }
  1986. $items = array();
  1987. $q = sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '$module' ORDER BY position DESC, id ASC");
  1988. while ($f = sqlfetch($q)) {
  1989. $items[] = $f;
  1990. }
  1991. return $items;
  1992. }
  1993. /*
  1994. Function: getModuleByRoute
  1995. Returns a module entry for the given route.
  1996. Parameters:
  1997. route - A module route.
  1998. Returns:
  1999. A module entry with the "gbp" column decoded or false if a module was not found.
  2000. */
  2001. function getModuleByRoute($route) {
  2002. $route = mysql_real_escape_string($route);
  2003. $module = sqlfetch(sqlquery("SELECT * FROM bigtree_modules WHERE route = '$route'"));
  2004. if (!$module) {
  2005. return false;
  2006. }
  2007. $module["gbp"] = json_decode($module["gbp"],true);
  2008. return $module;
  2009. }
  2010. /*
  2011. Function: getModuleForms
  2012. Gets all module forms.
  2013. Returns:
  2014. An array of entries from bigtree_module_forms with "fields" decoded.
  2015. */
  2016. function getModuleForms() {
  2017. $items = array();
  2018. $q = sqlquery("SELECT * FROM bigtree_module_forms");
  2019. while ($f = sqlfetch($q)) {
  2020. $f["fields"] = json_decode($f["fields"],true);
  2021. $items[] = $f;
  2022. }
  2023. return $items;
  2024. }
  2025. /*
  2026. Function: getModuleGroup
  2027. Returns a module group entry from the bigtree_module_groups table.
  2028. Parameters:
  2029. id - The id of the module group.
  2030. Returns:
  2031. A module group entry.
  2032. See Also:
  2033. <getModuleGroupByName>
  2034. <getModuleGroupByRoute>
  2035. */
  2036. function getModuleGroup($id) {
  2037. $id = mysql_real_escape_string($id);
  2038. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_groups WHERE id = '$id'"));
  2039. }
  2040. /*
  2041. Function: getModuleGroupByName
  2042. Returns a module group entry from the bigtree_module_groups table.
  2043. Parameters:
  2044. name - The name of the module group.
  2045. Returns:
  2046. A module group entry.
  2047. See Also:
  2048. <getModuleGroup>
  2049. <getModuleGroupByRoute>
  2050. */
  2051. function getModuleGroupByName($name) {
  2052. $name = mysql_real_escape_string(strtolower($name));
  2053. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_groups WHERE LOWER(name) = '$name'"));
  2054. }
  2055. /*
  2056. Function: getModuleGroupByRoute
  2057. Returns a module group entry from the bigtree_module_groups table.
  2058. Parameters:
  2059. route - The route of the module group.
  2060. Returns:
  2061. A module group entry.
  2062. See Also:
  2063. <getModuleGroup>
  2064. <getModuleGroupByName>
  2065. */
  2066. function getModuleGroupByRoute($route) {
  2067. $name = mysql_real_escape_string($route);
  2068. return sqlfetch(sqlquery("SELECT * FROM bigtree_module_groups WHERE route = '$route'"));
  2069. }
  2070. /*
  2071. Function: getModuleGroups
  2072. Returns a list of module groups.
  2073. Parameters:
  2074. sort - Sort by (defaults to positioned)
  2075. Returns:
  2076. An array of module group entries from bigtree_module_groups.
  2077. */
  2078. function getModuleGroups($sort = "position DESC, id ASC") {
  2079. $items = array();
  2080. $q = sqlquery("SELECT * FROM bigtree_module_groups ORDER BY $sort");
  2081. while ($f = sqlfetch($q)) {
  2082. $items[$f["id"]] = $f;
  2083. }
  2084. return $items;
  2085. }
  2086. /*
  2087. Function: getModuleNavigation
  2088. Returns a list of module actions that are in navigation.
  2089. Parameters:
  2090. module - A module id or a module entry.
  2091. Returns:
  2092. An array of module actions from bigtree_module_actions.
  2093. */
  2094. function getModuleNavigation($module) {
  2095. if (is_array($module)) {
  2096. $module = mysql_real_escape_string($module["id"]);
  2097. } else {
  2098. $module = mysql_real_escape_string($module);
  2099. }
  2100. $items = array();
  2101. $q = sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '$module' AND in_nav = 'on' ORDER BY position DESC, id ASC");
  2102. while ($f = sqlfetch($q)) {
  2103. $items[] = $f;
  2104. }
  2105. return $items;
  2106. }
  2107. /*
  2108. Function: getModulePackage
  2109. Returns a module package with details decoded.
  2110. Parameters:
  2111. id - The id of the module package.
  2112. Returns:
  2113. A module package entry from bigtree_module_packages.
  2114. */
  2115. function getModulePackage($id) {
  2116. $id = mysql_real_escape_string($id);
  2117. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_module_packages WHERE id = '$id'"));
  2118. if (!$item) {
  2119. return false;
  2120. }
  2121. $item["details"] = json_decode($item["details"],true);
  2122. return $item;
  2123. }
  2124. /*
  2125. Function: getModulePackages
  2126. Returns a list of module packages.
  2127. Parameters:
  2128. sort - Sort order (defaults to alphabetical by name)
  2129. Returns:
  2130. An array of entries from bigtree_module_packages.
  2131. */
  2132. function getModulePackages($sort = "name ASC") {
  2133. $packages = array();
  2134. $q = sqlquery("SELECT * FROM bigtree_module_packages ORDER BY $sort");
  2135. while ($f = sqlfetch($q)) {
  2136. $packages[] = $f;
  2137. }
  2138. return $packages;
  2139. }
  2140. /*
  2141. Function: getModules
  2142. Returns a list of modules.
  2143. Parameters:
  2144. sort - The sort order (defaults to oldest first).
  2145. auth - If set to true, only returns modules the logged in user has access to. Defaults to true.
  2146. Returns:
  2147. An array of entries from the bigtree_modules table with an additional "group_name" column for the group the module is in.
  2148. */
  2149. function getModules($sort = "id ASC",$auth = true) {
  2150. $items = array();
  2151. $q = sqlquery("SELECT bigtree_modules.*,bigtree_module_groups.name AS group_name FROM bigtree_modules LEFT JOIN bigtree_module_groups ON bigtree_modules.`group` = bigtree_module_groups.id ORDER BY $sort");
  2152. while ($f = sqlfetch($q)) {
  2153. if (!$auth || $this->checkAccess($f["id"])) {
  2154. $items[$f["id"]] = $f;
  2155. }
  2156. }
  2157. return $items;
  2158. }
  2159. /*
  2160. Function: getModulesByGroup
  2161. Returns a list of modules in a given group.
  2162. Parameters:
  2163. group - The group to return modules for.
  2164. sort - The sort order (defaults to positioned)
  2165. auth - If set to true, only returns modules the logged in user has access to. Defaults to true.
  2166. Returns:
  2167. An array of entries from the bigtree_modules table with an additional "group_name" column for the group the module is in.
  2168. */
  2169. function getModulesByGroup($group,$sort = "position DESC, id ASC",$auth = true) {
  2170. if (is_array($group)) {
  2171. $group = mysql_real_escape_string($group["id"]);
  2172. } else {
  2173. $group = mysql_real_escape_string($group);
  2174. }
  2175. $items = array();
  2176. $q = sqlquery("SELECT * FROM bigtree_modules WHERE `group` = '$group' ORDER BY $sort");
  2177. while ($f = sqlfetch($q)) {
  2178. if ($this->checkAccess($f["id"]) || !$auth) {
  2179. $items[$f["id"]] = $f;
  2180. }
  2181. }
  2182. return $items;
  2183. }
  2184. /*
  2185. Function: getNaturalNavigationByParent
  2186. Returns a list of positioned navigation that is in navigation under the given parent.
  2187. Does not return module navigation.
  2188. Parameters:
  2189. parent - The ID of the parent page
  2190. Returns:
  2191. An array of page entries.
  2192. */
  2193. function getNaturalNavigationByParent($parent,$levels = 1) {
  2194. $nav = array();
  2195. $q = sqlquery("SELECT id,nav_title as title,parent,external,new_window,template,publish_at,expire_at,path FROM bigtree_pages WHERE parent = '$parent' AND in_nav = 'on' AND archived != 'on' ORDER BY position DESC, id ASC");
  2196. while ($nav_item = sqlfetch($q)) {
  2197. $nav_item["external"] = str_replace("{wwwroot}",$GLOBALS["www_root"],$nav_item["external"]);
  2198. if ($levels > 1) {
  2199. $nav_item["children"] = $this->getNaturalNavigationByParent($f["id"],$levels - 1);
  2200. }
  2201. $nav[] = $nav_item;
  2202. }
  2203. return $nav;
  2204. }
  2205. /*
  2206. Function: getPageAccessLevel
  2207. Returns the access level for the logged in user to a given page.
  2208. Parameters:
  2209. page - The page id.
  2210. Returns:
  2211. "p" for publisher, "e" for editor, false for no access.
  2212. See Also:
  2213. <getPageAccessLevelForUser>
  2214. */
  2215. function getPageAccessLevel($page) {
  2216. return $this->getPageAccessLevelByUser($page,$this->ID);
  2217. }
  2218. /*
  2219. Function: getPageAccessLevel
  2220. Returns the access level for the given user to a given page.
  2221. Parameters:
  2222. page - The page id.
  2223. user - The user id.
  2224. Returns:
  2225. "p" for publisher, "e" for editor, false for no access.
  2226. See Also:
  2227. <getPageAccessLevel>
  2228. */
  2229. function getPageAccessLevelByUser($page,$user) {
  2230. $u = $this->getUser($user);
  2231. if ($u["level"] > 0) {
  2232. return "p";
  2233. }
  2234. if (!is_numeric($page) && $page[0] == "p") {
  2235. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE id = '".substr($page,1)."'"));
  2236. if ($f["user"] == $user) {
  2237. return "p";
  2238. }
  2239. $pdata = json_decode($f["changes"],true);
  2240. return $this->getPageAccessLevelByUser($pdata["parent"],$user);
  2241. }
  2242. $pp = $this->Permissions["page"][$page];
  2243. if ($pp == "n") {
  2244. return false;
  2245. }
  2246. if ($pp && $pp != "i") {
  2247. return $pp;
  2248. }
  2249. $parent = sqlfetch(sqlquery("SELECT parent FROM bigtree_pages WHERE id = '".mysql_real_escape_string($page)."'"),true);
  2250. $pp = $u["permissions"]["page"][$parent];
  2251. while ((!$pp || $pp == "i") && $parent) {
  2252. $parent = sqlfetch(sqlquery("SELECT parent FROM bigtree_pages WHERE id = '$parent'"),true);
  2253. $pp = $u["permissions"]["page"][$parent];
  2254. }
  2255. if (!$pp || $pp == "i" || $pp == "n") {
  2256. return false;
  2257. }
  2258. return $pp;
  2259. }
  2260. /*
  2261. Function: getPageAdminLinks
  2262. Gets a list of pages that link back to the admin.
  2263. Returns:
  2264. An array of pages that link to the admin.
  2265. */
  2266. function getPageAdminLinks() {
  2267. $pages = array();
  2268. $q = sqlquery("SELECT * FROM bigtree_pages WHERE resources LIKE '%".$admin_root."%' OR resources LIKE '%".str_replace($www_root,"{wwwroot}",$admin_root)."%'");
  2269. while ($f = sqlfetch($q)) {
  2270. $pages[] = $f;
  2271. }
  2272. return $pages;
  2273. }
  2274. /*
  2275. Function: getPageChanges
  2276. Returns pending changes for a given page.
  2277. Parameters:
  2278. page - The page id.
  2279. Returns:
  2280. An entry from bigtree_pending_changes with changes decoded.
  2281. */
  2282. function getPageChanges($page) {
  2283. $page = mysql_real_escape_string($page);
  2284. $c = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE `table` = 'bigtree_pages' AND item_id = '$page'"));
  2285. if (!$c) {
  2286. return false;
  2287. }
  2288. $c["changes"] = json_decode($c["changes"],true);
  2289. return $c;
  2290. }
  2291. /*
  2292. Function: getPageChildren
  2293. Returns all non-archived children of a given page.
  2294. Parameters:
  2295. page - The page id to pull children for.
  2296. sort - The way to sort results. Defaults to nav_title ASC.
  2297. Returns:
  2298. An array of pages.
  2299. */
  2300. function getPageChildren($page,$sort = "nav_title ASC") {
  2301. $page = mysql_real_escape_string($page);
  2302. $items = array();
  2303. $q = sqlquery("SELECT * FROM bigtree_pages WHERE parent = '$page' AND archived != 'on' ORDER BY $sort");
  2304. while ($f = sqlfetch($q)) {
  2305. $items[] = $f;
  2306. }
  2307. return $items;
  2308. }
  2309. /*
  2310. Function: getPageIds
  2311. Returns all page ids in bigtree_pages.
  2312. Returns:
  2313. An array of page ids.
  2314. */
  2315. function getPageIds() {
  2316. $ids = array();
  2317. $q = sqlquery("SELECT id FROM bigtree_pages ORDER BY id ASC");
  2318. while ($f = sqlfetch($q)) {
  2319. $ids[] = $f["id"];
  2320. }
  2321. return $ids;
  2322. }
  2323. /*
  2324. Function: getPageOfSettings
  2325. Returns a page of settings.
  2326. Parameters:
  2327. page - The page to return.
  2328. query - Optional query string to search against.
  2329. sort - Sort order. Defaults to name ASC.
  2330. Returns:
  2331. An array of entries from bigtree_settings.
  2332. If the setting is encrypted the value will be "[Encrypted Text]", otherwise it will be decoded.
  2333. If the calling user is a developer, returns locked settings, otherwise they are left out.
  2334. */
  2335. function getPageOfSettings($page = 0,$query = "") {
  2336. global $cms;
  2337. // If we're querying...
  2338. if ($query) {
  2339. $qparts = explode(" ",$query);
  2340. $qp = array();
  2341. foreach ($qparts as $part) {
  2342. $part = mysql_real_escape_string($part);
  2343. $qp[] = "(name LIKE '%$part%' OR `value` LIKE '%$part%' OR description LIKE '%$part%')";
  2344. }
  2345. // If we're not a developer, leave out locked settings
  2346. if ($this->Level < 2) {
  2347. $q = sqlquery("SELECT * FROM bigtree_settings WHERE ".implode(" AND ",$qp)." AND locked != 'on' AND system != 'on' ORDER BY name LIMIT ".($page*$this->PerPage).",".$this->PerPage);
  2348. // If we are a developer, show them.
  2349. } else {
  2350. $q = sqlquery("SELECT * FROM bigtree_settings WHERE ".implode(" AND ",$qp)." AND system != 'on' ORDER BY name LIMIT ".($page*$this->PerPage).",".$this->PerPage);
  2351. }
  2352. } else {
  2353. // If we're not a developer, leave out locked settings
  2354. if ($this->Level < 2) {
  2355. $q = sqlquery("SELECT * FROM bigtree_settings WHERE locked != 'on' AND system != 'on' ORDER BY name LIMIT ".($page*$this->PerPage).",".$this->PerPage);
  2356. // If we are a developer, show them.
  2357. } else {
  2358. $q = sqlquery("SELECT * FROM bigtree_settings WHERE system != 'on' ORDER BY name LIMIT ".($page*$this->PerPage).",".$this->PerPage);
  2359. }
  2360. }
  2361. $items = array();
  2362. while ($f = sqlfetch($q)) {
  2363. foreach ($f as $key => $val) {
  2364. $f[$key] = str_replace("{wwwroot}",$GLOBALS["www_root"],$val);
  2365. }
  2366. $f["value"] = json_decode($f["value"],true);
  2367. if ($f["encrypted"] == "on") {
  2368. $f["value"] = "[Encrypted Text]";
  2369. }
  2370. $items[] = $f;
  2371. }
  2372. return $items;
  2373. }
  2374. /*
  2375. Function: getPageOfUsers
  2376. Returns a page of users.
  2377. Parameters:
  2378. page - The page of users to return.
  2379. query - Optional query string to search against.
  2380. sort - Order to sort the results by. Defaults to name ASC.
  2381. Returns:
  2382. An array of entries from bigtree_users.
  2383. */
  2384. function getPageOfUsers($page = 0,$query = "",$sort = "name ASC") {
  2385. // If we're searching.
  2386. if ($query) {
  2387. $qparts = explode(" ",$query);
  2388. $qp = array();
  2389. foreach ($qparts as $part) {
  2390. $part = mysql_real_escape_string($part);
  2391. $qp[] = "(name LIKE '%$part%' OR email LIKE '%$part%' OR company LIKE '%$part%')";
  2392. }
  2393. $q = sqlquery("SELECT * FROM bigtree_users WHERE ".implode(" AND ",$qp)." ORDER BY $sort LIMIT ".($page * $this->PerPage).",".$this->PerPage);
  2394. // If we're grabbing anyone.
  2395. } else {
  2396. $q = sqlquery("SELECT * FROM bigtree_users ORDER BY $sort LIMIT ".($page * $this->PerPage).",".$this->PerPage);
  2397. }
  2398. $items = array();
  2399. while ($f = sqlfetch($q)) {
  2400. $items[] = $f;
  2401. }
  2402. return $items;
  2403. }
  2404. /*
  2405. Function: getPageRevision
  2406. Returns a version of a page from the bigtree_page_revisions table.
  2407. Parameters:
  2408. id - The id of the page version.
  2409. Returns:
  2410. A page version entry from the table.
  2411. */
  2412. function getPageRevision($id) {
  2413. $id = mysql_real_escape_string($id);
  2414. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_page_revisions WHERE id = '$id'"));
  2415. return $item;
  2416. }
  2417. /*
  2418. Function: getPageRevisions
  2419. Get all revisions for a page.
  2420. Parameters:
  2421. page - The page id to get revisions for.
  2422. Returns:
  2423. An array of "saved" revisions and "unsaved" revisions.
  2424. */
  2425. function getPageRevisions($page) {
  2426. $page = mysql_real_escape_string($page);
  2427. // Get all previous revisions, add them to the saved or unsaved list
  2428. $unsaved = array();
  2429. $saved = array();
  2430. $q = sqlquery("SELECT bigtree_users.name, bigtree_page_revisions.saved, bigtree_page_revisions.saved_description, bigtree_page_revisions.updated_at, bigtree_page_revisions.id FROM bigtree_page_revisions JOIN bigtree_users ON bigtree_page_revisions.author = bigtree_users.id WHERE page = '$page' ORDER BY updated_at DESC");
  2431. while ($f = sqlfetch($q)) {
  2432. if ($f["saved"]) {
  2433. $saved[] = $f;
  2434. } else {
  2435. $unsaved[] = $f;
  2436. }
  2437. }
  2438. return array("saved" => $saved, "unsaved" => $unsaved);
  2439. }
  2440. /*
  2441. Function: getPages
  2442. Returns all pages from the database.
  2443. Returns:
  2444. Array of unmodified entries from bigtree_pages.
  2445. */
  2446. function getPages() {
  2447. $items = array();
  2448. $q = sqlquery("SELECT * FROM bigtree_pages ORDER BY id ASC");
  2449. while ($f = sqlfetch($q)) {
  2450. $items[] = $f;
  2451. }
  2452. return $items;
  2453. }
  2454. /*
  2455. Function: getPageSEORating
  2456. Returns the SEO rating for a page.
  2457. Parameters:
  2458. page - A page array.
  2459. content - An array of resources.
  2460. Returns:
  2461. An array of SEO data.
  2462. "score" reflects a score from 0 to 100 points.
  2463. "recommendations" is an array of recommendations to improve SEO score.
  2464. "color" is a color reflecting the SEO score.
  2465. Score Parameters
  2466. - Having a title - 5 points
  2467. - Having a unique title - 5 points
  2468. - Title does not exceed 72 characters and has at least 4 words - 5 points
  2469. - Having a meta description - 5 points
  2470. - Meta description that is less than 165 characters - 5 points
  2471. - Having an h1 - 10 points
  2472. - Having page content - 5 points
  2473. - Having at least 300 words in your content - 15 points
  2474. - Having links in your content - 5 points
  2475. - Having external links in your content - 5 points
  2476. - Having one link for every 120 words of content - 5 points
  2477. - Readability Score - up to 20 points
  2478. - Fresh content - up to 10 points
  2479. */
  2480. function getPageSEORating($page,$content) {
  2481. global $cms;
  2482. $template = $cms->getTemplate($page["template"]);
  2483. $tsources = array();
  2484. $h1_field = "";
  2485. $body_fields = array();
  2486. if (is_array($template)) {
  2487. foreach ($template["resources"] as $item) {
  2488. if ($item["seo_body"]) {
  2489. $body_fields[] = $item["id"];
  2490. }
  2491. if ($item["seo_h1"]) {
  2492. $h1_field = $item["id"];
  2493. }
  2494. $tsources[$item["id"]] = $item;
  2495. }
  2496. }
  2497. if (!$h1_field && $tsources["page_header"]) {
  2498. $h1_field = "page_header";
  2499. }
  2500. if (!count($body_fields) && $tsources["page_content"]) {
  2501. $body_fields[] = "page_content";
  2502. }
  2503. $textStats = new TextStatistics;
  2504. $recommendations = array();
  2505. $score = 0;
  2506. // Check if they have a page title.
  2507. if ($page["title"]) {
  2508. $score += 5;
  2509. // They have a title, let's see if it's unique
  2510. $q = sqlquery("SELECT * FROM bigtree_pages WHERE title = '".mysql_real_escape_string($page["title"])."' AND id != '".$page["page"]."'");
  2511. if ($r == 0) {
  2512. // They have a unique title
  2513. $score += 5;
  2514. } else {
  2515. $recommendations[] = "Your page title should be unique. ".($r-1)." other page(s) have the same title.";
  2516. }
  2517. $words = $textStats->word_count($page["title"]);
  2518. $length = mb_strlen($page["title"]);
  2519. if ($words >= 4 && $length <= 72) {
  2520. // Fits the bill!
  2521. $score += 5;
  2522. } else {
  2523. $recommendations[] = "Your page title should be no more than 72 characters and should contain at least 4 words.";
  2524. }
  2525. } else {
  2526. $recommendations[] = "You should enter a page title.";
  2527. }
  2528. // Check for meta description
  2529. if ($page["meta_description"]) {
  2530. $score += 5;
  2531. // They have a meta description, let's see if it's no more than 165 characters.
  2532. if (mb_strlen($page["meta_description"]) <= 165) {
  2533. $score += 5;
  2534. } else {
  2535. $recommendations[] = "Your meta description should be no more than 165 characters. It is currently ".mb_strlen($page["meta_description"])." characters.";
  2536. }
  2537. } else {
  2538. $recommendations[] = "You should enter a meta description.";
  2539. }
  2540. // Check for an H1
  2541. if (!$h1_field || $content[$h1_field]) {
  2542. $score += 10;
  2543. } else {
  2544. $recommendations[] = "You should enter a page header.";
  2545. }
  2546. // Check the content!
  2547. if (!count($body_fields)) {
  2548. // If this template doesn't for some reason have a seo body resource, give the benefit of the doubt.
  2549. $score += 65;
  2550. } else {
  2551. $regular_text = "";
  2552. $stripped_text = "";
  2553. foreach ($body_fields as $field) {
  2554. if (!is_array($content[$field])) {
  2555. $regular_text .= $content[$field]." ";
  2556. $stripped_text .= strip_tags($content[$field])." ";
  2557. }
  2558. }
  2559. // Check to see if there is any content
  2560. if ($stripped_text) {
  2561. $score += 5;
  2562. $words = $textStats->word_count($stripped_text);
  2563. $readability = $textStats->flesch_kincaid_reading_ease($stripped_text);
  2564. $number_of_links = substr_count($regular_text,"<a ");
  2565. $number_of_external_links = substr_count($regular_text,'href="http://');
  2566. // See if there are at least 300 words.
  2567. if ($words >= 300) {
  2568. $score += 15;
  2569. } else {
  2570. $recommendations[] = "You should enter at least 300 words of page content. You currently have ".$words." word(s).";
  2571. }
  2572. // See if we have any links
  2573. if ($number_of_links) {
  2574. $score += 5;
  2575. // See if we have at least one link per 120 words.
  2576. if (floor($words / 120) <= $number_of_links) {
  2577. $score += 5;
  2578. } else {
  2579. $recommendations[] = "You should have at least one link for every 120 words of page content. You currently have $number_of_links link(s). You should have at least ".floor($words / 120).".";
  2580. }
  2581. // See if we have any external links.
  2582. if ($number_of_external_links) {
  2583. $score += 5;
  2584. } else {
  2585. $recommendations[] = "Having an external link helps build Page Rank.";
  2586. }
  2587. } else {
  2588. $recommendations[] = "You should have at least one link in your content.";
  2589. }
  2590. // Check on our readability score.
  2591. if ($readability >= 90) {
  2592. $score += 20;
  2593. } else {
  2594. $read_score = round(($readability / 90),2);
  2595. $recommendations[] = "Your readability score is ".($read_score*100)."%. Using shorter sentences and words with less syllables will make your site easier to read by search engines and users.";
  2596. $score += ceil($read_score * 20);
  2597. }
  2598. } else {
  2599. $recommendations[] = "You should enter page content.";
  2600. }
  2601. // Check page freshness
  2602. $updated = strtotime($page["updated_at"]);
  2603. $age = time()-$updated-(60*24*60*60);
  2604. // See how much older it is than 2 months.
  2605. if ($age > 0) {
  2606. $age_score = 10 - floor(2 * ($age / (30*24*60*60)));
  2607. if ($age_score < 0) {
  2608. $age_score = 0;
  2609. }
  2610. $score += $age_score;
  2611. $recommendations[] = "Your content is around ".ceil(2 + ($age / (30*24*60*60)))." months old. Updating your page more frequently will make it rank higher.";
  2612. } else {
  2613. $score += 10;
  2614. }
  2615. }
  2616. $color = "#008000";
  2617. if ($score <= 50) {
  2618. $color = BigTree::colorMesh("#CCAC00","#FF0000",100-(100 * $score / 50));
  2619. } elseif ($score <= 80) {
  2620. $color = BigTree::colorMesh("#008000","#CCAC00",100-(100 * ($score-50) / 30));
  2621. }
  2622. return array("score" => $score, "recommendations" => $recommendations, "color" => $color);
  2623. }
  2624. /*
  2625. Function: getPendingChange
  2626. Returns a pending change from the bigtree_pending_changes table.
  2627. Parameters:
  2628. id - The id of the change.
  2629. Returns:
  2630. A entry from the table with the "changes" column decoded.
  2631. */
  2632. function getPendingChange($id) {
  2633. $id = mysql_real_escape_string($id);
  2634. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE id = '$id'"));
  2635. if (!$item) {
  2636. return false;
  2637. }
  2638. $item["changes"] = json_decode($item["changes"],true);
  2639. return $item;
  2640. }
  2641. /*
  2642. Function: getPendingChanges
  2643. Returns a list of changes that the logged in user has access to publish.
  2644. Parameters:
  2645. user - The user id to retrieve changes for. Defaults to the logged in user.
  2646. Returns:
  2647. An array of changes sorted by most recent.
  2648. */
  2649. function getPendingChanges($user = false) {
  2650. if (!$user) {
  2651. $user = $this->getUser($this->ID);
  2652. } else {
  2653. $user = $this->getUser($user);
  2654. }
  2655. $changes = array();
  2656. // Setup the default search array to just be pages
  2657. $search = array("`module` = ''");
  2658. // Add each module the user has publisher permissions to
  2659. if (is_array($user["permissions"]["module"])) {
  2660. foreach ($user["permissions"]["module"] as $module => $permission) {
  2661. if ($permission == "p") {
  2662. $search[] = "`module` = '$module'";
  2663. }
  2664. }
  2665. }
  2666. // Add module group based permissions as well
  2667. if (is_array($user["permissions"]["module_gbp"])) {
  2668. foreach ($user["permissions"]["module_gbp"] as $module => $groups) {
  2669. foreach ($groups as $group => $permission) {
  2670. if ($permission == "p") {
  2671. $search[] = "`module` = '$module'";
  2672. }
  2673. }
  2674. }
  2675. }
  2676. $q = sqlquery("SELECT * FROM bigtree_pending_changes WHERE ".implode(" OR ",$search)." ORDER BY date DESC");
  2677. while ($f = sqlfetch($q)) {
  2678. $ok = false;
  2679. if (!$f["item_id"]) {
  2680. $id = "p".$f["id"];
  2681. } else {
  2682. $id = $f["item_id"];
  2683. }
  2684. // If they're an admin, they've got it.
  2685. if ($user["level"] > 0) {
  2686. $ok = true;
  2687. // Check permissions on a page if it's a page.
  2688. } elseif ($f["table"] == "bigtree_pages") {
  2689. $r = $this->getPageAccessLevel($id);
  2690. // If we're a publisher, this is ours!
  2691. if ($r == "p") {
  2692. $ok = true;
  2693. }
  2694. } else {
  2695. // Check our list of modules.
  2696. if ($user["permissions"]["module"][$f["module"]] == "p") {
  2697. $ok = true;
  2698. } else {
  2699. // Check our group based permissions
  2700. $item = BigTreeAutoModule::getPendingItem($f["table"],$id);
  2701. $level = $this->getAccessLevel($this->getModule($f["module"]),$item["item"],$f["table"]);
  2702. if ($level == "p") {
  2703. $ok = true;
  2704. }
  2705. }
  2706. }
  2707. // We're a publisher, get the info about the change and put it in the change list.
  2708. if ($ok) {
  2709. $mod = $this->getModule($f["module"]);
  2710. $user = $this->getUser($f["user"]);
  2711. $comments = unserialize($f["comments"]);
  2712. if (!is_array($comments)) {
  2713. $comments = array();
  2714. }
  2715. $f["mod"] = $mod;
  2716. $f["user"] = $user;
  2717. $f["comments"] = $comments;
  2718. $changes[] = $f;
  2719. }
  2720. }
  2721. return $changes;
  2722. }
  2723. /*
  2724. Function: getPendingNavigationByParent
  2725. Returns a list of pending pages under a given parent ordered by most recent.
  2726. Parameters:
  2727. parent - The ID of the parent page
  2728. in_nav - "on" returns pages in navigation, "" returns hidden pages
  2729. Returns:
  2730. An array of pending page titles/ids.
  2731. */
  2732. function getPendingNavigationByParent($parent,$in_nav = "on") {
  2733. $nav = array();
  2734. $titles = array();
  2735. $q = sqlquery("SELECT * FROM bigtree_pending_changes WHERE pending_page_parent = '$parent' AND `table` = 'bigtree_pages' AND type = 'NEW' ORDER BY date DESC");
  2736. while ($f = sqlfetch($q)) {
  2737. $page = json_decode($f["changes"],true);
  2738. if ($page["in_nav"] == $in_nav) {
  2739. $titles[] = $page["nav_title"];
  2740. $page["bigtree_pending"] = true;
  2741. $page["title"] = $page["nav_title"];
  2742. $page["id"] = "p".$f["id"];
  2743. $nav[] = $page;
  2744. }
  2745. }
  2746. array_multisort($titles,$nav);
  2747. return $nav;
  2748. }
  2749. /*
  2750. Function: getPendingPage
  2751. Returns a page from the database with all its pending changes applied.
  2752. Parameters:
  2753. id - The ID of the live page or the ID of a pending page with "p" preceding the ID.
  2754. Returns:
  2755. A decoded page array with pending changes applied and related tags.
  2756. See Also:
  2757. <BigTreeCMS.getPage>
  2758. */
  2759. function getPendingPage($id) {
  2760. global $cms;
  2761. // Get the live page.
  2762. if (is_numeric($id)) {
  2763. global $cms;
  2764. $page = $cms->getPage($id);
  2765. if (!$page) {
  2766. return false;
  2767. }
  2768. $page["tags"] = $this->getTagsForPage($id);
  2769. // Get pending changes for this page.
  2770. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE `table` = 'bigtree_pages' AND item_id = '".$page["id"]."'"));
  2771. } else {
  2772. $page = array();
  2773. // Get the page.
  2774. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE `id` = '".mysql_real_escape_string(substr($id,1))."'"));
  2775. if ($f) {
  2776. $f["id"] = $id;
  2777. } else {
  2778. return false;
  2779. }
  2780. }
  2781. // Sweep through pending changes and apply them to the page
  2782. if ($f) {
  2783. $page["updated_at"] = $f["date"];
  2784. $changes = json_decode($f["changes"],true);
  2785. foreach ($changes as $key => $val) {
  2786. if ($key == "external") {
  2787. $val = $cms->getInternalPageLink($val);
  2788. }
  2789. // Decode the changes' IPLs.
  2790. if (is_array($val)) {
  2791. $val = BigTree::untranslateArray($val);
  2792. }
  2793. $page[$key] = $val;
  2794. }
  2795. // Decode the tag changes, apply them back.
  2796. $tags = array();
  2797. $temp_tags = json_decode($f["tags_changes"],true);
  2798. if (is_array($temp_tags)) {
  2799. foreach ($temp_tags as $tag) {
  2800. $tags[] = sqlfetch(sqlquery("SELECT * FROM bigtree_tags WHERE id = '$tag'"));
  2801. }
  2802. }
  2803. $page["tags"] = $tags;
  2804. // Say that changes exist
  2805. $page["changes_applied"] = true;
  2806. }
  2807. return $page;
  2808. }
  2809. /*
  2810. Function: getContentsOfResourceFolder
  2811. Returns a list of resources and subfolders in a folder (based on user permissions).
  2812. Parameters:
  2813. folder - The id of a folder or a folder entry.
  2814. sort - The column to sort the folder's files on (default: date DESC).
  2815. Returns:
  2816. An array of two arrays - folders and resources - that a user has access to.
  2817. */
  2818. function getContentsOfResourceFolder($folder, $sort = "date DESC") {
  2819. if (is_array($folder)) {
  2820. $folder = $folder["id"];
  2821. }
  2822. $folder = mysql_real_escape_string($folder);
  2823. $folders = array();
  2824. $resources = array();
  2825. $q = sqlquery("SELECT * FROM bigtree_resource_folders WHERE parent = '$folder' ORDER BY name");
  2826. while ($f = sqlfetch($q)) {
  2827. if ($this->Level > 0 || $this->getResourceFolderPermission($f["id"]) != "n") {
  2828. $folders[] = $f;
  2829. }
  2830. }
  2831. $q = sqlquery("SELECT * FROM bigtree_resources WHERE folder = '$folder' ORDER BY $sort");
  2832. while ($f = sqlfetch($q)) {
  2833. $resources[] = $f;
  2834. }
  2835. return array("folders" => $folders, "resources" => $resources);
  2836. }
  2837. /*
  2838. Function: getResourceByFile
  2839. Returns a resource with the given file name.
  2840. Parameters:
  2841. file - The file name.
  2842. Returns:
  2843. An entry from bigtree_resources with file and thumbs decoded.
  2844. */
  2845. function getResourceByFile($file) {
  2846. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_resources WHERE file = '".mysql_real_escape_string($file)."'"));
  2847. if (!$item) {
  2848. return false;
  2849. }
  2850. $item["file"] = str_replace("{wwwroot}",$GLOBALS["www_root"],$item["file"]);
  2851. $item["thumbs"] = json_decode($item["thumbs"],true);
  2852. foreach ($item["thumbs"] as &$thumb) {
  2853. $thumb = str_replace("{wwwroot}",$GLOBALS["www_root"],$thumb);
  2854. }
  2855. return $item;
  2856. }
  2857. /*
  2858. Function: getResourceFolder
  2859. Returns a resource folder.
  2860. Parameters:
  2861. id - The id of the folder.
  2862. Returns:
  2863. A resource folder entry.
  2864. */
  2865. function getResourceFolder($id) {
  2866. $id = mysql_real_escape_string($id);
  2867. return sqlfetch(sqlquery("SELECT * FROM bigtree_resource_folders WHERE id = '$id'"));
  2868. }
  2869. /*
  2870. Function: getResourceFolderBreadcrumb
  2871. Returns a breadcrumb of the given folder.
  2872. Parameters:
  2873. folder - The id of a folder or a folder entry.
  2874. Returns:
  2875. An array of arrays containing the name and id of folders above.
  2876. */
  2877. function getResourceFolderBreadcrumb($folder,$crumb = array()) {
  2878. if (!is_array($folder)) {
  2879. $folder = sqlfetch(sqlquery("SELECT * FROM bigtree_resource_folders WHERE id = '".mysql_real_escape_string($folder)."'"));
  2880. }
  2881. if ($folder) {
  2882. $crumb[] = array("id" => $folder["id"], "name" => $folder["name"]);
  2883. }
  2884. if ($folder["parent"]) {
  2885. return $this->getResourceFolderBreadcrumb($folder["parent"],$crumb);
  2886. } else {
  2887. $crumb[] = array("id" => 0, "name" => "Home");
  2888. return array_reverse($crumb);
  2889. }
  2890. }
  2891. /*
  2892. Function: getResourceFolderChildren
  2893. Returns the child folders of a resource folder.
  2894. Parameters:
  2895. id - The id of the parent folder.
  2896. Returns:
  2897. An array of resource folder entries.
  2898. */
  2899. function getResourceFolderChildren($id) {
  2900. $items = array();
  2901. $id = mysql_real_escape_string($id);
  2902. $q = sqlquery("SELECT * FROM bigtree_resource_folders WHERE parent = '$id' ORDER BY name ASC");
  2903. while ($f = sqlfetch($q)) {
  2904. $items[] = $f;
  2905. }
  2906. return $items;
  2907. }
  2908. /*
  2909. Function: getResourceFolderPermission
  2910. Returns the permission level of the current user for the folder.
  2911. Parameters:
  2912. folder - The id of a folder or a folder entry.
  2913. Returns:
  2914. "p" if a user can create folders and upload files, "e" if the user can see/use files, "n" if a user can't access this folder.
  2915. */
  2916. function getResourceFolderPermission($folder) {
  2917. // User is an admin or developer
  2918. if ($this->Level > 0) {
  2919. return "p";
  2920. }
  2921. // We're going to save the folder entry in case we need its parent later.
  2922. if (is_array($folder)) {
  2923. $id = $folder["id"];
  2924. } else {
  2925. $id = $folder;
  2926. }
  2927. $p = $this->Permissions["resources"][$id];
  2928. // If p is already no, creator, or consumer we can just return it.
  2929. if ($p && $p != "i") {
  2930. return $p;
  2931. } else {
  2932. // If folder is 0, we're already at home and can't check a higher folder for permissions.
  2933. if (!$folder) {
  2934. return "e";
  2935. }
  2936. // If a folder entry wasn't passed in, we need it to find its parent.
  2937. if (!is_array($folder)) {
  2938. $folder = sqlfetch(sqlquery("SELECT parent FROM bigtree_resource_folders WHERE id = '".mysql_real_escape_string($id)."'"));
  2939. }
  2940. // If we couldn't find the folder anymore, just say they can consume.
  2941. if (!$folder) {
  2942. return "e";
  2943. }
  2944. // Return the parent's permissions
  2945. return $this->getResourceFolderPermission($folder["parent"]);
  2946. }
  2947. }
  2948. /*
  2949. Function: getRoutedTemplates
  2950. Returns a list of routed templates ordered by position.
  2951. Returns:
  2952. An array of template entries.
  2953. */
  2954. function getRoutedTemplates() {
  2955. $q = sqlquery("SELECT * FROM bigtree_templates WHERE level <= '".$this->Level."' ORDER BY position DESC, id ASC");
  2956. $items = array();
  2957. while ($f = sqlfetch($q)) {
  2958. if ($f["routed"]) {
  2959. $items[] = $f;
  2960. }
  2961. }
  2962. return $items;
  2963. }
  2964. /*
  2965. Function: getSetting
  2966. Returns a setting.
  2967. Parameters:
  2968. id - The id of the setting to return.
  2969. Returns:
  2970. A setting entry with its value properly decoded and decrypted.
  2971. Returns false if the setting could not be found.
  2972. */
  2973. function getSetting($id) {
  2974. global $config;
  2975. $id = mysql_real_escape_string($id);
  2976. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_settings WHERE id = '$id'"));
  2977. if (!$f) {
  2978. return false;
  2979. }
  2980. foreach ($f as $key => $val) {
  2981. $f[$key] = str_replace("{wwwroot}",$GLOBALS["www_root"],$val);
  2982. }
  2983. if ($f["encrypted"]) {
  2984. $v = sqlfetch(sqlquery("SELECT AES_DECRYPT(`value`,'".mysql_real_escape_string($config["settings_key"])."') AS `value` FROM bigtree_settings WHERE id = '$id'"));
  2985. $f["value"] = $v["value"];
  2986. }
  2987. $f["value"] = json_decode($f["value"],true);
  2988. return $f;
  2989. }
  2990. /*
  2991. Function: getSettings
  2992. Returns a list of all settings.
  2993. Checks for developer access.
  2994. Parameters:
  2995. sort - Order to return the settings. Defaults to name ASC.
  2996. Returns:
  2997. An array of entries from bigtree_settings.
  2998. If the setting is encrypted the value will be "[Encrypted Text]", otherwise it will be decoded.
  2999. If the calling user is a developer, returns locked settings, otherwise they are left out.
  3000. */
  3001. function getSettings($sort = "name ASC") {
  3002. $items = array();
  3003. if ($this->Level < 2) {
  3004. $q = sqlquery("SELECT * FROM bigtree_settings WHERE locked != 'on' AND system != 'on' ORDER BY $sort");
  3005. } else {
  3006. $q = sqlquery("SELECT * FROM bigtree_settings WHERE system != 'on' ORDER BY $sort");
  3007. }
  3008. while ($f = sqlfetch($q)) {
  3009. foreach ($f as $key => $val) {
  3010. $f[$key] = str_replace("{wwwroot}",$GLOBALS["www_root"],$val);
  3011. }
  3012. $f["value"] = json_decode($f["value"],true);
  3013. if ($f["encrypted"] == "on") {
  3014. $f["value"] = "[Encrypted Text]";
  3015. }
  3016. $items[] = $f;
  3017. }
  3018. return $items;
  3019. }
  3020. /*
  3021. Function: getSettingsPageCount
  3022. Returns the number of pages of settings.
  3023. Parameters:
  3024. query - Optional string to query against.
  3025. Returns:
  3026. The number of pages of settings.
  3027. */
  3028. function getSettingsPageCount($query = "") {
  3029. // If we're searching.
  3030. if ($query) {
  3031. $qparts = explode(" ",$query);
  3032. $qp = array();
  3033. foreach ($qparts as $part) {
  3034. $part = mysql_real_escape_string($part);
  3035. $qp[] = "(name LIKE '%$part%' OR value LIKE '%$part%' OR description LIKE '%$part%')";
  3036. }
  3037. // Administrator
  3038. if ($this->Level < 2) {
  3039. $q = sqlquery("SELECT id FROM bigtree_settings WHERE system != 'on' AND locked != 'on' AND ".implode(" AND ",$qp));
  3040. // Developer
  3041. } else {
  3042. $q = sqlquery("SELECT id FROM bigtree_settings WHERE system != 'on' AND ".implode(" AND ",$qp));
  3043. }
  3044. } else {
  3045. // Administrator
  3046. if ($this->Level < 2) {
  3047. $q = sqlquery("SELECT id FROM bigtree_settings WHERE system != 'on' AND locked != 'on'");
  3048. // Developer
  3049. } else {
  3050. $q = sqlquery("SELECT id FROM bigtree_settings WHERE system != 'on'");
  3051. }
  3052. }
  3053. $r = sqlrows($q);
  3054. $pages = ceil($r / $this->PerPage);
  3055. if ($pages == 0) {
  3056. $pages = 1;
  3057. }
  3058. return $pages;
  3059. }
  3060. /*
  3061. Function: getTag
  3062. Returns a tag for the given id.
  3063. Parameters:
  3064. id - The id of the tag.
  3065. Returns:
  3066. A bigtree_tags entry.
  3067. */
  3068. function getTag($id) {
  3069. $id = mysql_real_escape_string($id);
  3070. return sqlfetch(sqlquery("SELECT * FROM bigtree_tags WHERE id = '$id'"));
  3071. }
  3072. /*
  3073. Function: getTagsForPage
  3074. Returns a list of tags a page is tagged with.
  3075. Parameters:
  3076. page - Either a page id or a page entry.
  3077. Returns:
  3078. An array of tags.
  3079. */
  3080. function getTagsForPage($page) {
  3081. if (is_array($page)) {
  3082. $page = mysql_real_escape_string($page["id"]);
  3083. } else {
  3084. $page = mysql_real_escape_string($page);
  3085. }
  3086. $tags = array();
  3087. $q = sqlquery("SELECT bigtree_tags.* FROM bigtree_tags JOIN bigtree_tags_rel WHERE bigtree_tags_rel.tag = bigtree_tags.id AND bigtree_tags_rel.entry = '$page' AND bigtree_tags_rel.module = '0' ORDER BY bigtree_tags.tag");
  3088. while ($f = sqlfetch($q)) {
  3089. $tags[] = $f;
  3090. }
  3091. return $tags;
  3092. }
  3093. /*
  3094. Function: getTemplates
  3095. Returns a list of templates.
  3096. Parameters:
  3097. sort - Sort order, defaults to positioned.
  3098. Returns:
  3099. An array of template entries.
  3100. */
  3101. function getTemplates($sort = "position DESC, name ASC") {
  3102. $items = array();
  3103. $q = sqlquery("SELECT * FROM bigtree_templates ORDER BY $sort");
  3104. while ($f = sqlfetch($q)) {
  3105. $items[] = $f;
  3106. }
  3107. return $items;
  3108. }
  3109. /*
  3110. Function: getUnreadMessageCount
  3111. Returns the number of unread messages for the logged in user.
  3112. Returns:
  3113. The number of unread messages.
  3114. */
  3115. function getUnreadMessageCount() {
  3116. return sqlrows(sqlquery("SELECT id FROM bigtree_messages WHERE recipients LIKE '%|".$this->ID."|%' AND read_by NOT LIKE '%|".$this->ID."|%'"));
  3117. }
  3118. /*
  3119. Function: getUser
  3120. Gets a user's decoded information.
  3121. Parameters:
  3122. id - The id of the user to return.
  3123. Returns:
  3124. A user entry from bigtree_users with permissions and alerts decoded.
  3125. */
  3126. function getUser($id) {
  3127. $id = mysql_real_escape_string($id);
  3128. $item = sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE id = '$id'"));
  3129. if ($item["level"] > 0) {
  3130. $permissions = array();
  3131. $q = sqlquery("SELECT * FROM bigtree_modules");
  3132. while ($f = sqlfetch($q)) {
  3133. $permissions["module"][$f["id"]] = "p";
  3134. }
  3135. $item["permissions"] = $permissions;
  3136. } else {
  3137. $item["permissions"] = json_decode($item["permissions"],true);
  3138. }
  3139. $item["alerts"] = json_decode($item["alerts"],true);
  3140. return $item;
  3141. }
  3142. /*
  3143. Function: getUserByEmail
  3144. Gets a user entry for a given email.
  3145. Parameters:
  3146. email - The email to find.
  3147. Returns:
  3148. A user entry from bigtree_users.
  3149. */
  3150. function getUserByEmail($email) {
  3151. $email = mysql_real_escape_string($email);
  3152. return sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE email = '$email'"));
  3153. }
  3154. /*
  3155. Function: getUserByHash
  3156. Gets a user entry for a change password hash.
  3157. Parameters:
  3158. hash - The hash to find.
  3159. Returns:
  3160. A user entry from bigtree_users.
  3161. */
  3162. function getUserByHash($hash) {
  3163. $hash = mysql_real_escape_string($hash);
  3164. return sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE change_password_hash = '$hash'"));
  3165. }
  3166. /*
  3167. Function: getUsers
  3168. Returns a list of all users.
  3169. Parameters:
  3170. sort - Order to sort the list. Defaults to name ASC.
  3171. Returns:
  3172. An array of entries from bigtree_users.
  3173. The keys of the array are the ids of the user.
  3174. */
  3175. function getUsers($sort = "name ASC") {
  3176. $items = array();
  3177. $q = sqlquery("SELECT * FROM bigtree_users ORDER BY $sort");
  3178. while ($f = sqlfetch($q)) {
  3179. $items[$f["id"]] = $f;
  3180. }
  3181. return $items;
  3182. }
  3183. /*
  3184. Function: getUsersPageCount
  3185. Returns the number of pages of users.
  3186. Parameters:
  3187. query - Optional query string to search against.
  3188. Returns:
  3189. The number of pages of results.
  3190. */
  3191. function getUsersPageCount($query = "") {
  3192. // If we're searching.
  3193. if ($query) {
  3194. $qparts = explode(" ",$query);
  3195. $qp = array();
  3196. foreach ($qparts as $part) {
  3197. $part = mysql_real_escape_string($part);
  3198. $qp[] = "(name LIKE '%$part%' OR email LIKE '%$part%' OR company LIKE '%$part%')";
  3199. }
  3200. $q = sqlquery("SELECT id FROM bigtree_users WHERE ".implode(" AND ",$qp));
  3201. // If we're showing all.
  3202. } else {
  3203. $q = sqlquery("SELECT id FROM bigtree_users");
  3204. }
  3205. $r = sqlrows($q);
  3206. $pages = ceil($r / $this->PerPage);
  3207. if ($pages == 0) {
  3208. $pages = 1;
  3209. }
  3210. return $pages;
  3211. }
  3212. /*
  3213. Function: growl
  3214. Sets up a growl session for the next page reload.
  3215. Parameters:
  3216. title - The section message for the growl.
  3217. message - The description of what happened.
  3218. type - The icon to draw.
  3219. */
  3220. function growl($title,$message,$type = "success") {
  3221. $_SESSION["bigtree"]["flash"] = array("message" => $message, "title" => $title, "type" => $type);
  3222. }
  3223. /*
  3224. Function: htmlClean
  3225. Removes things that shouldn't be in the <body> of an HTML document from a string.
  3226. Parameters:
  3227. html - A string of HTML
  3228. Returns:
  3229. A clean string of HTML for echoing in <body>
  3230. */
  3231. function htmlClean($html) {
  3232. return str_replace("<br></br>","<br />",strip_tags($html,"<a><abbr><address><area><article><aside><audio><b><base><bdo><blockquote><body><br><button><canvas><caption><cite><code><col><colgroup><command><datalist><dd><del><details><dfn><div><dl><dt><em><emded><fieldset><figcaption><figure><footer><form><h1><h2><h3><h4><h5><h6><header><hgroup><hr><i><iframe><img><input><ins><keygen><kbd><label><legend><li><link><map><mark><menu><meter><nav><noscript><object><ol><optgroup><option><output><p><param><pre><progress><q><rp><rt><ruby><s><samp><script><section><select><small><source><span><strong><style><sub><summary><sup><table><tbody><td><textarea><tfoot><th><thead><time><title><tr><ul><var><video><wbr>"));
  3233. }
  3234. /*
  3235. Function: ignore404
  3236. Ignores a 404 error.
  3237. Checks permissions.
  3238. Parameters:
  3239. id - The id of the reported 404.
  3240. */
  3241. function ignore404($id) {
  3242. $this->requireLevel(1);
  3243. $id = mysql_real_escape_string($id);
  3244. sqlquery("UPDATE bigtree_404s SET ignored = 'on' WHERE id = '$id'");
  3245. }
  3246. /*
  3247. Function: iplExists
  3248. Determines whether an internal page link still exists or not.
  3249. Parameters:
  3250. ipl - An internal page link
  3251. Returns:
  3252. True if it is still a valid link, otherwise false.
  3253. */
  3254. function iplExists($ipl) {
  3255. global $cms;
  3256. $ipl = explode("//",$ipl);
  3257. // See if the page it references still exists.
  3258. $nav_id = $ipl[1];
  3259. if (!sqlrows(sqlquery("SELECT id FROM bigtree_pages WHERE id = '$nav_id'"))) {
  3260. return false;
  3261. }
  3262. // Decode the commands attached to the page
  3263. $commands = json_decode(base64_decode($ipl[2]),true);
  3264. // If there are no commands, we're good.
  3265. if (!isset($commands[0]) || !$commands[0]) {
  3266. return true;
  3267. }
  3268. // If it's a hash tag link, we're also good.
  3269. if (substr($commands[0],0,1) == "#") {
  3270. return true;
  3271. }
  3272. // Get template for the navigation id to see if it's a routed template
  3273. $t = sqlfetch(sqlquery("SELECT bigtree_templates.routed FROM bigtree_templates JOIN bigtree_pages ON bigtree_templates.id = bigtree_pages.template WHERE bigtree_pages.id = '$nav_id'"));
  3274. // If we're a routed template, we're good.
  3275. if ($t["routed"]) {
  3276. return true;
  3277. }
  3278. // We may have been on a page, but there's extra routes that don't go anywhere or do anything so it's a 404.
  3279. return false;
  3280. }
  3281. /*
  3282. Function: lockCheck
  3283. Checks if a lock exists.
  3284. If a lock exists and it's currently active, stops page execution and shows the lock page.
  3285. If a lock is yours, refreshes the lock.
  3286. If there is no lock, creates one for you.
  3287. Parameters:
  3288. table - The table to check.
  3289. id - The id of the entry to check.
  3290. include - The lock page to include (relative to /core/ or /custom/)
  3291. force - Whether to force through the lock or not.
  3292. in_admin - Whether to call stop()
  3293. Returns:
  3294. Your lock id.
  3295. */
  3296. function lockCheck($table,$id,$include,$force = false,$in_admin = true) {
  3297. global $www_root,$admin_root,$admin;
  3298. $table = mysql_real_escape_string($table);
  3299. $id = mysql_real_escape_string($id);
  3300. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_locks WHERE `table` = '$table' AND item_id = '$id'"));
  3301. if ($f && $f["user"] != $this->ID && strtotime($f["last_accessed"]) > (time()-300) && !$force) {
  3302. include BigTree::path($include);
  3303. if ($in_admin) {
  3304. $this->stop();
  3305. }
  3306. return false;
  3307. }
  3308. if ($f) {
  3309. sqlquery("UPDATE bigtree_locks SET last_accessed = NOW(), user = '".$this->ID."' WHERE id = '".$f["id"]."'");
  3310. return $f["id"];
  3311. } else {
  3312. sqlquery("INSERT INTO bigtree_locks (`table`,`item_id`,`user`,`title`) VALUES ('$table','$id','".$this->ID."','Page')");
  3313. return sqlid();
  3314. }
  3315. }
  3316. /*
  3317. Function: login
  3318. Attempts to login a user to the CMS.
  3319. Parameters:
  3320. email - The email address of the user.
  3321. password - The password of the user.
  3322. stay_logged_in - Whether to set a cookie to keep the user logged in.
  3323. Returns:
  3324. false if login failed, otherwise redirects back to the page the person requested.
  3325. */
  3326. function login($email,$password,$stay_logged_in = false) {
  3327. global $path;
  3328. $f = sqlfetch(sqlquery("SELECT * FROM bigtree_users WHERE email = '".mysql_real_escape_string($email)."'"));
  3329. $phpass = new PasswordHash($config["password_depth"], TRUE);
  3330. $ok = $phpass->CheckPassword($password,$f["password"]);
  3331. if ($ok) {
  3332. if ($stay_logged_in) {
  3333. setcookie('bigtree[email]',$f["email"],time()+31*60*60*24,str_replace($GLOBALS["domain"],"",$GLOBALS["www_root"]));
  3334. setcookie('bigtree[password]',$f["password"],time()+31*60*60*24,str_replace($GLOBALS["domain"],"",$GLOBALS["www_root"]));
  3335. }
  3336. $_SESSION["bigtree"]["id"] = $f["id"];
  3337. $_SESSION["bigtree"]["email"] = $f["email"];
  3338. $_SESSION["bigtree"]["level"] = $f["level"];
  3339. $_SESSION["bigtree"]["name"] = $f["name"];
  3340. $_SESSION["bigtree"]["permissions"] = json_decode($f["permissions"],true);
  3341. if ($path[1] == "login") {
  3342. header("Location: ".$GLOBALS["admin_root"]);
  3343. } else {
  3344. header("Location: ".$GLOBALS["domain"].$_SERVER["REQUEST_URI"]);
  3345. }
  3346. die();
  3347. } else {
  3348. return false;
  3349. }
  3350. }
  3351. /*
  3352. Function: logout
  3353. Logs out of the CMS.
  3354. Destroys the user's session and unsets the login cookies, then sends the user back to the login page.
  3355. */
  3356. function logout() {
  3357. setcookie("bigtree[email]","",time()-3600,str_replace($GLOBALS["domain"],"",$GLOBALS["www_root"]));
  3358. setcookie("bigtree[password]","",time()-3600,str_replace($GLOBALS["domain"],"",$GLOBALS["www_root"]));
  3359. unset($_SESSION["bigtree"]);
  3360. header("Location: ".$GLOBALS["admin_root"]);
  3361. die();
  3362. }
  3363. /*
  3364. Function: makeIPL
  3365. Creates an internal page link out of a URL.
  3366. Paramters:
  3367. url - A URL
  3368. Returns:
  3369. An internal page link (if possible) or just the same URL (if it's not internal).
  3370. */
  3371. function makeIPL($url) {
  3372. global $cms;
  3373. $command = explode("/",rtrim(str_replace($GLOBALS["www_root"],"",$url),"/"));
  3374. list($navid,$commands) = $cms->getNavId($command);
  3375. if (!$navid) {
  3376. return str_replace(array($GLOBALS["www_root"],$GLOBALS["resource_root"]),"{wwwroot}",$url);
  3377. }
  3378. return "ipl://".$navid."//".base64_encode(json_encode($commands));
  3379. }
  3380. /*
  3381. Function: markMessageRead
  3382. Marks a message as read by the currently logged in user.
  3383. Parameters:
  3384. id - The message id.
  3385. */
  3386. function markMessageRead($id) {
  3387. $message = $this->getMessage($id);
  3388. if (!$message) {
  3389. return false;
  3390. }
  3391. $read_by = str_replace("|".$this->ID."|","",$message["read_by"])."|".$this->ID."|";
  3392. sqlquery("UPDATE bigtree_messages SET read_by = '".mysql_real_escape_string($read_by)."' WHERE id = '".$message["id"]."'");
  3393. return true;
  3394. }
  3395. /*
  3396. Function: moduleActionExists
  3397. Checks to see if an action exists for a given route and module.
  3398. Parameters:
  3399. module - The module to check.
  3400. route - The route of the action to check.
  3401. Returns:
  3402. true if an action exists, otherwise false.
  3403. */
  3404. function moduleActionExists($module,$route) {
  3405. $module = mysql_real_escape_string($module);
  3406. $route = mysql_real_escape_string($route);
  3407. $f = sqlfetch(sqlquery("SELECT id FROM bigtree_module_actions WHERE module = '$module' AND route = '$route'"));
  3408. if ($f) {
  3409. return true;
  3410. }
  3411. return false;
  3412. }
  3413. /*
  3414. Function: pingSearchEngines
  3415. Sends the latest sitemap.xml out to search engine ping services if enabled in settings.
  3416. */
  3417. function pingSearchEngines() {
  3418. global $cms;
  3419. if ($cms->getSetting("ping-search-engines") == "on") {
  3420. $google = file_get_contents("http://www.google.com/webmasters/tools/ping?sitemap=".urlencode($GLOBALS["www_root"]."sitemap.xml"));
  3421. $ask = file_get_contents("http://submissions.ask.com/ping?sitemap=".urlencode($GLOBALS["www_root"]."sitemap.xml"));
  3422. $yahoo = file_get_contents("http://search.yahooapis.com/SiteExplorerService/V1/ping?sitemap=".urlencode($GLOBALS["www_root"]."sitemap.xml"));
  3423. $bing = file_get_contents("http://www.bing.com/webmaster/ping.aspx?siteMap=".urlencode($GLOBALS["www_root"]."sitemap.xml"));
  3424. }
  3425. }
  3426. /*
  3427. Function: refreshLock
  3428. Refreshes a lock.
  3429. Paramters:
  3430. id - The id of the lock.
  3431. */
  3432. function refreshLock($id) {
  3433. $id = mysql_real_escape_string($id);
  3434. sqlquery("UPDATE bigtree_locks SET last_accessed = NOW() WHERE id = '$id' AND user = '".$this->ID."'");
  3435. }
  3436. /*
  3437. Function: requireAccess
  3438. Checks the logged in user's access to a given module.
  3439. Throws a permission denied page and stops page execution if the user doesn't have access.
  3440. Parameters:
  3441. module - The id of the module to check access to.
  3442. Returns:
  3443. The permission level of the logged in user.
  3444. */
  3445. function requireAccess($module) {
  3446. global $cms,$admin_root,$css,$js,$site;
  3447. if ($this->Level > 0)
  3448. return "p";
  3449. if (!isset($this->Permissions[$module]) || $this->Permissions[$module] == "") {
  3450. ob_clean();
  3451. include BigTree::path("admin/pages/_denied.php");
  3452. $content = ob_get_clean();
  3453. include BigTree::path("admin/layouts/default.php");
  3454. die();
  3455. }
  3456. return $this->Permissions[$module];
  3457. }
  3458. /*
  3459. Function: requireLevel
  3460. Requires the logged in user to have a certain access level to continue.
  3461. Throws a permission denied page and stops page execution if the user doesn't have access.
  3462. Parameters:
  3463. level - An access level (0 being normal user, 1 being administrator, 2 being developer)
  3464. */
  3465. function requireLevel($level) {
  3466. global $admin,$cms,$admin_root,$css,$js,$site;
  3467. if (!isset($this->Level) || $this->Level < $level) {
  3468. ob_clean();
  3469. include BigTree::path("admin/pages/_denied.php");
  3470. $content = ob_get_clean();
  3471. include BigTree::path("admin/layouts/default.php");
  3472. die();
  3473. }
  3474. }
  3475. /*
  3476. Function: requirePublisher
  3477. Checks the logged in user's access to a given module to make sure they are a publisher.
  3478. Throws a permission denied page and stops page execution if the user doesn't have access.
  3479. Parameters:
  3480. module - The id of the module to check access to.
  3481. Returns:
  3482. The permission level of the logged in user.
  3483. */
  3484. function requirePublisher($module) {
  3485. global $cms,$admin_root,$css,$js,$site;
  3486. if ($this->Level > 0)
  3487. return true;
  3488. if ($this->Permissions[$module] != "p") {
  3489. ob_clean();
  3490. include BigTree::path("admin/pages/_denied.php");
  3491. $content = ob_get_clean();
  3492. include BigTree::path("admin/layouts/default.php");
  3493. die();
  3494. }
  3495. return true;
  3496. }
  3497. /*
  3498. Function: saveCurrentPageRevision
  3499. Saves the currently published page as a revision.
  3500. Parameters:
  3501. page - The page id.
  3502. description - The revision description.
  3503. Returns:
  3504. The new revision id.
  3505. */
  3506. function saveCurrentPageRevision($page,$description) {
  3507. $page = mysql_real_escape_string($page);
  3508. $description = mysql_real_escape_string($description);
  3509. // Get the current page.
  3510. $current = sqlfetch(sqlquery("SELECT * FROM bigtree_pages WHERE id = '$page'"));
  3511. foreach ($current as $key => $val) {
  3512. $$key = mysql_real_escape_string($val);
  3513. }
  3514. // Copy it to the saved versions
  3515. sqlquery("INSERT INTO bigtree_page_revisions (`page`,`title`,`meta_keywords`,`meta_description`,`template`,`external`,`new_window`,`resources`,`callouts`,`author`,`updated_at`,`saved`,`saved_description`) VALUES ('$page','$title','$meta_keywords','$meta_description','$template','$external','$new_window','$resources','$callouts','$last_edited_by','$updated_at','on','$description')");
  3516. return sqlid();
  3517. }
  3518. /*
  3519. Function: search404s
  3520. Searches 404s, returns results.
  3521. Parameters:
  3522. type - The type of results (301, 404, or ignored).
  3523. query - The search query.
  3524. Returns:
  3525. An array of entries from bigtree_404s.
  3526. */
  3527. function search404s($type,$query = "") {
  3528. $items = array();
  3529. if ($query) {
  3530. $s = mysql_real_escape_string($query);
  3531. if ($type == "301") {
  3532. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored = '' AND (broken_url LIKE '%$s%' OR redirect_url LIKE '%$s%') AND redirect_url != '' ORDER BY requests DESC LIMIT 50");
  3533. } elseif ($type == "ignored") {
  3534. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored != '' AND (broken_url LIKE '%$s%' OR redirect_url LIKE '%$s%') ORDER BY requests DESC LIMIT 50");
  3535. } else {
  3536. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored = '' AND broken_url LIKE '%$s%' AND redirect_url = '' ORDER BY requests DESC LIMIT 50");
  3537. }
  3538. } else {
  3539. if ($type == "301") {
  3540. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored = '' AND redirect_url != '' ORDER BY requests DESC LIMIT 50");
  3541. } elseif ($type == "ignored") {
  3542. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored != '' ORDER BY requests DESC LIMIT 50");
  3543. } else {
  3544. $q = sqlquery("SELECT * FROM bigtree_404s WHERE ignored = '' AND redirect_url = '' ORDER BY requests DESC LIMIT 50");
  3545. }
  3546. }
  3547. while ($f = sqlfetch($q)) {
  3548. $items[] = $f;
  3549. }
  3550. return $items;
  3551. }
  3552. /*
  3553. Function: searchPages
  3554. Searches for pages.
  3555. Parameters:
  3556. query - Query string to search against.
  3557. fields - Fields to search.
  3558. max - Maximum number of results to return.
  3559. Returns:
  3560. An array of pages.
  3561. */
  3562. function searchPages($query,$fields = array("nav_title"),$max = 10) {
  3563. $results = array();
  3564. $terms = explode(" ",$query);
  3565. foreach ($terms as $term) {
  3566. $term = mysql_real_escape_string(strtolower($term));
  3567. $or_parts = array();
  3568. foreach ($fields as $field) {
  3569. $or_parts[] = "LOWER(`$field`) LIKE '%$term%'";
  3570. }
  3571. $qpart[] = "(".implode(" OR ",$or_parts).")";
  3572. }
  3573. $q = sqlquery("SELECT * FROM bigtree_pages WHERE ".implode(" AND ",$qpart)." ORDER BY nav_title LIMIT $max");
  3574. while ($f = sqlfetch($q)) {
  3575. $results[] = $f;
  3576. }
  3577. return $results;
  3578. }
  3579. /*
  3580. Function: searchResources
  3581. Returns a list of folders and files that match the given query string.
  3582. Parameters:
  3583. query - A string of text to search folders' and files' names to.
  3584. sort - The column to sort the files on (default: date DESC).
  3585. Returns:
  3586. An array of two arrays - folders and files - with permission levels.
  3587. */
  3588. function searchResources($query, $sort = "date DESC") {
  3589. $query = mysql_real_escape_string($query);
  3590. $folders = array();
  3591. $resources = array();
  3592. $permission_cache = array();
  3593. $q = sqlquery("SELECT * FROM bigtree_resource_folders WHERE name LIKE '%$query%' ORDER BY name");
  3594. while ($f = sqlfetch($q)) {
  3595. $f["permission"] = $this->getResourceFolderPermission($f);
  3596. // We're going to cache the folder permissions so we don't have to fetch them a bunch of times if many files have the same folder.
  3597. $permission_cache[$f["id"]] = $f["permission"];
  3598. $folders[] = $f;
  3599. }
  3600. $q = sqlquery("SELECT * FROM bigtree_resources WHERE name LIKE '%$query%' ORDER BY $sort");
  3601. while ($f = sqlfetch($q)) {
  3602. // If we've already got the permission cahced, use it. Otherwise, fetch it and cache it.
  3603. if ($permission_cache[$f["folder"]]) {
  3604. $f["permission"] = $permission_cache[$f["folder"]];
  3605. } else {
  3606. $f["permission"] = $this->getResourceFolderPermission($f["folder"]);
  3607. $permission_cache[$f["folder"]] = $f["permission"];
  3608. }
  3609. $resources[] = $f;
  3610. }
  3611. return array("folders" => $folders, "resources" => $resources);
  3612. }
  3613. /*
  3614. Function: searchTags
  3615. Finds existing tags that are similar.
  3616. Parameters:
  3617. tag - A tag to find similar tags for.
  3618. Returns:
  3619. An array of up to 8 similar tags.
  3620. */
  3621. function searchTags($tag) {
  3622. $tags = array();
  3623. $meta = metaphone($tag);
  3624. $close_tags = array();
  3625. $dist = array();
  3626. $q = sqlquery("SELECT * FROM bigtree_tags");
  3627. while ($f = sqlfetch($q)) {
  3628. $distance = levenshtein($f["metaphone"],$meta);
  3629. if ($distance < 2) {
  3630. $tags[] = $f["tag"];
  3631. $dist[] = $distance;
  3632. }
  3633. }
  3634. array_multisort($dist,SORT_ASC,$tags);
  3635. if (count($tags) > 8) {
  3636. $tags = array_slice($tags,0,8);
  3637. }
  3638. return $tags;
  3639. }
  3640. /*
  3641. Function: set404Redirect
  3642. Sets the redirect address for a 404.
  3643. Checks permissions.
  3644. Parameters:
  3645. id - The id of the 404.
  3646. url - The redirect URL.
  3647. */
  3648. function set404Redirect($id,$url) {
  3649. $this->requireLevel(1);
  3650. $id = mysql_real_escape_string($id);
  3651. $url = mysql_real_escape_string($url);
  3652. sqlquery("UPDATE bigtree_404s SET redirect_url = '$url' WHERE id = '$id'");
  3653. }
  3654. /*
  3655. Function: setCalloutPosition
  3656. Sets the position of a callout.
  3657. Parameters:
  3658. id - The id of the callout.
  3659. position - The position to set.
  3660. */
  3661. function setCalloutPosition($id,$position) {
  3662. $id = mysql_real_escape_string($id);
  3663. $position = mysql_real_escape_string($position);
  3664. sqlquery("UPDATE bigtree_callouts SET position = '$position' WHERE id = '$id'");
  3665. }
  3666. /*
  3667. Function: setModuleActionPosition
  3668. Sets the position of a module action.
  3669. Parameters:
  3670. id - The id of the module action.
  3671. position - The position to set.
  3672. */
  3673. function setModuleActionPosition($id,$position) {
  3674. $id = mysql_real_escape_string($id);
  3675. $position = mysql_real_escape_string($position);
  3676. sqlquery("UPDATE bigtree_module_actions SET position = '$position' WHERE id = '$id'");
  3677. }
  3678. /*
  3679. Function: setModuleGroupPosition
  3680. Sets the position of a module group.
  3681. Parameters:
  3682. id - The id of the module group.
  3683. position - The position to set.
  3684. */
  3685. function setModuleGroupPosition($id,$position) {
  3686. $id = mysql_real_escape_string($id);
  3687. $position = mysql_real_escape_string($position);
  3688. sqlquery("UPDATE bigtree_module_groups SET position = '$position' WHERE id = '$id'");
  3689. }
  3690. /*
  3691. Function: setModulePosition
  3692. Sets the position of a module.
  3693. Parameters:
  3694. id - The id of the module.
  3695. position - The position to set.
  3696. */
  3697. function setModulePosition($id,$position) {
  3698. $id = mysql_real_escape_string($id);
  3699. $position = mysql_real_escape_string($position);
  3700. sqlquery("UPDATE bigtree_modules SET position = '$position' WHERE id = '$id'");
  3701. }
  3702. /*
  3703. Function: setPagePosition
  3704. Sets the position of a page.
  3705. Parameters:
  3706. id - The id of the page.
  3707. position - The position to set.
  3708. */
  3709. function setPagePosition($id,$position) {
  3710. $id = mysql_real_escape_string($id);
  3711. $position = mysql_real_escape_string($position);
  3712. sqlquery("UPDATE bigtree_pages SET position = '$position' WHERE id = '$id'");
  3713. }
  3714. /*
  3715. Function: setPasswordHashForUser
  3716. Creates a change password hash for a user.
  3717. Parameters:
  3718. user - A user entry.
  3719. Returns:
  3720. A change password hash.
  3721. */
  3722. function setPasswordHashForUser($user) {
  3723. $hash = md5(microtime().$user["password"]);
  3724. sqlquery("UPDATE bigtree_users SET change_password_hash = '$hash' WHERE id = '".$user["id"]."'");
  3725. }
  3726. /*
  3727. Function: setTemplatePosition
  3728. Sets the position of a template.
  3729. Parameters:
  3730. id - The id of the template.
  3731. position - The position to set.
  3732. */
  3733. function setTemplatePosition($id,$position) {
  3734. $id = mysql_real_escape_string($id);
  3735. $position = mysql_real_escape_string($position);
  3736. sqlquery("UPDATE bigtree_templates SET position = '$position' WHERE id = '$id'");
  3737. }
  3738. /*
  3739. Function: settingExists
  3740. Determines whether a setting exists for a given id.
  3741. Parameters:
  3742. id - The setting id to check for.
  3743. Returns:
  3744. 1 if the setting exists, otherwise 0.
  3745. */
  3746. function settingExists($id) {
  3747. return sqlrows(sqlquery("SELECT id FROM bigtree_settings WHERE id = '".mysql_real_escape_string($id)."'"));
  3748. }
  3749. /*
  3750. Function: stop
  3751. Stops processing of the Admin area and shows a message in the default layout.
  3752. Parameters:
  3753. message - Content to show (error, permission denied, etc)
  3754. */
  3755. function stop($message = "") {
  3756. global $cms,$admin,$www_root,$admin_root,$site,$breadcrumb;
  3757. echo $message;
  3758. $content = ob_get_clean();
  3759. include BigTree::path("admin/layouts/default.php");
  3760. die();
  3761. }
  3762. /*
  3763. Function: submitPageChange
  3764. Adds a pending change to the bigtree_pending_changes table for the page.
  3765. Determines what has changed and only stores the changed fields.
  3766. Does not check permissions.
  3767. Parameters:
  3768. page - The page id or pending page id (prefixed with a "p")
  3769. changes - An array of changes
  3770. */
  3771. function submitPageChange($page,$changes) {
  3772. global $cms;
  3773. if ($page[0] == "p") {
  3774. // It's still pending...
  3775. $existing_page = array();
  3776. $pending = true;
  3777. $type = "NEW";
  3778. } else {
  3779. // It's an existing page
  3780. $pending = false;
  3781. $existing_page = $cms->getPage($page);
  3782. $type = "EDIT";
  3783. }
  3784. $template = $existing_page["template"];
  3785. if (!$pending) {
  3786. $existing_pending_change = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE `table` = 'bigtree_pages' AND item_id = '$page'"));
  3787. } else {
  3788. $existing_pending_change = sqlfetch(sqlquery("SELECT * FROM bigtree_pending_changes WHERE id = '".substr($page,1)."'"));
  3789. }
  3790. // Save tags separately
  3791. $tags = mysql_real_escape_string(json_encode($changes["_tags"]));
  3792. unset($changes["_tags"]);
  3793. // If there's already a change in the queue, update it with this latest info.
  3794. if ($existing_pending_change) {
  3795. $comments = json_decode($f["comments"],true);
  3796. if ($existing_pending_change["user"] == $this->ID) {
  3797. $comments[] = array(
  3798. "user" => "BigTree",
  3799. "date" => date("F j, Y @ g:ia"),
  3800. "comment" => "A new revision has been made."
  3801. );
  3802. } else {
  3803. $user = $this->getUser($this->ID);
  3804. $comments[] = array(
  3805. "user" => "BigTree",
  3806. "date" => date("F j, Y @ g:ia"),
  3807. "comment" => "A new revision has been made. Owner switched to ".$user["name"]."."
  3808. );
  3809. }
  3810. // If this is a pending change, just replace all the changes
  3811. if ($pending) {
  3812. $changes = mysql_real_escape_string(json_encode($changes));
  3813. // Otherwise, we need to check what's changed.
  3814. } else {
  3815. $original_changes = json_decode($existing_pending_change["changes"],true);
  3816. if (isset($original_changes["template"])) {
  3817. $template = $original_changes["template"];
  3818. }
  3819. if (isset($changes["external"])) {
  3820. $changes["external"] = $this->makeIPL($changes["external"]);
  3821. }
  3822. foreach ($changes as $key => $val) {
  3823. if ($val != $existing_page[$key] && isset($existing_page[$key])) {
  3824. $original_changes[$key] = $val;
  3825. }
  3826. }
  3827. $changes = mysql_real_escape_string(json_encode($original_changes));
  3828. }
  3829. $comments = mysql_real_escape_string(json_encode($comments));
  3830. sqlquery("UPDATE bigtree_pending_changes SET comments = '$comments', changes = '$changes', tags_changes = '$tags', date = NOW(), user = '".$this->ID."', type = '$type' WHERE id = '".$existing_pending_change["id"]."'");
  3831. $this->track("bigtree_pages",$page,"updated-draft");
  3832. // We're submitting a change to a presently published page with no pending changes.
  3833. } else {
  3834. $original_changes = array();
  3835. foreach ($changes as $key => $val) {
  3836. if ($key == "external") {
  3837. $val = $this->makeIPL($val);
  3838. }
  3839. if (isset($existing_page[$key]) && $val != $existing_page[$key]) {
  3840. $original_changes[$key] = $val;
  3841. }
  3842. }
  3843. $changes = mysql_real_escape_string(json_encode($original_changes));
  3844. if ($type == "DELETE") {
  3845. sqlquery("INSERT INTO bigtree_pending_changes (`user`,`date`,`table`,`item_id`,`changes`,`type`,`title`) VALUES ('".$this->ID."',NOW(),'bigtree_pages','$page','$changes','DELETE','Page Deletion Pending')");
  3846. } else {
  3847. sqlquery("INSERT INTO bigtree_pending_changes (`user`,`date`,`table`,`item_id`,`changes`,`tags_changes`,`type`,`title`) VALUES ('".$this->ID."',NOW(),'bigtree_pages','$page','$changes','$tags','EDIT','Page Change Pending')");
  3848. }
  3849. $this->track("bigtree_pages",$page,"saved-draft");
  3850. }
  3851. return sqlid();
  3852. }
  3853. /*
  3854. Function: track
  3855. Logs a user's actions to the audit trail table.
  3856. Parameters:
  3857. table - The table affected by the user.
  3858. entry - The primary key of the entry affected by the user.
  3859. type - The action taken by the user (delete, edit, create, etc.)
  3860. */
  3861. function track($table,$entry,$type) {
  3862. $table = mysql_real_escape_string($table);
  3863. $entry = mysql_real_escape_string($entry);
  3864. $type = mysql_real_escape_string($type);
  3865. sqlquery("INSERT INTO bigtree_audit_trail (`table`,`user`,`entry`,`date`,`type`) VALUES ('$table','".$this->ID."','$entry',NOW(),'$type')");
  3866. }
  3867. /*
  3868. Function: unarchivePage
  3869. Unarchives a page and all its children that inherited archived status.
  3870. Checks permissions.
  3871. Parameters:
  3872. page - The page id or page entry.
  3873. Returns:
  3874. true if successful. false if permission was denied.
  3875. */
  3876. function unarchivePage($page) {
  3877. global $cms;
  3878. if (is_array($page)) {
  3879. $page = mysql_real_escape_string($page["id"]);
  3880. } else {
  3881. $page = mysql_real_escape_string($page);
  3882. }
  3883. $access = $this->getPageAccessLevel($page);
  3884. if ($access == "p" && $this->canModifyChildren($cms->getPage($page))) {
  3885. sqlquery("UPDATE bigtree_pages SET archived = '' WHERE id = '$page'");
  3886. $this->track("bigtree_pages",$page,"unarchived");
  3887. $this->unarchivePageChildren($page);
  3888. return true;
  3889. }
  3890. return false;
  3891. }
  3892. /*
  3893. Function: unarchivePageChildren
  3894. Unarchives a page's children that have the archived_inherited status.
  3895. Does not checks permissions.
  3896. Parameters:
  3897. id - The parent page id.
  3898. */
  3899. function unarchivePageChildren($id) {
  3900. $q = sqlquery("SELECT * FROM bigtree_pages WHERE parent = '$id'");
  3901. while ($f = sqlfetch($q)) {
  3902. if ($f["archived_inherited"]) {
  3903. sqlquery("UPDATE bigtree_pages SET archived = '', archived_inherited = '' WHERE id = '".$f["id"]."'");
  3904. $this->track("bigtree_pages",$f["id"],"unarchived");
  3905. $this->archivePageChildren($f["id"]);
  3906. }
  3907. }
  3908. }
  3909. /*
  3910. Function: ungrowl
  3911. Destroys the growl session.
  3912. */
  3913. function ungrowl() {
  3914. unset($_SESSION["bigtree"]["flash"]);
  3915. }
  3916. /*
  3917. Function: urlExists
  3918. Attempts to connect to a URL using cURL.
  3919. Parameters:
  3920. url - The URL to connect to.
  3921. Returns:
  3922. true if it can connect, false if connection failed.
  3923. */
  3924. function urlExists($url) {
  3925. $handle = curl_init($url);
  3926. if ($handle === false) {
  3927. return false;
  3928. }
  3929. curl_setopt($handle, CURLOPT_HEADER, false);
  3930. curl_setopt($handle, CURLOPT_FAILONERROR, true);
  3931. // Request as Firefox so that servers don't reject us for not having headers.
  3932. curl_setopt($handle, CURLOPT_HTTPHEADER, Array("User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.15) Gecko/20080623 Firefox/2.0.0.15") );
  3933. curl_setopt($handle, CURLOPT_NOBODY, true);
  3934. curl_setopt($handle, CURLOPT_RETURNTRANSFER, false);
  3935. $connectable = curl_exec($handle);
  3936. curl_close($handle);
  3937. return $connectable;
  3938. }
  3939. /*
  3940. Function: unCache
  3941. Removes the cached copy of a given page.
  3942. Parameters:
  3943. page - Either a page id or a page entry.
  3944. */
  3945. function unCache($page) {
  3946. global $cms;
  3947. if (is_array($page)) {
  3948. $file = $GLOBALS["server_root"]."cache/".base64_encode($page["path"]."/");
  3949. } else {
  3950. $file = $GLOBALS["server_root"]."cache/".base64_encode(str_replace($GLOBALS["www_root"],"",$cms->getLink($page)));
  3951. }
  3952. if (file_exists($file)) {
  3953. @unlink($file);
  3954. }
  3955. }
  3956. /*
  3957. Function: unignore404
  3958. Unignores a 404.
  3959. Checks permissions.
  3960. Parameters:
  3961. id - The id of the 404.
  3962. */
  3963. function unignore404($id) {
  3964. $this->requireLevel(1);
  3965. $id = mysql_real_escape_string($id);
  3966. sqlquery("UPDATE bigtree_404s SET ignored = '' WHERE id = '$id'");
  3967. }
  3968. /*
  3969. Function: unlock
  3970. Removes a lock from a table entry.
  3971. Parameters:
  3972. table - The table the entry is in.
  3973. id - The id of the entry.
  3974. */
  3975. function unlock($table,$id) {
  3976. sqlquery("DELETE FROM bigtree_locks WHERE `table` = '".mysql_real_escape_string($table)."' AND item_id = '".mysql_real_escape_string($id)."'");
  3977. }
  3978. /*
  3979. Function: updateCallout
  3980. Updates a callout.
  3981. Parameters:
  3982. id - The id of the callout to update.
  3983. name - The name.
  3984. description - The description.
  3985. level - The access level (0 for all users, 1 for administrators, 2 for developers)
  3986. resources - An array of resources.
  3987. */
  3988. function updateCallout($id,$name,$description,$level,$resources) {
  3989. $r = array();
  3990. foreach ($resources as $resource) {
  3991. if ($resource["id"] && $resource["id"] != "type") {
  3992. $options = json_decode($resource["options"],true);
  3993. foreach ($options as $key => $val) {
  3994. if ($key != "name" && $key != "id" && $key != "type")
  3995. $resource[$key] = $val;
  3996. }
  3997. $resource["id"] = htmlspecialchars($resource["id"]);
  3998. $resource["name"] = htmlspecialchars($resource["name"]);
  3999. $resource["subtitle"] = htmlspecialchars($resource["subtitle"]);
  4000. unset($resource["options"]);
  4001. $r[] = $resource;
  4002. }
  4003. }
  4004. $id = mysql_real_escape_string($id);
  4005. $name = mysql_real_escape_string(htmlspecialchars($name));
  4006. $description = mysql_real_escape_string(htmlspecialchars($description));
  4007. $level = mysql_real_escape_string($level);
  4008. $resources = mysql_real_escape_string(json_encode($r));
  4009. sqlquery("UPDATE bigtree_callouts SET resources = '$resources', name = '$name', description = '$description', level = '$level' WHERE id = '$id'");
  4010. }
  4011. /*
  4012. Function: updateChildPagePaths
  4013. Updates the paths for pages who are descendants of a given page to reflect the page's new route.
  4014. Also sets route history if the page has changed paths.
  4015. Parameters:
  4016. page - The page id.
  4017. */
  4018. function updateChildPagePaths($page) {
  4019. global $cms;
  4020. $page = mysql_real_escape_string($page);
  4021. $q = sqlquery("SELECT * FROM bigtree_pages WHERE parent = '$page'");
  4022. while ($f = sqlfetch($q)) {
  4023. $oldpath = $f["path"];
  4024. $path = $this->getFullNavigationPath($f["id"]);
  4025. if ($oldpath != $path) {
  4026. sqlquery("DELETE FROM bigtree_route_history WHERE old_route = '$path' OR old_route = '$oldpath'");
  4027. sqlquery("INSERT INTO bigtree_route_history (`old_route`,`new_route`) VALUES ('$oldpath','$path')");
  4028. sqlquery("UPDATE bigtree_pages SET path = '$path' WHERE id = '".$f["id"]."'");
  4029. $this->updateChildPagePaths($f["id"]);
  4030. }
  4031. }
  4032. }
  4033. /*
  4034. Function: updateFeed
  4035. Updates a feed.
  4036. Parameters:
  4037. id - The id of the feed to update.
  4038. name - The name.
  4039. description - The description.
  4040. table - The data table.
  4041. type - The feed type.
  4042. options - The feed type options.
  4043. fields - The fields.
  4044. */
  4045. function updateFeed($id,$name,$description,$table,$type,$options,$fields) {
  4046. $options = json_decode($options,true);
  4047. foreach ($options as &$option) {
  4048. $option = str_replace($www_root,"{wwwroot}",$option);
  4049. }
  4050. // Fix stuff up for the db.
  4051. $id = mysql_real_escape_string($id);
  4052. $name = mysql_real_escape_string(htmlspecialchars($name));
  4053. $description = mysql_real_escape_string(htmlspecialchars($description));
  4054. $table = mysql_real_escape_string($table);
  4055. $type = mysql_real_escape_string($type);
  4056. $options = mysql_real_escape_string(json_encode($options));
  4057. $fields = mysql_real_escape_string(json_encode($fields));
  4058. sqlquery("UPDATE bigtree_feeds SET name = '$name', description = '$description', `table` = '$table', type = '$type', fields = '$fields', options = '$options' WHERE id = '$id'");
  4059. }
  4060. /*
  4061. Function: updateFieldType
  4062. Updates a field type.
  4063. Parameters:
  4064. id - The id of the field type.
  4065. name - The name.
  4066. pages - Whether it can be used as a page resource or not ("on" is yes)
  4067. modules - Whether it can be used as a module resource or not ("on" is yes)
  4068. callouts - Whether it can be used as a callout resource or not ("on" is yes)
  4069. */
  4070. function updateFieldType($id,$name,$pages,$modules,$callouts) {
  4071. $id = mysql_real_escape_string($id);
  4072. $name = mysql_real_escape_string(htmlspecialchars($name));
  4073. $pages = mysql_real_escape_string($pages);
  4074. $modules = mysql_real_escape_string($modules);
  4075. $callouts = mysql_real_escape_string($callouts);
  4076. sqlquery("UPDATE bigtree_field_types SET name = '$name', pages = '$pages', modules = '$modules', callouts = '$callouts' WHERE id = '$id'");
  4077. }
  4078. /*
  4079. Function: updateModule
  4080. Updates a module.
  4081. Parameters:
  4082. id - The id of the module to update.
  4083. name - The name of the module.
  4084. group - The group for the module.
  4085. class - The module class to create.
  4086. permissions - The group-based permissions.
  4087. */
  4088. function updateModule($id,$name,$group,$class,$permissions) {
  4089. $id = mysql_real_escape_string($id);
  4090. $name = mysql_real_escape_string(htmlspecialchars($name));
  4091. $group = mysql_real_escape_string($group);
  4092. $class = mysql_real_escape_string($class);
  4093. $permissions = mysql_real_escape_string(json_encode($permissions));
  4094. sqlquery("UPDATE bigtree_modules SET name = '$name', `group` = '$group', class = '$class', `gbp` = '$permissions' WHERE id = '$id'");
  4095. // Remove cached class list.
  4096. unlink($GLOBALS["server_root"]."cache/module-class-list.btc");
  4097. }
  4098. /*
  4099. Function: updateModuleAction
  4100. Updates a module action.
  4101. Parameters:
  4102. id - The id of the module action to update.
  4103. name - The name of the action.
  4104. route - The action route.
  4105. in_nav - Whether the action is in the navigation.
  4106. icon - The icon class for the action.
  4107. */
  4108. function updateModuleAction($id,$name,$route,$in_nav,$icon) {
  4109. $id = mysql_real_escape_string($id);
  4110. $route = mysql_real_escape_string(htmlspecialchars($route));
  4111. $in_nav = mysql_real_escape_string($in_nav);
  4112. $icon = mysql_real_escape_string($icon);
  4113. $name = mysql_real_escape_string(htmlspecialchars($name));
  4114. $item = $this->getModuleAction($id);
  4115. $oroute = $route;
  4116. $x = 2;
  4117. while ($f = sqlfetch(sqlquery("SELECT * FROM bigtree_module_actions WHERE module = '".$item["module"]."' AND route = '$route' AND id != '$id'"))) {
  4118. $route = $oroute."-".$x;
  4119. $x++;
  4120. }
  4121. sqlquery("UPDATE bigtree_module_actions SET name = '$name', route = '$route', class = '$icon', in_nav = '$in_nav' WHERE id = '$id'");
  4122. }
  4123. /*
  4124. Function: updateModuleForm
  4125. Updates a module form.
  4126. Parameters:
  4127. id - The id of the form.
  4128. title - The title of the form.
  4129. table - The table for the form data.
  4130. fields - The form fields.
  4131. javascript - Optional Javascript file to include in the form.
  4132. css - Optional CSS file to include in the form.
  4133. callback - Optional callback function to run after the form processes.
  4134. default_position - Default position for entries to the form (if the view is positioned).
  4135. suffix - Optional add/edit suffix for the form.
  4136. */
  4137. function updateModuleForm($id,$title,$table,$fields,$javascript = "",$css = "",$callback = "",$default_position = "",$suffix = "") {
  4138. $id = mysql_real_escape_string($id);
  4139. $title = mysql_real_escape_string(htmlspecialchars($title));
  4140. $table = mysql_real_escape_string($table);
  4141. $fields = mysql_real_escape_string(json_encode($fields));
  4142. $javascript - mysql_real_escape_string(htmlspecialchars($javascript));
  4143. $css - mysql_real_escape_string(htmlspecialchars($css));
  4144. $callback - mysql_real_escape_string($callback);
  4145. $default_position - mysql_real_escape_string($default_position);
  4146. sqlquery("UPDATE bigtree_module_forms SET title = '$title', `table` = '$table', fields = '$fields', javascript = '$javascript', css = '$css', callback = '$callback', default_position = '$default_position' WHERE id = '$id'");
  4147. $oroute = str_replace(array("add-","edit-","add","edit"),"",$action["route"]);
  4148. if ($suffix != $oroute) {
  4149. sqlquery("UPDATE bigtree_module_actions SET route = 'add-$suffix' WHERE module = '".$action["module"]."' AND route = 'add-$oroute'");
  4150. sqlquery("UPDATE bigtree_module_actions SET route = 'edit-$suffix' WHERE module = '".$action["module"]."' AND route = 'edit-$oroute'");
  4151. }
  4152. }
  4153. /*
  4154. Function: updateModuleGroup
  4155. Updates a module group's name.
  4156. Parameters:
  4157. id - The id of the module group to update.
  4158. name - The name of the module group.
  4159. */
  4160. function updateModuleGroup($id,$name,$in_nav) {
  4161. global $cms;
  4162. $id = mysql_real_escape_string($id);
  4163. $name = mysql_real_escape_string(htmlspecialchars($name));
  4164. // Get a unique route
  4165. $x = 2;
  4166. $route = $cms->urlify($name);
  4167. $oroute = $route;
  4168. $q = sqlquery("SELECT * FROM bigtree_module_groups WHERE route = '" . mysql_real_escape_string($route) . "'");
  4169. while ($g = sqlfetch($q)) {
  4170. if ($g["id"] != $id) {
  4171. $route = $oroute."-".$x;
  4172. $x++;
  4173. }
  4174. }
  4175. // Just to be safe
  4176. $route = mysql_real_escape_string($route);
  4177. sqlquery("UPDATE bigtree_module_groups SET name = '$name', route = '$route', in_nav = '$in_nav' WHERE id = '$id'");
  4178. }
  4179. /*
  4180. Function: updateModuleView
  4181. Updates a module view.
  4182. Parameters:
  4183. id - The view id.
  4184. title - View title.
  4185. description - Description.
  4186. table - Data table.
  4187. type - View type.
  4188. options - View options array.
  4189. fields - Field array.
  4190. actions - Actions array.
  4191. suffix - Add/Edit suffix.
  4192. uncached - Don't cache the view.
  4193. preview_url - Optional preview URL.
  4194. Returns:
  4195. The id for view.
  4196. */
  4197. function updateModuleView($id,$title,$description,$table,$type,$options,$fields,$actions,$suffix,$uncached = "",$preview_url = "") {
  4198. $id = mysql_real_escape_string($id);
  4199. $title = mysql_real_escape_string(htmlspecialchars($title));
  4200. $description = mysql_real_escape_string(htmlspecialchars($description));
  4201. $table = mysql_real_escape_string($table);
  4202. $type = mysql_real_escape_string($type);
  4203. $options = mysql_real_escape_string(json_encode($options));
  4204. $fields = mysql_real_escape_string(json_encode($fields));
  4205. $actions = mysql_real_escape_string(json_encode($actions));
  4206. $suffix = mysql_real_escape_string($suffix);
  4207. $uncached = mysql_real_escape_string($uncached);
  4208. $preview_url = mysql_real_escape_string(htmlspecialchars($preview_url));
  4209. sqlquery("UPDATE bigtree_module_views SET title = '$title', description = '$description', `table` = '$table', type = '$type', options = '$options', fields = '$fields', actions = '$actions', suffix = '$suffix', uncached = '$uncached', preview_url = '$preview_url' WHERE id = '$id'");
  4210. }
  4211. /*
  4212. Function: updateModuleViewFields
  4213. Updates the fields for a module view.
  4214. Paramters:
  4215. view - The view id.
  4216. fields - A fields array.
  4217. */
  4218. function updateModuleViewFields($view,$fields) {
  4219. $view = mysql_real_escape_string($view);
  4220. $fields = mysql_real_escape_string(json_encode($fields));
  4221. sqlquery("UPDATE bigtree_module_views SET `fields` = '$fields' WHERE id = '$view'");
  4222. }
  4223. /*
  4224. Function: updatePage
  4225. Updates a page.
  4226. Does not check permissions.
  4227. Paramters:
  4228. page - The page id to update.
  4229. data - The page data to update with.
  4230. */
  4231. function updatePage($page,$data) {
  4232. global $cms;
  4233. $page = mysql_real_escape_string($page);
  4234. // Save the existing copy as a draft, remove drafts for this page that are one month old or older.
  4235. sqlquery("DELETE FROM bigtree_page_revisions WHERE page = '$page' AND updated_at < '".date("Y-m-d",strtotime("-31 days"))."' AND saved != 'on'");
  4236. // Get the current copy
  4237. $current = sqlfetch(sqlquery("SELECT * FROM bigtree_pages WHERE id = '$page'"));
  4238. foreach ($current as $key => $val) {
  4239. $$key = mysql_real_escape_string($val);
  4240. }
  4241. // Copy it to the saved versions
  4242. sqlquery("INSERT INTO bigtree_page_revisions (`page`,`title`,`meta_keywords`,`meta_description`,`template`,`external`,`new_window`,`resources`,`callouts`,`author`,`updated_at`) VALUES ('$page','$title','$meta_keywords','$meta_description','$template','$external','$new_window','$resources','$callouts','$last_edited_by','$updated_at')");
  4243. // Remove this page from the cache
  4244. $this->unCache($page);
  4245. // Set local variables in a clean fashion that prevents _SESSION exploitation. Also, don't let them somehow overwrite $page and $current.
  4246. foreach ($data as $key => $val) {
  4247. if (substr($key,0,1) != "_" && $key != "current" && $key != "page") {
  4248. if (is_array($val)) {
  4249. $$key = mysql_real_escape_string(json_encode($val));
  4250. } else {
  4251. $$key = mysql_real_escape_string($val);
  4252. }
  4253. }
  4254. }
  4255. $in_nav = mysql_real_escape_string($data["in_nav"]);
  4256. $redirect_lower = mysql_real_escape_string($data["redirect_lower"]);
  4257. // Make an ipl:// or {wwwroot}'d version of the URL
  4258. if ($external) {
  4259. $external = $this->makeIPL($external);
  4260. }
  4261. // If somehow we didn't provide a parent page (like, say, the user didn't have the right to change it) then pull the one from before. Actually, this might be exploitable… look into it later.
  4262. if (!isset($data["parent"])) {
  4263. $parent = $current["parent"];
  4264. }
  4265. // Create a route if we don't have one, otherwise, make sure the one they provided doesn't suck.
  4266. $route = $data["route"];
  4267. if (!$route) {
  4268. $route = $cms->urlify($data["nav_title"]);
  4269. } else {
  4270. $route = $cms->urlify($route);
  4271. }
  4272. // Get a unique route
  4273. $oroute = $route;
  4274. $x = 2;
  4275. // Reserved paths.
  4276. if ($parent == 0) {
  4277. while (file_exists($GLOBALS["server_root"]."site/".$route."/")) {
  4278. $route = $oroute."-".$x;
  4279. $x++;
  4280. }
  4281. }
  4282. // Existing pages.
  4283. $f = sqlfetch(sqlquery("SELECT id FROM bigtree_pages WHERE `route` = '$route' AND parent = '$parent' AND id != '$page'"));
  4284. while ($f) {
  4285. $route = $oroute."-".$x;
  4286. $f = sqlfetch(sqlquery("SELECT id FROM bigtree_pages WHERE `route` = '$route' AND parent = '$parent' AND id != '$page'"));
  4287. $x++;
  4288. }
  4289. // We have no idea how this affects the nav, just wipe it all.
  4290. if ($current["nav_title"] != $nav_title || $current["route"] != $route || $current["in_nav"] != $in_nav || $current["parent"] != $parent) {
  4291. $this->clearCache();
  4292. }
  4293. // Make sure we set the publish date to NULL if it wasn't provided or we'll have a page that got published at 0000-00-00
  4294. if ($publish_at) {
  4295. $publish_at = "'".date("Y-m-d",strtotime($publish_at))."'";
  4296. } else {
  4297. $publish_at = "NULL";
  4298. }
  4299. // Same goes for the expiration date.
  4300. if ($expire_at) {
  4301. $expire_at = "'".date("Y-m-d",strtotime($expire_at))."'";
  4302. } else {
  4303. $expire_at = "NULL";
  4304. }
  4305. // Set the full path, saves DB access time on the front end.
  4306. if ($parent) {
  4307. $path = $this->getFullNavigationPath($parent)."/".$route;
  4308. } else {
  4309. $path = $route;
  4310. }
  4311. // htmlspecialchars stuff so that it doesn't need to be re-encoded when echo'd on the front end.
  4312. $title = htmlspecialchars($title);
  4313. $nav_title = htmlspecialchars($nav_title);
  4314. $meta_description = htmlspecialchars($meta_description);
  4315. $meta_keywords = htmlspecialchars($meta_keywords);
  4316. $external = htmlspecialchars($external);
  4317. // Update the database
  4318. sqlquery("UPDATE bigtree_pages SET `parent` = '$parent', `nav_title` = '$nav_title', `route` = '$route', `path` = '$path', `in_nav` = '$in_nav', `title` = '$title', `template` = '$template', `external` = '$external', `new_window` = '$new_window', `resources` = '$resources', `callouts` = '$callouts', `meta_keywords` = '$meta_keywords', `meta_description` = '$meta_description', `last_edited_by` = '".$this->ID."', updated_at = NOW(), publish_at = $publish_at, expire_at = $expire_at, max_age = '$max_age' WHERE id = '$page'");
  4319. // Remove any pending drafts
  4320. sqlquery("DELETE FROM bigtree_pending_changes WHERE `table` = 'bigtree_pages' AND item_id = '$page'");
  4321. // Remove old paths from the redirect list
  4322. sqlquery("DELETE FROM bigtree_route_history WHERE old_route = '$path' OR old_route = '".$current["path"]."'");
  4323. // Create an automatic redirect from the old path to the new one.
  4324. if ($current["path"] != $path) {
  4325. sqlquery("INSERT INTO bigtree_route_history (`old_route`,`new_route`) VALUES ('$oldpath','$newpath')");
  4326. // Update all child page routes, ping those engines, clean those caches
  4327. $this->updateChildPagePaths($page);
  4328. $this->pingSearchEngines();
  4329. $this->clearCache();
  4330. }
  4331. // Handle tags
  4332. sqlquery("DELETE FROM bigtree_tags_rel WHERE module = '0' AND entry = '$page'");
  4333. if (is_array($data["_tags"])) {
  4334. foreach ($data["_tags"] as $tag) {
  4335. sqlquery("INSERT INTO bigtree_tags_rel (`module`,`entry`,`tag`) VALUES ('0','$page','$tag')");
  4336. }
  4337. }
  4338. // Audit trail.
  4339. $this->track("bigtree_pages",$page,"updated");
  4340. return $page;
  4341. }
  4342. /*
  4343. Function: updatePageParent
  4344. Changes a page's parent.
  4345. Checks permissions.
  4346. Parameters:
  4347. page - The page to update.
  4348. parent - The parent to switch to.
  4349. */
  4350. function updatePageParent($page,$parent) {
  4351. $page = mysql_real_escape_string($page);
  4352. $parent = mysql_real_escape_string($parent);
  4353. if ($this->Level < 1) {
  4354. $this->stop("You are not allowed to move pages.");
  4355. }
  4356. sqlquery("UPDATE bigtree_pages SET parent = '$parent' WHERE id = '$page'");
  4357. $path = $this->getFullNavigationPath($page);
  4358. sqlquery("UPDATE bigtree_pages SET path = '".mysql_real_escape_string($path)."' WHERE id = '$page'");
  4359. $this->updateChildPagePaths($page);
  4360. }
  4361. /*
  4362. Function: updatePageRevision
  4363. Updates a page revision to save it as a favorite.
  4364. Checks permissions.
  4365. Parameters:
  4366. id - The page revision id.
  4367. description - Saved description.
  4368. */
  4369. function updatePageRevision($id,$description) {
  4370. // Get the version, check if the user has access to the page the version refers to.
  4371. $revision = $this->getPageRevision($id);
  4372. $access = $this->getPageAccessLevel($revision["page"]);
  4373. if ($access != "p") {
  4374. $this->stop("You must be a publisher to manage revisions.");
  4375. }
  4376. // Save the version's description and saved status
  4377. $description = mysql_real_escape_string(htmlspecialchars($description));
  4378. sqlquery("UPDATE bigtree_page_revisions SET saved = 'on', saved_description = '$description' WHERE id = '".$revision["id"]."'");
  4379. }
  4380. /*
  4381. Function: updatePendingChange
  4382. Updated a pending change.
  4383. Parameters:
  4384. id - The id of the pending change.
  4385. changes - The changes to the fields in the entry.
  4386. mtm_changes - Many to Many changes.
  4387. tags_changes - Tags changes.
  4388. */
  4389. function updatePendingChange($id,$changes,$mtm_changes = array(),$tags_changes = array()) {
  4390. $id = mysql_real_escape_string($id);
  4391. $changes = mysql_real_escape_string(json_encode($changes));
  4392. $mtm_changes = mysql_real_escape_string(json_encode($mtm_changes));
  4393. $tags_changes = mysql_real_escape_string(json_encode($tags_changes));
  4394. sqlquery("UPDATE bigtree_pending_changes SET changes = '$changes', mtm_changes = '$mtm_changes', tags_changes = '$tags_changes', date = NOW(), author = '".$this->ID."' WHERE id = '$id'");
  4395. }
  4396. /*
  4397. Function: updateProfile
  4398. Updates a user's name, company, digest setting, and (optionally) password.
  4399. Parameters:
  4400. data - Array containing name / company / daily_digest / password.
  4401. */
  4402. function updateProfile($data) {
  4403. global $config;
  4404. foreach ($data as $key => $val) {
  4405. if (substr($key,0,1) != "_" && !is_array($val)) {
  4406. $$key = mysql_real_escape_string($val);
  4407. }
  4408. }
  4409. $id = mysql_real_escape_string($this->ID);
  4410. if ($data["password"]) {
  4411. $phpass = new PasswordHash($config["password_depth"], TRUE);
  4412. $password = mysql_real_escape_string($phpass->HashPassword($data["password"]));
  4413. sqlquery("UPDATE bigtree_users SET `password` = '$password', `name` = '$name', `company` = '$company', `daily_digest` = '$daily_digest' WHERE id = '$id'");
  4414. } else {
  4415. sqlquery("UPDATE bigtree_users SET `name` = '$name', `company` = '$company', `daily_digest` = '$daily_digest' WHERE id = '$id'");
  4416. }
  4417. }
  4418. /*
  4419. Function: updateResource
  4420. Updates a resource.
  4421. Parameters:
  4422. id - The id of the resource.
  4423. name - The name of the resource.
  4424. */
  4425. function updateResource($id,$name) {
  4426. $id = mysql_real_escape_string($id);
  4427. $name = mysql_real_escape_string(htmlspecialchars($title));
  4428. sqlquery("UPDATE bigtree_resources SET name = '$name' WHERE id = '$id'");
  4429. }
  4430. /*
  4431. Function: updateSetting
  4432. Updates a setting.
  4433. Parameters:
  4434. old_id - The current id of the setting to update.
  4435. data - The new data for the setting ("id", "type", "name", "description", "locked", "encrypted")
  4436. Returns:
  4437. true if successful, false if a setting exists for the new id already.
  4438. */
  4439. function updateSetting($old_id,$data) {
  4440. global $config;
  4441. // Get the existing setting information.
  4442. $existing = $this->getSetting($old_id);
  4443. $old_id = mysql_real_escape_string($old_id);
  4444. // Globalize the data and clean it up.
  4445. foreach ($data as $key => $val) {
  4446. if (substr($key,0,1) != "_" && !is_array($val)) {
  4447. $$key = mysql_real_escape_string(htmlspecialchars($val));
  4448. }
  4449. }
  4450. // We don't want this encoded since it's a WYSIWYG field.
  4451. $description = mysql_real_escape_string($data["description"]);
  4452. // See if we have an id collision with the new id.
  4453. if ($old_id != $id && $this->settingExists($id)) {
  4454. return false;
  4455. }
  4456. sqlquery("UPDATE bigtree_settings SET id = '$id', type = '$type', name = '$name', description = '$description', locked = '$locked', encrypted = '$encrypted' WHERE id = '$old_id'");
  4457. // If encryption status has changed, update the value
  4458. if ($existing["encrypted"] && !$encrypted) {
  4459. sqlquery("UPDATE bigtree_settings SET value = AES_DECRYPT(value,'".mysql_real_escape_string($config["settings_key"])."') WHERE id = '$id'");
  4460. }
  4461. if (!$existing["encrypted"] && $encrypted) {
  4462. sqlquery("UPDATE bigtree_settings SET value = AES_ENCRYPT(value,'".mysql_real_escape_string($config["settings_key"])."') WHERE id = '$id'");
  4463. }
  4464. // Audit trail.
  4465. $this->track("bigtree_settings",$id,"updated");
  4466. return true;
  4467. }
  4468. /*
  4469. Function: updateSettingValue
  4470. Updates the value of a setting.
  4471. Paramters:
  4472. id - The id of the setting to update.
  4473. value - A value to set (can be a string or array).
  4474. */
  4475. function updateSettingValue($id,$value) {
  4476. global $config;
  4477. $item = $this->getSetting($id);
  4478. $id = mysql_real_escape_string($id);
  4479. $value = mysql_real_escape_string(json_encode($value));
  4480. if ($item["encrypted"]) {
  4481. sqlquery("UPDATE bigtree_settings SET `value` = AES_ENCRYPT('$value','".mysql_real_escape_string($config["settings_key"])."') WHERE id = '$id'");
  4482. } else {
  4483. sqlquery("UPDATE bigtree_settings SET `value` = '$value' WHERE id = '$id'");
  4484. }
  4485. // Audit trail
  4486. $this->track("bigtree_settings",$id,"updated-value");
  4487. }
  4488. /*
  4489. Function: updateTemplate
  4490. Updates a template.
  4491. Paremeters:
  4492. id - The id of the template to update.
  4493. name - Name
  4494. description - Description
  4495. level - Access level (0 for everyone, 1 for administrators, 2 for developers)
  4496. module - Related module id
  4497. image - Image
  4498. callouts_enabled - "on" for yes
  4499. resources - An array of resources
  4500. */
  4501. function updateTemplate($id,$name,$description,$level,$module,$image,$callouts_enabled,$resources) {
  4502. $clean_resources = array();
  4503. foreach ($resources as $resource) {
  4504. if ($resource["id"]) {
  4505. $options = json_decode($resource["options"],true);
  4506. foreach ($options as $key => $val) {
  4507. if ($key != "title" && $key != "id" && $key != "subtitle" && $key != "type") {
  4508. $resource[$key] = $val;
  4509. }
  4510. }
  4511. $resource["id"] = htmlspecialchars($resource["id"]);
  4512. $resource["title"] = htmlspecialchars($resource["title"]);
  4513. $resource["subtitle"] = htmlspecialchars($resource["subtitle"]);
  4514. unset($resource["options"]);
  4515. $clean_resources[] = $resource;
  4516. }
  4517. }
  4518. $id = mysql_real_escape_string($id);
  4519. $name = mysql_real_escape_string(htmlspecialchars($name));
  4520. $description = mysql_real_escape_string(htmlspecialchars($description));
  4521. $module = mysql_real_escape_string($module);
  4522. $resources = mysql_real_escape_string(json_encode($clean_resources));
  4523. $image = mysql_real_escape_string($image);
  4524. $level = mysql_real_escape_string($level);
  4525. $callouts_enabled = mysql_real_escape_string($callouts_enabled);
  4526. sqlquery("UPDATE bigtree_templates SET resources = '$resources', image = '$image', name = '$name', module = '$module', description = '$description', level = '$level', callouts_enabled = '$callouts_enabled' WHERE id = '$id'");
  4527. }
  4528. /*
  4529. Function: updateUser
  4530. Updates a user.
  4531. Parameters:
  4532. id - The user's "id"
  4533. data - A key/value array containing email, name, company, level, permissions, alerts, daily_digest, and (optionally) password.
  4534. Returns:
  4535. True if successful. False if the logged in user doesn't have permission to change the user or there was an email collision.
  4536. */
  4537. function updateUser($id,$data) {
  4538. global $config;
  4539. $id = mysql_real_escape_string($id);
  4540. // See if there's an email collission
  4541. $r = sqlrows(sqlquery("SELECT * FROM bigtree_users WHERE email = '".mysql_real_escape_string($data["email"])."' AND id != '$id'"));
  4542. if ($r) {
  4543. return false;
  4544. }
  4545. // If this person has higher access levels than the person trying to update them, fail.
  4546. $current = $this->getUser($id);
  4547. if ($current["level"] > $this->Level) {
  4548. return false;
  4549. }
  4550. // If we didn't pass in a level because we're editing ourselves, use the current one.
  4551. if (!$level || $this->ID == $current["id"]) {
  4552. $level = $current["level"];
  4553. }
  4554. foreach ($data as $key => $val) {
  4555. if (substr($key,0,1) != "_" && !is_array($val)) {
  4556. $$key = mysql_real_escape_string($val);
  4557. }
  4558. }
  4559. $permissions = mysql_real_escape_string(json_encode($data["permissions"]));
  4560. $alerts = mysql_real_escape_string(json_encode($data["alerts"]));
  4561. if ($data["password"]) {
  4562. $phpass = new PasswordHash($config["password_depth"], TRUE);
  4563. $password = mysql_real_escape_string($phpass->HashPassword($data["password"]));
  4564. sqlquery("UPDATE bigtree_users SET `email` = '$email', `password` = '$password', `name` = '$name', `company` = '$company', `level` = '$level', `permissions` = '$permissions', `alerts` = '$alerts', `daily_digest` = '$daily_digest' WHERE id = '$id'");
  4565. } else {
  4566. sqlquery("UPDATE bigtree_users SET `email` = '$email', `name` = '$name', `company` = '$company', `level` = '$level', `permissions` = '$permissions', `alerts` = '$alerts', `daily_digest` = '$daily_digest' WHERE id = '$id'");
  4567. }
  4568. $this->track("bigtree_users",$id,"updated");
  4569. return true;
  4570. }
  4571. /*
  4572. Function: updateUserPassword
  4573. Updates a user's password.
  4574. Parameters:
  4575. id - The user's id.
  4576. password - The new password.
  4577. */
  4578. function updateUserPassword($id,$password) {
  4579. global $config;
  4580. $id = mysql_real_escape_string($id);
  4581. $phpass = new PasswordHash($config["password_depth"], TRUE);
  4582. $password = mysql_real_escape_string($phpass->HashPassword($password));
  4583. sqlquery("UPDATE bigtree_users SET password = '$password' WHERE id = '$id'");
  4584. }
  4585. }
  4586. ?>