_binary From 1b7879dc2b8f22aabd8ff6b8a319772d63e40cf2 Mon Sep 17 00:00:00 2001
From: Eswara Rajesh Pinapala <epinapala@ebay.com>
Date: Mon, 10 Nov 2014 11:38:37 -0800
Subject: [PATCH 1/2] Pulled latest changes pertaining to doMessageRemoval by
 Professor, Merged and resolved conflicts manually.

Changes summary below:
* Execute Wiki help back logic only-> c=admin or group &&a=wiki && arg= edit or read
* Move Help Javascript source to a new file. Load the help.js only when atleast one button is rendered on the page.
* Fixes help issues that were caused by the latets changes to Pagetitle.
* Clean $_REQUEST params before using.
* Populate help articles in create db by directly, remove logic that fetches pages from sqlite db.
---
 configs/createdb.php                | 177 +++++++++++++++---
 controllers/api_controller.php      |   3 +-
 controllers/controller.php          |  32 ++--
 scripts/basic.js                    | 318 +-------------------------------
 scripts/help.js                     | 348 ++++++++++++++++++++++++++++++++++++
 views/elements/api_element.php      |   3 +-
 views/helpers/helpbutton_helper.php |  79 +++++---
 views/layouts/web_layout.php        |   7 +
 8 files changed, 583 insertions(+), 384 deletions(-)
 create mode 100644 scripts/help.js

diff --git a/configs/createdb.php b/configs/createdb.php
index 7920321..442670a 100755
--- a/configs/createdb.php
+++ b/configs/createdb.php
@@ -548,8 +548,158 @@ foreach($public_pages as $page_name => $page_content) {
         $page_content, "en-US", "Creating Default Pages",
         "$page_name Wiki Page Created!", "Discuss the page in this thread!");
 }
