From d309b99b0ccb80440eb838fb540c840fc3bb0644 Mon Sep 17 00:00:00 2001
From: Jared Hancock <jared@osticket.com>
Date: Tue, 9 Jul 2013 17:48:12 -0400
Subject: [PATCH] Allow generation and serving of abritrary custom pages

The administrator can define pages in the admin panel defined as type
'other', and when set to active, those pages can be served from the
/pages/<page-name-slug> URL from the base of the helpdesk.

This is mocked up only against Apache
---
 include/class.format.php    | 17 +++++++++++-
 include/staff/page.inc.php  | 12 ++++++++
 include/staff/pages.inc.php |  3 +-
 pages/.htaccess             | 11 ++++++++
 pages/index.php             | 55 +++++++++++++++++++++++++++++++++++++
 5 files changed, 96 insertions(+), 2 deletions(-)
 create mode 100644 pages/.htaccess
 create mode 100644 pages/index.php

diff --git a/include/class.format.php b/include/class.format.php
index 10859d15a..c3abb0029 100644
--- a/include/class.format.php
+++ b/include/class.format.php
@@ -53,7 +53,7 @@ class Format {
             $text = mb_convert_encoding($text, $encoding, $charset);
         elseif(!strcasecmp($encoding, 'utf-8')) //forced blind utf8 encoding.
             $text = function_exists('imap_utf8')?imap_utf8($text):utf8_encode($text);
-        
+
         // If $text is false, then we have a (likely) invalid charset, use
         // the original text and assume 8-bit (latin-1 / iso-8859-1)
         // encoding
@@ -298,5 +298,20 @@ class Format {
         return date($format, ($gmtimestamp+ ($offset*3600)));
     }
 
+    // Thanks, http://stackoverflow.com/a/2955878/1025836
+    /* static */
+    function slugify($text) {
+        // replace non letter or digits by -
+        $text = preg_replace('~[^\p{L}\p{N}]+~u', '-', $text);
+
+        // trim
+        $text = trim($text, '-');
+
+        // lowercase
+        $text = strtolower($text);
+
+        return (empty($text)) ? 'n-a' : $text;
+    }
+
 }
 ?>
diff --git a/include/staff/page.inc.php b/include/staff/page.inc.php
index be52b3607..35881ee74 100644
--- a/include/staff/page.inc.php
+++ b/include/staff/page.inc.php
@@ -13,6 +13,7 @@ if($page && $_REQUEST['a']!='add'){
     $action='update';
     $submit_text='Save Changes';
     $info=$page->getHashtable();
+    $slug = Format::slugify($info['name']);
     $qstr.='&id='.$page->getId();
 }else {
     $title='Add New Page';
@@ -64,6 +65,17 @@ $info=Format::htmlchars(($errors && $_POST)?$_POST:$info);
                 &nbsp;<span class="error">*&nbsp;<?php echo $errors['type']; ?></span>
             </td>
         </tr>
+        <?php if ($info['name'] && $info['type'] == 'other') { ?>
+        <tr>
+            <td width="180" class="required">
+                Public URL:
+            </td>
+            <td><a href="<?php echo sprintf("%s/pages/%s",
+                    $ost->getConfig()->getBaseUrl(), urlencode($slug));
+                ?>">pages/<?php echo $slug; ?></a>
+            </td>
+        </tr>
+        <?php } ?>
         <tr>
             <td width="180" class="required">
                 Status:
diff --git a/include/staff/pages.inc.php b/include/staff/pages.inc.php
index 8fc14be62..cb5fd243a 100644
--- a/include/staff/pages.inc.php
+++ b/include/staff/pages.inc.php
@@ -2,7 +2,8 @@
 if(!defined('OSTADMININC') || !$thisstaff->isAdmin()) die('Access Denied');
 
 $qstr='';
-$sql='SELECT page.id, page.isactive, page.name, page.created, page.updated, count(topic.topic_id) as topics '
+$sql='SELECT page.id, page.isactive, page.name, page.created, page.updated, '
+     .'page.type, count(topic.topic_id) as topics '
      .' FROM '.PAGE_TABLE.' page '
      .' LEFT JOIN '.TOPIC_TABLE.' topic ON(topic.page_id=page.id) '
      .' WHERE 1 ';
diff --git a/pages/.htaccess b/pages/.htaccess
new file mode 100644
index 000000000..ff79be5c9
--- /dev/null
+++ b/pages/.htaccess
@@ -0,0 +1,11 @@
+<IfModule mod_rewrite.c>
+
+RewriteEngine On
+
+RewriteCond %{REQUEST_FILENAME} !-f
+RewriteCond %{REQUEST_FILENAME} !-d
+RewriteCond %{REQUEST_URI} (.*/pages)
+
+RewriteRule ^(.*)$ %1/index.php/$1 [L]
+
+</IfModule>
diff --git a/pages/index.php b/pages/index.php
new file mode 100644
index 000000000..78c49e737
--- /dev/null
+++ b/pages/index.php
@@ -0,0 +1,55 @@
+<?php
+/*********************************************************************
+    pages/index.php
+
+    Custom pages servlet
+
+    Peter Rotich <peter@osticket.com>
+    Jared Hancock <jared@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+@chdir(realpath(dirname(__file__).'/../'));
+define('ROOT_PATH','../');
+
+require_once('client.inc.php');
+require_once(INCLUDE_DIR.'class.format.php');
+require_once(INCLUDE_DIR.'class.page.php');
+
+// Determine the requested page
+// - Strip extension
+$slug = Format::slugify($ost->get_path_info());
+
+// Get the part before the first dash
+$first_word = explode('-', $slug);
+$first_word = $first_word[0];
+
+$sql = 'SELECT id, name FROM '.PAGE_TABLE
+    .' WHERE name LIKE '.db_input("$first_word%");
+$page_id = null;
+
+$res = db_query($sql);
+while (list($id, $name) = db_fetch_row($res)) {
+    if (Format::slugify($name) == $slug) {
+        $page_id = $id;
+        break;
+    }
+}
+
+if (!$page_id || !($page = Page::lookup($page_id)))
+    Http::response(404, 'Page Not Found');
+
+if (!$page->isActive() || $page->getType() != 'other')
+    Http::response(404, 'Page Not Found');
+
+require(CLIENTINC_DIR.'header.inc.php');
+
+print $page->getBody();
+
+require(CLIENTINC_DIR.'footer.inc.php');
+?>
-- 
GitLab