+$help_pages = array();
+$help_pages["Add_Locale"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+toc=true
+
+title=Add Locale
+
+description=Help article describing how to add a Locale.
+
+END_HEAD_VARS==Adding a Locale==
+
+The Manage Locales activity can be used to configure Yioop for use with different languages and for different regions.
+
+* The first form on this activity allows you to create a new &quot;Locale&quot; -- an object representing a language and a region.
+* The first field on this form should be filled in with a name for the locale in the language of the locale.
+* So for French you would put :Fran&ccedil;ais. The locale tag should be the IETF language tag.
+EOD;
+$help_pages["Database_Setup"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+title=Database Setup
+
+END_HEAD_VARSThe database is used to store information about what users are allowed to use the admin panel and what activities and roles these users have.
+* The Database Set-up field-set is used to specify what database management system should be used, how it should be connected to, and what user name and password should be used for the connection.
+
+* Supported Databases
+** PDO (PHP's generic DBMS interface).
+** Sqlite3 Database.
+** Mysql Database.
+
+* Unlike many database systems, if an sqlite3 database is being used then the connection is always a file on the current filesystem and there is no notion of login and password, so in this case only the name of the database is asked for. For sqlite, the database is stored in WORK_DIRECTORY/data.
+
+* For single user settings with a limited number of news feeds, sqlite is probably the most convenient database system to use with Yioop. If you think you are going to make use of Yioop's social functionality and have many users, feeds, and crawl mixes, using a system like Mysql or Postgres might be more appropriate.
+EOD;
+$help_pages["Locale_Writing_Mode"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+title=Locale Writing Mode
+
+END_HEAD_VARSThe last field on the form is to specify how the language is written. There are four options:
+# lr-tb -- from left-to-write from the top of the page to the bottom as in English.
+#  rl-tb from right-to-left from the top the page to the bottom as in Hebrew and Arabic.
+#  tb-rl from the top of the page to the bottom from right-to-left as in Classical Chinese.
+#  tb-lr from the top of the page to the bottom from left-to-right as in non-cyrillic Mongolian or American Sign Language.
+
+''lr-tb and rl-tb support work better than the vertical language support. As of this writing, Internet Explorer and WebKit based browsers (Chrome/Safari) have some vertical language support and the Yioop stylesheets for vertical languages still need some tweaking. For information on the status in Firefox check out this writing mode bug.''
+EOD;
+$help_pages["Locale_List"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+title=Locale List
+
+END_HEAD_VARSBeneath the Add Locale form is a table listing some of the current locales.
+
+
+* The Show Dropdown let's you control how many of these locales are displayed in one go.
+* The Search link lets you bring up an advance search form to search for particular locales and also allows you to control the direction of the listing.
+
+The Locale List table
+* The first column in the table  has a link with the name of the locale. Clicking on this link brings up a page where one can edit the strings for that locale.
+* The next two columns of the Locale List table give the locale tag and writing direction of the locale, this is followed by the percent of strings translated. Clicking the Edit link in the column let&amp;#039;s you edit the locale tag, and text direction of a locale.
+* Finally, clicking the Delete link let&amp;#039;s one delete a locale and all its strings.
+EOD;
+$help_pages["Browse_Groups"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+toc=true
+
+title=Browse Groups
+
+END_HEAD_VARS<br />
+Manage Groups is available to only those with a standard user role.
+<br />
+'''Groups''' are collections of users that have access to a group feed and a set of wiki pages. Any User with a &quot;Standard&quot; role can create or edit groups. The Create/Join Group form takes the name of a group, by which the user can select an existing group to Join. If you enter a name that currently does not exist, You will have the option to create a New group, which will be done on the Create Group form.
+EOD;
+$help_pages["Machine_Information"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+toc=true
+
+title=Machine Information
+
+END_HEAD_VARS<br />
+'''Machine Information listings:'''
+<br />
+This shows the currently known about machines. This list always begins with the Name Server itself and a toggle to control whether or not the News Updater process is running on the Name Server. This allows you to control whether or not Yioop attempts to update its RSS (or Atom) search sources on an hourly basis.There is also a link to the log file of the News Updater process. Under the Name Server information is a dropdown that can be used to control the number of current machine statuses that are displayed for all other machines that have been added. It also might have next and previous arrow links to go through the currently available machines.
+<br />
+For more information on prerequisites for crawling Visit full documentation [[https://www.seekquarry.com/?c=main&amp;p=documentation#prereqs| here]]
+EOD;
+$help_pages["Manage_Machines"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+toc=true
+
+title=Manage Machines
+
+END_HEAD_VARS<br />
+'''Add Machine:'''
+<br /><br />
+The Add machine form allows you to add a new machine to be controlled by this Yioop instance. The '''Machine Name''' field lets you give this machine an easy to remember name. The Machine URL field should be filled in with the URL to the installed Yioop instance.
+<br />
+The '''Mirror''' check-box says whether you want the given Yioop installation to act as a mirror for another Yioop installation. Checking it will reveal a drop-down menu that allows you to choose which installation among-st the previously entered machines you want to mirror. The '''Has Queue Server''' check-box is used to say whether the given Yioop installation will be running a queue server or not.
+<br />
+Finally, the '''Number of Fetchers''' drop down allows you to say how many fetcher instances you want to be able to manage for that machine.
+EOD;
+$help_pages["Discover_Groups"] = <<<EOD
+page_type=standard
+
+page_border=solid-border
+
+toc=true
+
+title=Discover Groups
+
+END_HEAD_VARS'''Name''' Field is used to specify the name of the Group to search for.
+'''Owner''' Field lets you search a Group using it's Owner name.
+<br />
+'''Register''' dropdown says how other users are allowed to join the group:
+* <u>No One</u> means no other user can join the group (you can still invite other users).
+* <u>By Request</u> means that other users can request the group owner to join the group.
+* <u>Anyone</u> means all users are allowed to join the group.
+<br />
+''It should be noted that the root account can always join any group.
+The root account can also always take over ownership of any group.''
+<br />
+The '''Access''' dropdown controls how users who belong/subscribe to a group other than the owner can access that group.
+* <u>No Read</u> means that a non-owner member of the group cannot read or write the group news feed and cannot read the group wiki.
+* <u>Read</u> means that a non-owner member of the group can read the group news feed and the groups wiki page.
+* <u>Read</u> Comment means that a non-owner member of the group can read the group feed and wikis and can comment on any existing threads, but cannot start new ones.
+* <u>Read Write</u>, means that a non-owner member of the group can start new threads and comment on existing ones in the group feed and can edit and create wiki pages for the group's wiki.
+<br />
+The access to a group can be changed by the owner after a group is created.
+* <u>No Read</u> and <u>Read</u> are often suitable if a group's owner wants to perform some kind of moderation.
+* <u>Read</u> and <u>Read Comment</u> groups are often suitable if someone wants to use a Yioop Group as a blog.
+* <u>Read</u> Write makes sense for a more traditional bulletin board.
+EOD;
 //Insert Help pages
-$help_pages = getWikiHelpPages();
 foreach($help_pages as $page_name => $page_content) {
     $page_content = str_replace("&amp;", "&", $page_content);
     $page_content = @htmlentities($page_content, ENT_QUOTES, "UTF-8");
@@ -557,31 +707,6 @@ foreach($help_pages as $page_name => $page_content) {
         $page_content, "en-US", "Creating Default Pages",
         "$page_name Help Page Created!", "Discuss the page in this thread!");
 }
-function getWikiHelpPages()
-{
-    $help_pages = array();
-    require_once(BASE_DIR . "/models/datasources/sqlite3_manager.php");
-    $default_dbm = new Sqlite3Manager();
-    $default_dbm->connect("", "", "", BASE_DIR . "/data/default_help.db");
-    if(!$default_dbm) {
-        return false;
-    }
-    $group_model = new GroupModel(DB_NAME, true);
-    $group_model->db = $default_dbm;
-    $page_list = $group_model->getPageList(HELP_GROUP_ID, "en-US", '', 0, 200);
-    foreach($page_list[1] as $page) {
-        if(isset($page['TITLE'])) {
-            $page_info = $group_model->getPageInfoByName(
-                HELP_GROUP_ID, $page['TITLE'], "en-US", "api");
-            $page_content = str_replace("&amp;", "&", $page_info['PAGE']);
-            $page_content = html_entity_decode($page_content, ENT_QUOTES,
-                "UTF-8");
-            $help_pages[$page['TITLE']] = $page_content;
-        }
-    }
-    return $help_pages;
-}
-
 /* End Help content insertion. */
 /* we insert 1 by 1 rather than comma separate as sqlite
    does not support comma separated inserts
diff --git a/controllers/api_controller.php b/controllers/api_controller.php
index 641067a..0fec3da 100644
--- a/controllers/api_controller.php
+++ b/controllers/api_controller.php
@@ -113,12 +113,13 @@ class ApiController extends Controller implements CrawlConstants {
     function processSession() {
         if (isset($_REQUEST['a']) &&
                 in_array($_REQUEST['a'], $this->activities)) {
-            $activity = $_REQUEST['a'];
+            $activity = $this->clean($_REQUEST['a'],"string");
         } else {
             $activity = "groupFeeds";
         }
         $data = $this->call($activity);
         $data['ACTIVITY_CONTROLLER'] = "group";
+        $data['PAGE_TITLE'] = $this->clean($_REQUEST['page_name'],"string");
         $data['ACTIVITY_METHOD'] = $activity; //for settings controller
         if (!is_array($data)) {
             $data = array();
diff --git a/controllers/controller.php b/controllers/controller.php
index a4a7504..3a177cb 100755
--- a/controllers/controller.php
+++ b/controllers/controller.php
@@ -298,21 +298,29 @@ abstract class Controller
     {
         $data = array();
         $data["OTHER_BACK_URL"] = "";
-        if(isset($_REQUEST['back_params']) && isset($_REQUEST['arg']) &&
-            in_array($_REQUEST['arg'], array('edit','read'))) {
-            foreach ($_REQUEST['back_params'] as
-                     $back_param_key => $back_param_value) {
-                $back_param_key = $this->clean($back_param_key, "string");
-                $back_param_value = $this->clean($back_param_value, "string");
-                $data['BACK_PARAMS']["back_params[$back_param_key]"]
-                    = $back_param_value;
-                $data["OTHER_BACK_URL"] .= "&amp;back_params[$back_param_key]"
-                    . "=" . $back_param_value;
+        if(isset($_REQUEST['a'])) {
+            $action = $this->clean($_REQUEST['a'], "string");
+            if($action == 'wiki' && isset($_REQUEST['back_params']) &&
+                isset($_REQUEST['arg']) && in_array(
+                    $this->clean($_REQUEST['arg'],"string"), array('edit',
+                    'read'))) {
+                foreach($_REQUEST['back_params'] as
+                        $back_param_key => $back_param_value) {
+                    $back_param_key = $this->clean($back_param_key, "string");
+                    $back_param_value = $this->clean($back_param_value,
+                        "string");
+                    $data['BACK_PARAMS']["back_params[$back_param_key]"]
+                        = $back_param_value;
+                    $data["OTHER_BACK_URL"] .=
+                        "&amp;back_params[$back_param_key]" . "=" .
+                        $back_param_value;
+                }
+                $data['BACK_URL'] = http_build_query($_REQUEST["back_params"]);
             }
-            $data['BACK_URL'] = http_build_query($_REQUEST["back_params"]);
         }
         if(isset($_REQUEST['open_help_page'])) {
-            $data['OPEN_HELP_PAGE'] = $_REQUEST['open_help_page'];
+            $data['OPEN_HELP_PAGE'] = $this->clean($_REQUEST['open_help_page'],
+                "string");
             if(!isset($data['SCRIPT'])) {
                 $data['SCRIPT'] = "";
             }
diff --git a/scripts/basic.js b/scripts/basic.js
index dede51f..c9f4d13 100755
--- a/scripts/basic.js
+++ b/scripts/basic.js
@@ -179,320 +179,4 @@ function toggleDisplay(id)
         value = "block";
     }
     obj.style.display = value;
-}
-current_activity_closed = true;
-current_activity_top = 0;
-/*
- * Toggles Help element from display:none and display block.
- * Also changes the width of the Current activity accordingly.
- * @param String help element's id to toggle.
- * @param String isMobile flag true/false.
- * @param String target_controller Edit page's controller name.
- */
-function toggleHelp(id, isMobile, target_controller)
-{
-    var activity = (target_controller === "admin") ? 'current-activity' :
-        'small-margin-current-activity';
-    var images = document.querySelectorAll(".wiki-resource-image");
-    var all_help_elements =
-        document.getElementsByClassName(activity);
-    var help_node = all_help_elements[0];
-    if (current_activity_closed === true) {
-        current_activity_top = getCssProperty(help_node, 'top');
-    }
-    obj = elt(id);
-    if (isMobile === false) {
-        toggleDisplay(id);
-        var new_width;
-        var decrease_width_by = Math.floor(getCssProperty(obj, 'width') / 3);
-        //Calculate pixel to inch. clientWidth only returns in pixels.
-        if (obj.style.display === "none") {
-            new_width = Math.floor(getCssProperty(help_node, 'width')) +
-            decrease_width_by;
-        } else if (obj.style.display === "block") {
-            new_width = Math.floor(getCssProperty(help_node, 'width')) -
-            decrease_width_by;
-        }
-        if (new_width !== undefined) {
-            help_node.style.maxWidth = new_width + "px";
-        }
-    } else {
-        toggleDisplay(id);
-        var height_after_toggle = (obj.clientHeight);
-        //Calculate pixel to inch. clientWidth only returns in pixels.
-        if (obj.style.display === "none") {
-            //on closing, restore top
-            help_node.style.top = current_activity_top + "px";
-            current_activity_closed = true;
-        } else if (obj.style.display === "block") {
-            help_node.style.top = current_activity_top +
-            height_after_toggle + "px";
-            /* The div.clientHeight doesnt include the height
-             of the images inside the div before the images are completely
-             loaded. So we iterate through the
-             image elements, as each image loads add the image
-             height to the top of the current_activity div dynamically. */
-            for (var i = 0; i < images.length; i++) {
-                var image = images[i];
-                image.onload = function ()
-                {
-                    help_node.style.top = getCssProperty(help_node,
-                        'top') + this.height + 'px';
-                };
-            }
-            current_activity_closed = false;
-        }
-    }
-}
-/*
- * Gets the Css property given an element and property name.
- * @param Object elm Element to get the Css property for.
- * @param String property Css property name.
- * @return String Css property value
- */
-function getCssProperty(elm, property)
-{
-    //always returns in px
-    return parseInt(window.getComputedStyle(elm, null)
-        .getPropertyValue(property));
-}
-/*
- * This is a JS function to convert yioop wiki markup to
- * html.
- * @param String wiki_text to be parsed as HTML
- * @return String parsed html.
- */
-function parseWikiContent(wiki_text, group_id, page_id, controller_name,
-    csrf_token_key, csrf_token_value)
-{
-    var html = wiki_text;
-    /* note that line breaks from a text area are sent
-     as \r\n , so make sure we clean them up to replace
-     all \r\n with \n */
-    html = html.replace(/\r\n/g, "\n");
-    html = parseLists(html);
-    //Regex replace normal links
-    html = html.replace(/[^\[](http[^\[\s]*)/g, function (m, l)
-    {
-        // normal link
-        return '<a href="' + l + '">' + l + '</a>';
-    });
-    //Regex replace for external links
-    html = html.replace(/\[[\[](http.*)[!\]]/g, function (m, l)
-    {
-        // external link
-        var p = l.replace(/[\[\]]/g, '').split(/\|/);
-        var link = p.shift();
-        return '<a href="' + link + '">' + (p.length ? p.join(' ') :
-            link) + '</a>';
-    });
-    //Regex replace for headings
-    html = html.replace(/(?:^|\n)([=]+)(.*)\1/g,
-        function (match, contents, t)
-        {
-            return '<h' + contents.length + '>' + t + '</h' + contents.length +
-            '>';
-        });
-    //Regex replace for Bold characters
-    html = html.replace(/'''(.*?)'''/g, function (match, contents)
-    {
-        return '<b>' + contents + '</b>';
-    });
-    //Regex replace for Italic characters
-    html = html.replace(/''(.*?)''/g, function (match, contents)
-    {
-        return '<i>' + contents + '</i>';
-    });
-    //Regex for yioop resource extraction.
-    html = html.replace(/\(\(resource:(.+?)\|(.+?)\)\)/g,
-        function (match, contents, desc)
-        {
-            if((/\.(gif|jpg|jpeg|tiff|png|bmp|tif)$/i).test(contents)) {
-                return '<img src="' + "?c=resource&a=get&f=resources&g=" +
-                group_id + "&p=" + page_id + "&n=" + contents +
-                '" alt="' + desc + '" class="wiki-resource-image"/>';
-            } else if((/\.(avi|m4v|flv|wmv|mp4|webm|ogg|mov|mpg)$/i)
-                    .test(contents)) {
-                return '<video style="width:100%" controls="controls">' +
-                '<source src="./?c=resource&amp;a=get&amp;f=resources&amp;g=' +
-                group_id + '&amp;p=' + page_id + '&amp;n=' + contents +
-                '" type="video/mp4">' + desc + '</video>';
-            } else {
-                return '<a href="' + "?c=resource&a=get&f=resources&g=" +
-                group_id + "&p=" + page_id + "&n=" + contents +
-                '" alt="' + desc + '"/>' + desc + '</a>';
-            }
-        });
-    //Regex replace for HR
-    html = html.replace(/----(.*?)/g, function (match, contents)
-    {
-        return contents + '<hr />';
-    });
-    //Regex replace for def list
-    html = html.replace
-    (/(\A|\n);([^:]+):(.+)/g,
-        function (match, match2, match3, match4)
-        {
-            return "<dl><dt>" + match3 + "</dt><dd>" +
-            match4 + "</dd></dl>";
-        });
-    //replace nowiki with pre tags
-    html = html.replace(/<nowiki>(.*?)<\/nowiki>/g, function (match,
-        contents)
-    {
-        return '<pre>' + contents + '</pre>';
-    });
-    //Regex replace for blocks
-    html = html.replace(/(?:^|\n+)([^# =\*<].+)(?:\n+|$)/gm,
-        function (match, contents)
-        {
-            if(contents.match(/^\^+$/))
-                return contents;
-            return "\n<div>" + contents + "</div>\n";
-        });
-    //Internal links to other pages.
-    html = html.replace(/\[\[(.*?)\]\]/g, function (matches, internal_link)
-    {
-        var internal_link_array = internal_link.split(/\|/);
-        var page_name = internal_link_array.shift().replace(/ /g, "_");
-        return '<a href="' + '?c=' + controller_name
-        + '&a=wiki&arg=read&group_id=' + group_id + '&page_name=' + page_name
-        + "&" + csrf_token_key + '=' + csrf_token_value + '">'
-        + (internal_link_array.length ? internal_link_array.join('|')
-            : page_name)
-        + '</a>';
-    });
-    return html;
-}
-/*
- * Lists need to be recursively parsed. So the below function is used
- * to recursively convert wiki markup to html.
- * @param String str usually the content string in which the UL/OL lists are
- * needed to be parsed to html.
- * @return String parsed html.
- */
-function parseLists(str)
-{
-    return str.replace(/(?:(?:(?:^|\n)[\*#].*)+)/g, function (match)
-    {
-        var listType = match.match(/(^|\n)#/) ? 'ol' : 'ul';
-        match = match.replace(/(^|\n)[\*#][ ]{0,1}/g, "$1");
-        match = parseLists(match);
-        return '<' + listType + '><li>' + match.replace(/^\n/, '')
-            .split(/\n/).join('</li><li>') + '</li></' + listType +
-        '>';
-    });
-}
-/*
- * getPageWithCallback does a GET HTTP call on the url passed.
- * Also fires the callback functions passed as
- * params appropriately.
- *
- * @param String url the url used for making GET HTTP call.
- * @param String response_type The response type expected.
- * @param Function object success_call_back Callback function on success.
- * @param Function object error_handler Callback function on failure.
- */
-function getPageWithCallback(url, response_type, success_call_back,
-    error_handler)
-{
-    var request = makeRequest();
-    request.open('GET', url, true);
-    request.onload = function ()
-    {
-        var status = request.status;
-        if(status == 200) {
-            success_call_back && success_call_back(
-                    JSON.parse(request.responseText));
-        } else {
-            error_handler && error_handler(status);
-        }
-    };
-    request.send();
-};
-/*
- * Takes in the help point id, uses it to fetch wiki content, then
- * wiki content is being eval'd to be painted int he help pane.
- * Ajax call happens only if help needs to be displayed.
- * @param Object help_point element
- * @param String is_mobile flag to check if the client is mobile
- * or not.
- * @param String target_controller Wiki page's controller name.
- * @param String csrf_token_key teh dynamic name used for CSRF token var.
- * @param String csrf_token_value The CSRF token to render edit page.
- * @param String help_group_id  help's group_id required to render resources.
- * @param String api_controller api's controller name.
- * @param String api_action api's action name.
- * @param String mode r/w mode , usually read.
- */
-function displayHelpForId(help_point, is_mobile, target_controller,
-    current_action, csrf_token_key, csrf_token_value, help_group_id,
-    api_controller, api_action, mode)
-{
-    if((elt("help-frame").style.display) === "block") {
-        toggleHelp('help-frame', is_mobile, target_controller);
-    }
-    var tl = eval('(' + help_point.getAttribute("data-tl") + ')');
-    var back_params = eval('(' + help_point.getAttribute("data-back-params")
-    + ')');
-    getPageWithCallback("?c=" + api_controller + "&group_id=" +
-        help_group_id + "&" +
-        "arg=" + mode + "&" +
-        "a=" + api_action + "&" +
-        csrf_token_key + '=' + csrf_token_value + "&" +
-        "page_name=" + help_point.getAttribute("data-pagename"),
-        'json',
-        function (data)
-        {
-            elt("help-frame-body").innerHTML = parseWikiContent(
-                data.wiki_content,
-                data.group_id,
-                data.page_id,
-                target_controller,
-                csrf_token_key,
-                csrf_token_value
-            );
-            elt('page_name').innerHTML = data.page_name + ' [<a href="' +
-            getEditLink(
-                target_controller,
-                current_action,
-                csrf_token_key,
-                csrf_token_value,
-                help_group_id,
-                data.page_name,
-                back_params) + '">' +
-            tl["wiki_view_edit"] + '</a>]';
-            toggleHelp('help-frame', is_mobile, target_controller);
-        },
-        function (status)
-        {
-            toggleHelp('help-frame', is_mobile, target_controller);
-        });
-}
-/*
- * Simple function to construct the Wiki Edit hyperlink with passed in params.
- * @param String target_controller Edit page's controller name.
- * @param String csrf_token_key teh dynamic name used for CSRF token var.
- * @param String csrf_token_value The CSRF token to render edit page.
- * @param String group_id GroupId of the group which has the wiki.
- * @param String page_name Page name,unique Identifier for wiki edit page.
- * @return String the edit link
- */
-function getEditLink(target_controller, current_action, csrf_token_key,
-    csrf_token_value, group_id, page_name, back_params)
-{
-    var edit_link = '?c=' + target_controller +
-        '&' + csrf_token_key + '=' + csrf_token_value +
-        '&group_id=' + group_id +
-        '&arg=edit' +
-        '&a=wiki' +
-        '&page_name=' + page_name +
-        '&back_params[open_help_page]=' + page_name +
-        '&back_params[c]=' + target_controller +
-        '&back_params[a]=' + current_action;
-    for (var key in back_params) {
-        var value = back_params[key];
-        edit_link += "&back_params[" + key + "]=" + value;
-    }
-    return edit_link;
-}
+}
\ No newline at end of file
diff --git a/scripts/help.js b/scripts/help.js
new file mode 100644
index 0000000..1380661
--- /dev/null
+++ b/scripts/help.js
@@ -0,0 +1,348 @@
+/**
+ * SeekQuarry/Yioop --
+ * Open Source Pure PHP Search Engine, Crawler, and Indexer
+ *
+ * Copyright (C) 2009 - 2014  Chris Pollett chris@pollett.org
+ *
+ * LICENSE:
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * END LICENSE
+ *
+ * @author Eswara Rajesh Pinapala epinapala@live.com
+ * @package seek_quarry
+ * @subpackage javascript
+ * @license http://www.gnu.org/licenses/ GPL3
+ * @link http://www.seekquarry.com/
+ * @copyright 2009 - 2014
+ * @filesource
+ */
+current_activity_closed = true;
+current_activity_top = 0;
+/*
+ * Toggles Help element from display:none and display block.
+ * Also changes the width of the Current activity accordingly.
+ * @param String help element's id to toggle.
+ * @param String isMobile flag true/false.
+ * @param String target_controller Edit page's controller name.
+ */
+function toggleHelp(id, isMobile, target_controller)
+{
+    var activity = (target_controller === "admin") ? 'current-activity' :
+        'small-margin-current-activity';
+    var images = document.querySelectorAll(".wiki-resource-image");
+    var all_help_elements =
+        document.getElementsByClassName(activity);
+    var help_node = all_help_elements[0];
+    if (current_activity_closed === true) {
+        current_activity_top = getCssProperty(help_node, 'top');
+    }
+    obj = elt(id);
+    if (isMobile === false) {
+        toggleDisplay(id);
+        var new_width;
+        var decrease_width_by = Math.floor(getCssProperty(obj, 'width') / 3);
+        //Calculate pixel to inch. clientWidth only returns in pixels.
+        if (obj.style.display === "none") {
+            new_width = Math.floor(getCssProperty(help_node, 'width')) +
+            decrease_width_by;
+        } else if (obj.style.display === "block") {
+            new_width = Math.floor(getCssProperty(help_node, 'width')) -
+            decrease_width_by;
+        }
+        if (new_width !== undefined) {
+            help_node.style.maxWidth = new_width + "px";
+        }
+    } else {
+        toggleDisplay(id);
+        var height_after_toggle = (obj.clientHeight);
+        //Calculate pixel to inch. clientWidth only returns in pixels.
+        if (obj.style.display === "none") {
+            //on closing, restore top
+            help_node.style.top = current_activity_top + "px";
+            current_activity_closed = true;
+        } else if (obj.style.display === "block") {
+            help_node.style.top = current_activity_top +
+            height_after_toggle + "px";
+            /* The div.clientHeight doesnt include the height
+             of the images inside the div before the images are completely
+             loaded. So we iterate through the
+             image elements, as each image loads add the image
+             height to the top of the current_activity div dynamically. */
+            for (var i = 0; i < images.length; i++) {
+                var image = images[i];
+                image.onload = function ()
+                {
+                    help_node.style.top = getCssProperty(help_node,
+                        'top') + this.height + 'px';
+                };
+            }
+            current_activity_closed = false;
+        }
+    }
+}
+/*
+ * Gets the Css property given an element and property name.
+ * @param Object elm Element to get the Css property for.
+ * @param String property Css property name.
+ * @return String Css property value
+ */
+function getCssProperty(elm, property)
+{
+    //always returns in px
+    return parseInt(window.getComputedStyle(elm, null)
+        .getPropertyValue(property));
+}
+/*
+ * This is a JS function to convert yioop wiki markup to
+ * html.
+ * @param String wiki_text to be parsed as HTML
+ * @return String parsed html.
+ */
+function parseWikiContent(wiki_text, group_id, page_id, controller_name,
+    csrf_token_key, csrf_token_value)
+{
+    var html = wiki_text;
+    /* note that line breaks from a text area are sent
+     as \r\n , so make sure we clean them up to replace
+     all \r\n with \n */
+    html = html.replace(/\r\n/g, "\n");
+    html = parseLists(html);
+    //Regex replace normal links
+    html = html.replace(/[^\[](http[^\[\s]*)/g, function (m, l)
+    {
+        // normal link
+        return '<a href="' + l + '">' + l + '</a>';
+    });
+    //Regex replace for external links
+    html = html.replace(/\[[\[](http.*)[!\]]/g, function (m, l)
+    {
+        // external link
+        var p = l.replace(/[\[\]]/g, '').split(/\|/);
+        var link = p.shift();
+        return '<a href="' + link + '">' + (p.length ? p.join(' ') :
+            link) + '</a>';
+    });
+    //Regex replace for headings
+    html = html.replace(/(?:^|\n)([=]+)(.*)\1/g,
+        function (match, contents, t)
+        {
+            return '<h' + contents.length + '>' + t + '</h' + contents.length +
+            '>';
+        });
+    //Regex replace for Bold characters
+    html = html.replace(/'''(.*?)'''/g, function (match, contents)
+    {
+        return '<b>' + contents + '</b>';
+    });
+    //Regex replace for Italic characters
+    html = html.replace(/''(.*?)''/g, function (match, contents)
+    {
+        return '<i>' + contents + '</i>';
+    });
+    //Regex for yioop resource extraction.
+    html = html.replace(/\(\(resource:(.+?)\|(.+?)\)\)/g,
+        function (match, contents, desc)
+        {
+            if((/\.(gif|jpg|jpeg|tiff|png|bmp|tif)$/i).test(contents)) {
+                return '<img src="' + "?c=resource&a=get&f=resources&g=" +
+                group_id + "&p=" + page_id + "&n=" + contents +
+                '" alt="' + desc + '" class="wiki-resource-image"/>';
+            } else if((/\.(avi|m4v|flv|wmv|mp4|webm|ogg|mov|mpg)$/i)
+                    .test(contents)) {
+                return '<video style="width:100%" controls="controls">' +
+                '<source src="./?c=resource&amp;a=get&amp;f=resources&amp;g=' +
+                group_id + '&amp;p=' + page_id + '&amp;n=' + contents +
+                '" type="video/mp4">' + desc + '</video>';
+            } else {
+                return '<a href="' + "?c=resource&a=get&f=resources&g=" +
+                group_id + "&p=" + page_id + "&n=" + contents +
+                '" alt="' + desc + '"/>' + desc + '</a>';
+            }
+        });
+    //Regex replace for HR
+    html = html.replace(/----(.*?)/g, function (match, contents)
+    {
+        return contents + '<hr />';
+    });
+    //Regex replace for def list
+    html = html.replace
+    (/(\A|\n);([^:]+):(.+)/g,
+        function (match, match2, match3, match4)
+        {
+            return "<dl><dt>" + match3 + "</dt><dd>" +
+            match4 + "</dd></dl>";
+        });
+    //replace nowiki with pre tags
+    html = html.replace(/<nowiki>(.*?)<\/nowiki>/g, function (match,
+        contents)
+    {
+        return '<pre>' + contents + '</pre>';
+    });
+    //Regex replace for blocks
+    html = html.replace(/(?:^|\n+)([^# =\*<].+)(?:\n+|$)/gm,
+        function (match, contents)
+        {
+            if(contents.match(/^\^+$/))
+                return contents;
+            return "\n<div>" + contents + "</div>\n";
+        });
+    //Internal links to other pages.
+    html = html.replace(/\[\[(.*?)\]\]/g, function (matches, internal_link)
+    {
+        var internal_link_array = internal_link.split(/\|/);
+        var page_name = internal_link_array.shift().replace(/ /g, "_");
+        return '<a href="' + '?c=' + controller_name
+        + '&a=wiki&arg=read&group_id=' + group_id + '&page_name=' + page_name
+        + "&" + csrf_token_key + '=' + csrf_token_value + '">'
+        + (internal_link_array.length ? internal_link_array.join('|')
+            : page_name)
+        + '</a>';
+    });
+    return html;
+}
+/*
+ * Lists need to be recursively parsed. So the below function is used
+ * to recursively convert wiki markup to html.
+ * @param String str usually the content string in which the UL/OL lists are
+ * needed to be parsed to html.
+ * @return String parsed html.
+ */
+function parseLists(str)
+{
+    return str.replace(/(?:(?:(?:^|\n)[\*#].*)+)/g, function (match)
+    {
+        var listType = match.match(/(^|\n)#/) ? 'ol' : 'ul';
+        match = match.replace(/(^|\n)[\*#][ ]{0,1}/g, "$1");
+        match = parseLists(match);
+        return '<' + listType + '><li>' + match.replace(/^\n/, '')
+            .split(/\n/).join('</li><li>') + '</li></' + listType +
+        '>';
+    });
+}
+/*
+ * getPageWithCallback does a GET HTTP call on the url passed.
+ * Also fires the callback functions passed as
+ * params appropriately.
+ *
+ * @param String url the url used for making GET HTTP call.
+ * @param String response_type The response type expected.
+ * @param Function object success_call_back Callback function on success.
+ * @param Function object error_handler Callback function on failure.
+ */
+function getPageWithCallback(url, response_type, success_call_back,
+    error_handler)
+{
+    var request = makeRequest();
+    request.open('GET', url, true);
+    request.onload = function ()
+    {
+        var status = request.status;
+        if(status == 200) {
+            success_call_back && success_call_back(
+                JSON.parse(request.responseText));
+        } else {
+            error_handler && error_handler(status);
+        }
+    };
+    request.send();
+};
+/*
+ * Takes in the help point id, uses it to fetch wiki content, then
+ * wiki content is being eval'd to be painted int he help pane.
+ * Ajax call happens only if help needs to be displayed.
+ * @param Object help_point element
+ * @param String is_mobile flag to check if the client is mobile
+ * or not.
+ * @param String target_controller Wiki page's controller name.
+ * @param String csrf_token_key teh dynamic name used for CSRF token var.
+ * @param String csrf_token_value The CSRF token to render edit page.
+ * @param String help_group_id  help's group_id required to render resources.
+ * @param String api_controller api's controller name.
+ * @param String api_action api's action name.
+ * @param String mode r/w mode , usually read.
+ */
+function displayHelpForId(help_point, is_mobile, target_controller,
+    current_action, csrf_token_key, csrf_token_value, help_group_id,
+    api_controller, api_action, mode)
+{
+    if((elt("help-frame").style.display) === "block") {
+        toggleHelp('help-frame', is_mobile, target_controller);
+    }
+    var tl = eval('(' + help_point.getAttribute("data-tl") + ')');
+    var back_params = eval('(' + help_point.getAttribute("data-back-params")
+    + ')');
+    getPageWithCallback("?c=" + api_controller + "&group_id=" +
+        help_group_id + "&" +
+        "arg=" + mode + "&" +
+        "a=" + api_action + "&" +
+        csrf_token_key + '=' + csrf_token_value + "&" +
+        "page_name=" + help_point.getAttribute("data-pagename"),
+        'json',
+        function (data)
+        {
+            elt("help-frame-body").innerHTML = parseWikiContent(
+                data.wiki_content,
+                data.group_id,
+                data.page_id,
+                target_controller,
+                csrf_token_key,
+                csrf_token_value
+            );
+            elt('page_name').innerHTML = data.page_title + ' [<a href="' +
+            getEditLink(
+                target_controller,
+                current_action,
+                csrf_token_key,
+                csrf_token_value,
+                help_group_id,
+                data.page_title,
+                back_params) + '">' +
+            tl["wiki_view_edit"] + '</a>]';
+            toggleHelp('help-frame', is_mobile, target_controller);
+        },
+        function (status)
+        {
+            toggleHelp('help-frame', is_mobile, target_controller);
+        });
+    event.preventDefault();
+}
+/*
+ * Simple function to construct the Wiki Edit hyperlink with passed in params.
+ * @param String target_controller Edit page's controller name.
+ * @param String csrf_token_key teh dynamic name used for CSRF token var.
+ * @param String csrf_token_value The CSRF token to render edit page.
+ * @param String group_id GroupId of the group which has the wiki.
+ * @param String page_name Page name,unique Identifier for wiki edit page.
+ * @return String the edit link
+ */
+function getEditLink(target_controller, current_action, csrf_token_key,
+    csrf_token_value, group_id, page_name, back_params)
+{
+    var edit_link = '?c=' + target_controller +
+        '&' + csrf_token_key + '=' + csrf_token_value +
+        '&group_id=' + group_id +
+        '&arg=edit' +
+        '&a=wiki' +
+        '&page_name=' + page_name +
+        '&back_params[open_help_page]=' + page_name +
+        '&back_params[c]=' + target_controller +
+        '&back_params[a]=' + current_action;
+    for (var key in back_params) {
+        var value = back_params[key];
+        edit_link += "&back_params[" + key + "]=" + value;
+    }
+    return edit_link;
+}
\ No newline at end of file
diff --git a/views/elements/api_element.php b/views/elements/api_element.php
index 64bfbcc..9c5d0fe 100644
--- a/views/elements/api_element.php
+++ b/views/elements/api_element.php
@@ -85,6 +85,7 @@ class ApiElement extends Element implements CrawlConstants
             $out_array['group_name'] = $data['GROUP']['GROUP_NAME'];
             $out_array['page_id'] = $data['PAGE_ID'];
             $out_array['page_name'] = $data['PAGE_NAME'];
+            $out_array['page_title'] = $data['PAGE_TITLE'];
             $http_code = "200 OK";
         } else {
             if(!$logged_in) {
@@ -92,7 +93,7 @@ class ApiElement extends Element implements CrawlConstants
                 $http_code = "401 Unauthorized";
             }
         }
-        if($can_edit) {
+        if($can_edit && $data['PAGE']) {
             $out_array["can_edit"] = true;
         }
         if(isset($data['errors']) && count($data['errors']) > 0) {
diff --git a/views/helpers/helpbutton_helper.php b/views/helpers/helpbutton_helper.php
index 9347d0b..993606c 100644
--- a/views/helpers/helpbutton_helper.php
+++ b/views/helpers/helpbutton_helper.php
@@ -52,23 +52,9 @@ class HelpbuttonHelper extends Helper
      */
     function __construct()
     {
-        $this->localizationdata = "{" .
-            'wiki_view_edit :"' . tl('wiki_view_edit') . '",' .
-            'wiki_view_read :"' . tl('wiki_view_read') . '"' .
-            "}";
-        $this->backParams = "{";
-        $back_params_array = array_diff_key($_REQUEST, array_flip(
-            array("a", "c", "u","p", CSRF_TOKEN, "open_help_page")
-        ));
-        $back_params_only_keys = array_keys($back_params_array);
-        $last_key = end($back_params_only_keys);
-        foreach($back_params_array as $key => $value) {
-            $this->backParams .= $key . ' : "' . $value . '"';
-            if($key != $last_key) {
-                $this->backParams .= ',';
-            }
-        }
-        $this->backParams .= "}";
+        $this->isHelpInitialized = false;
+        $this->localizationdata = NULL;
+        $this->backParams = NULL;
         parent::__construct();
     }
     /**
@@ -82,6 +68,28 @@ class HelpbuttonHelper extends Helper
      */
     public function render($help_point_id, $csrf_token_value)
     {
+        if ($this->isHelpInitialized == false) {
+            //Set only once.
+            $this->isHelpInitialized = true;
+            $this->localizationdata = "{" .
+                    'wiki_view_edit :"' . tl('wiki_view_edit') . '",' .
+                    'wiki_view_read :"' . tl('wiki_view_read') . '"' .
+                    "}";
+            $this->backParams = "{";
+            $back_params_array = array_diff_key($_REQUEST, array_flip(
+                array("a", "c", "u", "p", CSRF_TOKEN, "open_help_page")
+            ));
+            array_walk($back_params_array, array($this, 'clean'));
+            $back_params_only_keys = array_keys($back_params_array);
+            $last_key = end($back_params_only_keys);
+            foreach ($back_params_array as $key => $value) {
+                $this->backParams .= $key . ' : "' . $value . '"';
+                if ($key != $last_key) {
+                    $this->backParams .= ',';
+                }
+            }
+            $this->backParams .= "}";
+        }
         $is_mobile = MOBILE ? "true" : "false";
         $wiki_group_id = HELP_GROUP_ID;
         $api_controller = "api";
@@ -91,16 +99,33 @@ class HelpbuttonHelper extends Helper
                     class="help-button default"
                     data-tl=\'' . $this->localizationdata . '\'
                     data-back-params=\'' . $this->backParams . '\'
-                    onclick="javascript:displayHelpForId(
-                    this,'
-        . $is_mobile . ',\''
-        . $_REQUEST['c'] . '\',\''
-        . $_REQUEST['a'] . '\',\''
-        . CSRF_TOKEN . '\',\''
-        . $csrf_token_value . "','$wiki_group_id','$api_controller',"
-        . "'$api_wiki_action','$api_wiki_mode" . '\')" '
-        . 'data-pagename="' . $help_point_id . '"> '
-        . tl('wiki_question_mark') .'</button>';
+                    onclick="javascript:displayHelpForId(this,'
+                . $is_mobile . ',\''
+                . $_REQUEST['c'] . '\',\''
+                . $_REQUEST['a'] . '\',\''
+                . CSRF_TOKEN . '\',\''
+                . $csrf_token_value . "','$wiki_group_id','$api_controller',"
+                . "'$api_wiki_action','$api_wiki_mode" . '\')" '
+                . 'data-pagename="' . $help_point_id . '"> '
+                . tl('wiki_question_mark') . '</button>';
+    }
+    /**
+     * Used to clean strings that might be tainted as originate from the user
+     *
+     * @param mixed $value tainted data
+     * @param mixed $default if $value is not set default value is returned,
+     *     this isn't used much since if the error_reporting is E_ALL
+     *     or -1 you would still get a Notice.
+     * @return string the clean input matching the type provided
+     */
+    private function clean($value, $default = NULL) {
+        if (isset($value)) {
+            $value2 = str_replace("&amp;", "&", $value);
+            $clean_value = @htmlentities($value2, ENT_QUOTES, "UTF-8");
+        } else {
+            $clean_value = $default;
+        }
     }
+
 }
 ?>
\ No newline at end of file
diff --git a/views/layouts/web_layout.php b/views/layouts/web_layout.php
index 286b9d5..1105cab 100755
--- a/views/layouts/web_layout.php
+++ b/views/layouts/web_layout.php
@@ -234,6 +234,13 @@ class WebLayout extends Layout
         ?>
         <script type="text/javascript" src="./scripts/basic.js" ></script>
         <?php
+        if($this->view->helper('helpbutton')->isHelpInitialized){
+            if (!isset($data["INCLUDE_SCRIPTS"])) {
+                $data["INCLUDE_SCRIPTS"] = array();
+            }
+
+            $data["INCLUDE_SCRIPTS"][] = "help";
+        }
         if(isset($data['INCLUDE_SCRIPTS'])) {
             foreach($data['INCLUDE_SCRIPTS'] as $script_name) {
                 if($script_name == "math") {
-- 
1.9.3 (Apple Git-50)


From 9fb4c61a4f55ba0c32c0cf8ec452e7004f19687d Mon Sep 17 00:00:00 2001
From: epinapala <epinapala@ebay.com>
Date: Mon, 10 Nov 2014 12:20:31 -0800
Subject: [PATCH 2/2] - Adding back modified default.db that holds new Help
 page changes.

---
 data/default.db | Bin 124928 -> 128000 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)

diff --git a/data/default.db b/data/default.db
index 325ec6216fab0f9a957d59ee3f85d77282d9ebb9..c4042b8e736d53a2511af7b97bc085902d4ec24d 100644
GIT binary patch
-- 
1.9.3 (Apple Git-50)

