home *** CD-ROM | disk | FTP | other *** search
/ grafika-wolowiec.cba.pl / grafika-wolowiec.cba.pl.tar / grafika-wolowiec.cba.pl / res / x5engine.php < prev    next >
PHP Script  |  2014-01-24  |  212KB  |  5,433 lines

  1. <?php
  2.  
  3. /**
  4.  * This file contains all the classes used by the PHP code created by WebSite X5
  5.  *
  6.  * @category  X5engine
  7.  * @package   X5engine
  8.  * @copyright 2013 - Incomedia Srl
  9.  * @license   Copyright by Incomedia Srl http://incomedia.eu
  10.  * @version   WebSite X5 Professional 10.0.0
  11.  * @link      http://websitex5.com
  12.  */
  13.  
  14. @session_start();
  15.  
  16. $imSettings = Array();
  17. $l10n = Array();
  18. $phpError = false;
  19. $ImMailer = new ImSendEmail();
  20.  
  21. @include_once "imemail.inc.php";        // Email class - Static
  22. @include_once "x5settings.php";            // Basic settings - Dynamically created by WebSite X5
  23. @include_once "blog.inc.php";            // Blog data - Dynamically created by WebSite X5
  24. @include_once "access.inc.php";            // Private area data - Dynamically created by WebSite X5
  25. @include_once "l10n.php";                // Localizations - Dynamically created by WebSite X5
  26. @include_once "search.inc.php" ;        // Search engine data - Dynamically created by WebSite X5
  27.  
  28.  
  29.  
  30. /**
  31.  * Blog class
  32.  * @access public
  33.  */
  34. class imBlog
  35. {
  36.  
  37.     var $comments;
  38.  
  39.     /**
  40.      * Format a timestamp
  41.      * 
  42.      * @param string $ts The timestamp
  43.      * 
  44.      * @return string
  45.      */
  46.     function formatTimestamp($ts)
  47.     {
  48.         return date("d/m/Y H:i:s", strtotime($ts));
  49.     }
  50.  
  51.     /**
  52.      * Show the pagination links
  53.      * 
  54.      * @param string  $baseurl  The base url of the pagination
  55.      * @param integer $start    Start from this page
  56.      * @param integer $length   For this length
  57.      * @param integer $count    Count of the current objects to show
  58.      * 
  59.      * @return void
  60.      */
  61.     function paginate($baseurl = "", $start, $length, $count)
  62.     {
  63.         echo "<div style=\"text-align: center;\">";
  64.         if ($start > 0)
  65.             echo "<a href=\"" . $baseurl . "start=" . ($start - $length) . "&length=" . $length . "\" class=\"imCssLink\">" . l10n("blog_pagination_prev", "<< Newer posts") . "</a>";
  66.         if ($start > 0 && $count > $start + $length)
  67.             echo " | ";
  68.         if ($count > $start + $length)
  69.             echo "<a href=\"" . $baseurl . "start=" . ($start + $length) . "&length=" . $length . "\" class=\"imCssLink\">" . l10n("blog_pagination_next", "Older posts >>") . "</a>";
  70.         echo "</div>";
  71.     }
  72.  
  73.     /**
  74.      * Provide the page title tag to be shown in the header
  75.      * Keep track of the page using the $_GET vars provided:
  76.      *     - id
  77.      *     - category
  78.      *     - tag
  79.      *     - month
  80.      *     - search
  81.      *
  82.      * @param string $basetitle The base title of the blog, to be appended after the specific page title
  83.      * @param string $separator The separator char, default "-"
  84.      * 
  85.      * @return string The page title
  86.      */
  87.     function pageTitle($basetitle, $separator = "-") {
  88.         global $imSettings;
  89.  
  90.         if (isset($_GET['id']) && isset($imSettings['blog']['posts'][$_GET['id']])) {
  91.             // Post
  92.             return htmlspecialchars($imSettings['blog']['posts'][$_GET['id']]['title'] . $separator . $basetitle);
  93.         } else if (isset($_GET['category']) && isset($imSettings['blog']['posts_cat'][$_GET['category']])) {
  94.             // Category
  95.             return htmlspecialchars(str_replace("_", " ", $_GET['category']) . $separator . $basetitle);
  96.         } else if (isset($_GET['tag'])) {
  97.             // Tag
  98.             return htmlspecialchars(strip_tags($_GET['tag']) . $separator . $basetitle);
  99.         } else if (isset($_GET['month']) && is_numeric($_GET['month']) && strlen($_GET['month']) == 6) {
  100.             // Month
  101.             return htmlspecialchars(substr($_GET['month'], 4, 2) . "/" . substr($_GET['month'], 0, 4) . $separator . $basetitle);
  102.         } else if (isset($_GET['search'])) {
  103.             // Search
  104.             return htmlspecialchars(strip_tags(urldecode($_GET['search'])) . $separator . $basetitle);
  105.         }
  106.         
  107.         // Default (Home page): Show the blog description
  108.         return htmlspecialchars($basetitle);
  109.     }
  110.  
  111.     /**
  112.      * Show the page description to be echoed in the metatag description tag.
  113.      * Keep track of the page using the $_GET vars provided:
  114.      *     - id
  115.      *     - category
  116.      *     - tag
  117.      *     - month
  118.      *     - search
  119.      *
  120.      * @return string The required description
  121.      */
  122.     function pageDescription()
  123.     {
  124.         global $imSettings;
  125.         
  126.         if (isset($_GET['id']) && isset($imSettings['blog']['posts'][$_GET['id']])) {
  127.             // Post
  128.             return htmlspecialchars(str_replace("\n", " ", $imSettings['blog']['posts'][$_GET['id']]['summary']));
  129.         } else if (isset($_GET['category'])) {
  130.             // Category
  131.             return htmlspecialchars(strip_tags($_GET['category']));
  132.         } else if (isset($_GET['tag'])) {
  133.             // Tag
  134.             return htmlspecialchars(strip_tags($_GET['tag']));
  135.         } else if (isset($_GET['month'])) {
  136.             // Month
  137.             return htmlspecialchars(substr($_GET['month'], 4, 2) . "/" . substr($_GET['month'], 0, 4));
  138.         } else if (isset($_GET['search'])) {
  139.             // Search
  140.             return htmlspecialchars(strip_tags(urldecode($_GET['search'])));
  141.         }
  142.         
  143.         // Default (Home page): Show the blog description
  144.         return htmlspecialchars(str_replace("\n", " ", $imSettings['blog']['description']));
  145.     }
  146.  
  147.     /**
  148.      * Get the last update date
  149.      *
  150.      * @return string
  151.      */
  152.     function getLastModified()
  153.     {
  154.         global $imSettings;
  155.         $c = $this->comments->getComments($_GET['id']);
  156.         if ($_GET['id'] != "" && $c != -1) {
  157.             return $this->formatTimestamp($c[count($c)-1]['timestamp']);
  158.         } else {
  159.             $last_post = $imSettings['blog']['posts'];
  160.             $last_post = array_shift($last_post);
  161.             return $last_post['timestamp'];
  162.         }
  163.     }
  164.  
  165.     /**
  166.      * Show a post
  167.      * 
  168.      * @param string  $id    the post id
  169.      * @param intger  $ext   Set 1 to show as extended
  170.      * @param integer $first Set 1 if this is the first post in the list
  171.      *
  172.      * @return void
  173.      */
  174.     function showPost($id, $ext=0, $first=0)
  175.     {
  176.         global $imSettings;
  177.         
  178.         $bs = $imSettings['blog'];
  179.         $bp = isset($bs['posts'][$id]) ? $bs['posts'][$id] : false;
  180.  
  181.         if (is_bool($bp) && !$bp)
  182.             return;
  183.  
  184.  
  185.         $title = !$ext ? "<a href=\"?id=" . $id . "\">" . $bp['title'] . "</a>" : $bp['title'];
  186.         echo "<h2 id=\"imPgTitle\" style=\"display: block;\">" . $title . "</h2>\n";
  187.         echo "<div class=\"imBreadcrumb\" style=\"display: block;\">" . l10n('blog_published_by') . "<strong> " . $bp['author'] . " </strong>";
  188.         echo l10n('blog_in') . " <a href=\"?category=" . urlencode($bp['category']) . "\" target=\"_blank\" rel=\"nofollow\">" . $bp['category'] . "</a> · " . $bp['timestamp'];
  189.  
  190.         // Media audio/video
  191.         if (isset($bp['media'])) {
  192.             echo " · <a href=\"" . $bp['media'] . "\">Download " . basename($bp['media']) . "</a>";
  193.         }
  194.  
  195.         if (count($bp['tag']) > 0) {
  196.             echo "<br />Tags: ";
  197.             for ($i = 0; $i < count($bp['tag']); $i++) {
  198.                 echo "<a href=\"?tag=" . $bp['tag'][$i] . "\">" . $bp['tag'][$i] . "</a>";
  199.                 if ($i < count($bp['tag']) - 1)
  200.                     echo ", ";
  201.             }
  202.         }
  203.         echo "</div>\n";
  204.  
  205.         if ($ext || $first && $imSettings['blog']['post_type'] == 'firstshown' || $imSettings['blog']['post_type'] == 'allshown') {
  206.             echo "<div class=\"imBlogPostBody\">\n";
  207.  
  208.             if (isset($bp['mediahtml']) || isset($bp['slideshow'])) {
  209.                 // Audio/video
  210.                 if (isset($bp['mediahtml'])) {
  211.                     echo $bp['mediahtml'] . "\n";
  212.                 }
  213.  
  214.                 // Slideshow
  215.                 if (isset($bp['slideshow'])) {
  216.                     echo $bp['slideshow'];
  217.                 }
  218.                 echo "<div style=\"clear: both; margin-bottom: 10px;\"></div>";
  219.             }
  220.             echo $bp['body'];
  221.  
  222.             if (count($bp['sources']) > 0) {
  223.                 echo "\t<div class=\"imBlogSources\">\n";
  224.                 echo "\t\t<b>" . l10n('blog_sources') . "</b>:<br />\n";
  225.                 echo "\t\t<ul>\n";
  226.  
  227.                 foreach ($bp['sources'] as $source) {
  228.                     echo "\t\t\t<li>" . $source . "</li>\n";
  229.                 }
  230.  
  231.                 echo "\t\t</ul>\n\t</div>\n";
  232.             }
  233.             echo (isset($imSettings['blog']['addThis']) ? "<br />" . $imSettings['blog']['addThis'] : "") . "<br /><br /></div>\n";
  234.         } else {
  235.             echo "<div class=\"imBlogPostSummary\">" . $bp['summary'] . "</div>\n";
  236.         }
  237.         if ($ext == 0) {
  238.             echo "<div class=\"imBlogPostRead\"><a class=\"imCssLink\" href=\"?id=" . $id . "\">" . l10n('blog_read_all') ." »</a></div>\n";
  239.         } else if (isset($bp['foo_html'])) {
  240.             echo "<div class=\"imBlogPostFooHTML\">" . $bp['foo_html'] . "</div>\n";
  241.         }
  242.  
  243.         if ($ext != 0 && $bp['comments']) {
  244.             echo "<div id=\"blog-topic\">\n";
  245.             $this->comments = new ImTopic($imSettings['blog']['file_prefix'] . 'pc' . $id, "../", "index.php?id=" . $id);
  246.             // Show the comments
  247.             if ($bs['sendmode'] == "db")
  248.                 $this->comments->loadDb($bs['dbhost'], $bs['dbuser'], $bs['dbpassword'], $bs['dbname'], $bs['dbtable']);
  249.             else
  250.                 $this->comments->loadXML($bs['folder']);
  251.             $this->comments->setPostUrl("index.php?id=" . $id);
  252.             if ($imSettings['blog']['comment_type'] != "stars") {
  253.                 $this->comments->showSummary($bs['comment_type'] != "comment");
  254.                 $this->comments->showComments($bs['comment_type'] != "comment", $bs["comments_order"], $bs["abuse"]);
  255.                 $this->comments->showForm($bs['comment_type'] != "comment", $bs['captcha'], $bs['moderate'], $bs['email'], "blog", $imSettings['general']['url'] . "/admin/blog.php?category=" . str_replace(" ", "_", $imSettings['blog']['posts'][$id]['category']) . "&post=" . $id);
  256.             } else {
  257.                 $this->comments->showRating();
  258.             }
  259.             echo "</div>";
  260.             echo "<script type=\"text/javascript\">x5engine.boot.push('x5engine.topic({ target: \\'#blog-topic\\', scrollbar: false})', false, 6);</script>\n";
  261.         }
  262.     }
  263.  
  264.     /**
  265.      * Find the posts tagged with tag
  266.      * 
  267.      * @param string $tag The searched tag
  268.      *
  269.      * @return void
  270.      */
  271.     function showTag($tag)
  272.     {
  273.         global $imSettings;
  274.         $start = isset($_GET['start']) ? max(0, (int)$_GET['start']) : 0;
  275.         $length = isset($_GET['length']) ? (int)$_GET['length'] : 5;
  276.  
  277.         if (count($imSettings['blog']['posts']) == 0)
  278.             return;
  279.         $bps = array();
  280.         foreach ($imSettings['blog']['posts'] as $id => $post) {
  281.             if (in_array($tag, $post['tag'])) {
  282.                 $bps[] = $post;
  283.             }
  284.         }
  285.         $bpsc = count($bps);
  286.         for($i = $start; $i < ($bpsc < $start + $length ? $bpsc : $start + $length); $i++) {
  287.             if ($i > $start)
  288.                 echo "<div class=\"imBlogSeparator\"></div>";
  289.             $this->showPost($bps[$i]['id'], 0, ($i == $start ? 1 : 0));
  290.         }
  291.         $this->paginate("?tag=" . $tag . "&", $start, $length, $bpsc);
  292.     }
  293.  
  294.     /**
  295.      * Find the post in a category
  296.      * 
  297.      * @param strmg $category the category ID
  298.      *
  299.      * @return void
  300.      */
  301.     function showCategory($category)
  302.     {
  303.         global $imSettings;
  304.         $start = isset($_GET['start']) ? max(0, (int)$_GET['start']) : 0;
  305.         $length = isset($_GET['length']) ? (int)$_GET['length'] : 5;
  306.  
  307.         $bps = isset($imSettings['blog']['posts_cat'][$category]) ? $imSettings['blog']['posts_cat'][$category] : false;
  308.         if (!is_array($bps))
  309.             return;
  310.         $bpsc = count($bps);
  311.         for($i = $start; $i < ($bpsc < $start + $length ? $bpsc : $start + $length); $i++) {
  312.             if ($i > $start)
  313.                 echo "<div class=\"imBlogSeparator\"></div>";
  314.             $this->showPost($bps[$i], 0, ($i == 0 ? 1 : 0));
  315.         }
  316.         $this->paginate("?category=" . $category . "&", $start, $length, $bpsc);
  317.     }
  318.  
  319.     /**
  320.      * Find the posts of the month
  321.      * 
  322.      * @param string $month The mont
  323.      *
  324.      * @return void
  325.      */
  326.     function showMonth($month)
  327.     {
  328.         global $imSettings;
  329.         $start = isset($_GET['start']) ? max(0, (int)$_GET['start']) : 0;
  330.         $length = isset($_GET['length']) ? (int)$_GET['length'] : 5;
  331.  
  332.         $bps = isset($imSettings['blog']['posts_month'][$month]) ? $imSettings['blog']['posts_month'][$month] : false;
  333.         if (!is_array($bps))
  334.             return;
  335.         $bpsc = count($bps);
  336.         for($i = $start; $i < ($bpsc < $start + $length ? $bpsc : $start + $length); $i++) {
  337.             if ($i > $start)
  338.                 echo "<div class=\"imBlogSeparator\"></div>";
  339.             $this->showPost($bps[$i], 0, ($i == $start ? 1 : 0));
  340.         }
  341.         $this->paginate("?month=" . $month . "&", $start, $length, $bpsc);
  342.     }
  343.  
  344.     /**
  345.      * Show the last n posts
  346.      * 
  347.      * @param integer $count the number of posts to show
  348.      *
  349.      * @return void
  350.      */
  351.     function showLast($count)
  352.     {
  353.         global $imSettings;
  354.         $start = isset($_GET['start']) ? max(0, (int)$_GET['start']) : 0;
  355.         $length = isset($_GET['length']) ? (int)$_GET['length'] : 5;
  356.  
  357.         $bps = array_keys($imSettings['blog']['posts']);
  358.         if (!is_array($bps))
  359.             return;
  360.         $bpsc = count($bps);
  361.         for($i = $start; $i < ($bpsc < $start + $length ? $bpsc : $start + $length); $i++) {
  362.             if ($i > $start)
  363.                 echo "<div class=\"imBlogSeparator\"></div>";
  364.             $this->showPost($bps[$i], 0, ($i == $start ? 1 : 0));
  365.         }
  366.         $this->paginate("?", $start, $length, $bpsc);
  367.     }
  368.  
  369.     /**
  370.      * Show the search results
  371.      * 
  372.      * @param string $search the search query
  373.      *
  374.      * @return void
  375.      */
  376.     function showSearch($search)
  377.     {
  378.         global $imSettings;
  379.         $start = isset($_GET['start']) ? max(0, (int)$_GET['start']) : 0;
  380.         $length = isset($_GET['length']) ? (int)$_GET['length'] : 5;
  381.  
  382.         $bps = array_keys($imSettings['blog']['posts']);
  383.         $j = 0;
  384.         if (is_array($bps)) {
  385.             $bpsc = count($bps);
  386.             $results = array();
  387.             for ($i = $start; $i < $bpsc; $i++) {
  388.                 if (stristr($imSettings['blog']['posts'][$bps[$i]]['title'], $search) || stristr($imSettings['blog']['posts'][$bps[$i]]['summary'], $search) || stristr($imSettings['blog']['posts'][$bps[$i]]['body'], $search)) {
  389.                     $results[] = $bps[$i];
  390.                     $j++;
  391.                 }
  392.             }
  393.             for ($i = $start; $i < ($j < $start + $length ? $j : $start + $length); $i++) {
  394.                 if ($i > $start)
  395.                     echo "<div class=\"imBlogSeparator\"></div>";
  396.                 $this->showPost($bps[$i], 0, ($i == $start ? 1 : 0));
  397.             }
  398.             $this->paginate("?search=" . $search . "&", $start, $length, $j);
  399.             if ($j == 0) {
  400.                 echo "<div class=\"imBlogEmpty\">Empty search</div>";
  401.             }
  402.         } else {
  403.             echo "<div class=\"imBlogEmpty\">Empty blog</div>";
  404.         }
  405.     }
  406.  
  407.     /**
  408.      * Show the categories sideblock
  409.      * 
  410.      * @param integer $n The number of categories to show
  411.      *
  412.      * @return void
  413.      */
  414.     function showBlockCategories($n)
  415.     {
  416.         global $imSettings;
  417.  
  418.         if (is_array($imSettings['blog']['posts_cat'])) {
  419.             $categories = array_keys($imSettings['blog']['posts_cat']);
  420.             array_multisort($categories);
  421.             echo "<ul>";
  422.             for ($i = 0; $i < count($categories) && $i < $n; $i++) {
  423.                 $post = $imSettings['blog']['posts'][$imSettings['blog']['posts_cat'][$categories[$i]][0]];
  424.                 echo "<li><a href=\"?category=" . $categories[$i] . "\">" . $post['category'] . "</a></li>";
  425.             }
  426.             echo "</ul>";
  427.         }
  428.     }
  429.  
  430.     /**
  431.      * Show the cloud sideblock
  432.      * 
  433.      * @param string $type TAGS or CATEGORY
  434.      *
  435.      * @return void;
  436.      */
  437.     function showBlockCloud($type)
  438.     {
  439.         global $imSettings;
  440.  
  441.         $max = 0;
  442.         $min_em = 0.95;
  443.         $max_em = 1.25;
  444.         if ($type == "tags") {
  445.             $tags = array();
  446.             foreach ($imSettings['blog']['posts'] as $id => $post) {
  447.                 foreach ($post['tag'] as $tag) {
  448.                     if (!isset($tags[$tag]))
  449.                         $tags[$tag] = 1;
  450.                     else
  451.                         $tags[$tag] = $tags[$tag] + 1;
  452.                     if ($tags[$tag] > $max)
  453.                         $max = $tags[$tag];
  454.                 }
  455.             }
  456.             if (count($tags) == 0)
  457.                 return;
  458.  
  459.             $tags = shuffleAssoc($tags);
  460.             
  461.             foreach ($tags as $name => $number) {
  462.                 $size = number_format(($number/$max * ($max_em - $min_em)) + $min_em, 2, '.', '');
  463.                 echo "\t\t\t<span class=\"imBlogCloudItem\" style=\"font-size: " . $size . "em;\">\n";
  464.                 echo "\t\t\t\t<a href=\"?tag=" . $name . "\" style=\"font-size: " . $size . "em;\">" . $name . "</a>\n";
  465.                 echo "\t\t\t</span>\n";
  466.             }
  467.         } else if ($type == "categories") {
  468.             $categories = array();
  469.             foreach ($imSettings['blog']['posts'] as $id => $post) {
  470.                 if (!isset($categories[$post['category']]))
  471.                     $categories[$post['category']] = 1;
  472.                 else
  473.                     $categories[$post['category']] = $categories[$post['category']] + 1;
  474.                 if ($categories[$post['category']] > $max)
  475.                     $max = $categories[$post['category']];
  476.             }
  477.             if (count($categories) == 0)
  478.                 return;
  479.  
  480.             $categories = shuffleAssoc($categories);
  481.  
  482.             foreach ($categories as $name => $number) {
  483.                 $size = number_format(($number/$max * ($max_em - $min_em)) + $min_em, 2, '.', '');
  484.                 echo "\t\t\t<span class=\"imBlogCloudItem\" style=\"font-size: " . $size . "em;\">\n";
  485.                 echo "\t\t\t\t<a href=\"?category=" . $name . "\" style=\"font-size: " . $size . "em;\">" . $name . "</a>\n";
  486.                 echo "\t\t\t</span>\n";
  487.             }
  488.         }
  489.     }
  490.  
  491.     /**
  492.      * Show the month sideblock
  493.      * 
  494.      * @param integer $n Number of entries
  495.      *
  496.      * @return void
  497.      */
  498.     function showBlockMonths($n)
  499.     {
  500.         global $imSettings;
  501.  
  502.         if (is_array($imSettings['blog']['posts_month'])) {
  503.             $months = array_keys($imSettings['blog']['posts_month']);
  504.             array_multisort($months, SORT_DESC);
  505.             echo "<ul>";
  506.             for ($i = 0; $i < count($months) && $i < $n; $i++) {
  507.                 echo "<li><a href=\"?month=" . $months[$i] . "\">" . substr($months[$i], 4) . "/" . substr($months[$i], 0, 4) . "</a></li>";
  508.             }
  509.             echo "</ul>";
  510.         }
  511.     }
  512.  
  513.     /**
  514.      * Show the last posts block
  515.      * 
  516.      * @param integer $n The number of post to show
  517.      *
  518.      * @return void
  519.      */
  520.     function showBlockLast($n)
  521.     {
  522.         global $imSettings;
  523.  
  524.         if (is_array($imSettings['blog']['posts'])) {
  525.             echo "<ul>";
  526.             for ($i = 0; $i < count($imSettings['blog']['posts']) && $i < $n; $i++) {
  527.                 $post = array_keys($imSettings['blog']['posts']);
  528.                 $post = $imSettings['blog']['posts'][$post[$i]];
  529.                 echo "<li><a href=\"?id=" . $post['id'] . "\">" . $post['title'] . "</a></li>";
  530.             }
  531.             echo "</ul>";
  532.         }
  533.     }
  534. }
  535.  
  536.  
  537.  
  538. /**
  539.  * Captcha handling class
  540.  * @access public
  541.  */
  542. class imCaptcha {
  543.  
  544.     /**
  545.      * Show the captcha chars
  546.      */
  547.     function show($sCode)
  548.     {
  549.         global $oNameList;
  550.         global $oCharList;
  551.  
  552.         $text = "<!DOCTYPE HTML>
  553.             <html>
  554.           <head>
  555.           <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">
  556.           <meta http-equiv=\"pragma\" content=\"no-cache\">
  557.           <meta http-equiv=\"cache-control\" content=\"no-cache, must-revalidate\">
  558.           <meta http-equiv=\"expires\" content=\"0\">
  559.           <meta http-equiv=\"last-modified\" content=\"\">
  560.           </head>
  561.           <body style=\"margin: 0; padding: 0; border-collapse: collapse;\">";
  562.  
  563.         for ($i=0; $i<strlen($sCode); $i++)
  564.             $text .= "<img style=\"margin:0; padding:0; border: 0; border-collapse: collapse; width: 24px; height: 24px; position: absolute; top: 0; left: " . (24 * $i) . "px;\" src=\"imcpa_".$oNameList[substr($sCode, $i, 1)].".gif\" width=\"24\" height=\"24\">";
  565.  
  566.         $text .= "</body></html>";
  567.  
  568.         return $text;
  569.     }
  570.  
  571.     /**
  572.      * Check the sent data
  573.      * @param sCode The correct code (string)
  574.      * @param dans The user's answer (string)
  575.      */
  576.     function check($sCode, $ans)
  577.     {
  578.         global $oCharList;
  579.         if ($ans == "")
  580.             return '-1';
  581.         for ($i=0; $i<strlen($sCode); $i++)
  582.           if ($oCharList[substr(strtoupper($sCode), $i, 1)] != substr(strtoupper($ans), $i, 1))
  583.             return '-1';
  584.         return '0';
  585.     }
  586. }
  587.  
  588.  
  589.  
  590. /**
  591.  * Provide support for sending and saving a cart order as well as checking the coupon codes
  592.  */
  593. class ImCart {
  594.  
  595.     /**
  596.      * Contains the coupon data structured as follows:
  597.      * "cart" => array(
  598.      *        "coupon" => "CARTCOUPON",
  599.      *        "amount" => 10
  600.      *    ),
  601.      *    "products" => array(
  602.      *        "COUPONFORPROD1" => "prod1",
  603.      *        "COUPONFORPROD2" => "prod2",
  604.      *        "COUPONFORPROD3" => "prod1"
  605.      *    )
  606.      *    
  607.      * @var Array
  608.      */
  609.     var $couponData;
  610.  
  611.     /**
  612.      * Maximum coupon requests every 60 seconds. This is set to prevent the coupon spoofing.
  613.      * Set to 0 to disable the requests limit.
  614.      * 
  615.      * @var integer
  616.      */
  617.     var $couponRequestsPerMinute = 0;
  618.  
  619.     /**
  620.      * The public folder path used to store the anti-spoofing log to protect the coupon codes
  621.      * 
  622.      * @var string
  623.      */
  624.     var $publicFolder;
  625.  
  626.     /**
  627.      * Save the order data with the following structure:
  628.      *    "orderNo": "",
  629.      *    "userInvoiceData": {},
  630.      *    "userShippingData": {},
  631.      *    "shipping": {
  632.      *        "name": "",
  633.      *        "description": "",
  634.      *        "email_text": "",
  635.      *        "price": "",
  636.      *        "rawPrice":
  637.      *        "vat":""
  638.      *        "rawVat":
  639.      *    },
  640.      *    "payment": {
  641.      *        "name": "",
  642.      *        "description":"",
  643.      *        "price": "",
  644.      *        "rawPrice":""
  645.      *        "email_text": "",
  646.      *        "vat": "",
  647.      *        "rawVat":""
  648.      *        "html": ""
  649.      *    },
  650.      *    "products": [{
  651.      *        "name": "",
  652.      *        "description": "",
  653.      *        "option": "",
  654.      *        "suboption": "",
  655.      *        "rawSinglePrice": "",
  656.      *        "rawPrice": "",
  657.      *        "rawFullPrice": "",
  658.      *        "singlePrice": "",
  659.      *        "singleFullPrice": "",
  660.      *        "price": "",
  661.      *        "fullPrice": "",
  662.      *        "quantity": "",
  663.      *        "vat": ""
  664.      *    }],
  665.      *    "rawTotalPrice": "",
  666.      *    "rawTalVat": "",
  667.      *    "totalPrice": "",
  668.      *    "totalVat": "",
  669.      *    "coupon": "",
  670.      *    "currency": ""
  671.      * @var array
  672.      */
  673.     var $orderData;
  674.  
  675.     /**
  676.      * Database connection
  677.      * @var boolean
  678.      */
  679.     var $db = false;
  680.     var $table_prefix = "";
  681.  
  682.     /**
  683.      * Contains the cart settings
  684.      * @var array
  685.      */
  686.     var $settings = array(
  687.         'orders_table' => 'orders',
  688.         'shipping_addresses_table' => 'shipping_addresses',
  689.         'invoice_addresses_table' => 'invoice_addresses',
  690.         'products_table' => 'products',
  691.         'force_sender' => false,
  692.         'email_opening' => '',
  693.         'email_closing' => '',
  694.         'useCSV' => false,
  695.         'header_bg_color' => '#FFD34F',
  696.         'header_text_color' => '#404040',
  697.         'cell_bg_color' => '#FFFFFF',
  698.         'cell_text_color' => '#000000',
  699.         'border_color' => '#D3D3D3',
  700.         'owner_email' => '',
  701.         'vat_type' => 'none'
  702.     );
  703.  
  704.     function setSettings($data)
  705.     {
  706.         // Copy the settings preserving the default data when a key is missing
  707.         foreach ($data as $key => $value)
  708.             $this->settings[$key] = $value;
  709.     }
  710.  
  711.     function setOrderData($data)
  712.     {
  713.         // Sanitize the form data
  714.         if (isset($data['userInvoiceData'])) {
  715.             foreach ($data['userInvoiceData'] as $key => $value) {
  716.                 if (isset($value['value']) && isset($value['label'])) {
  717.                     $data['userInvoiceData'][$key] = array(
  718.                         "label" => strip_tags($value['label']),
  719.                         "value" => strip_tags($value['value'])
  720.                     );
  721.                 }
  722.             }
  723.         }
  724.         if (isset($data['userShippingData'])) {
  725.             foreach ($data['userShippingData'] as $key => $value) {
  726.                 if (isset($value['value']) && isset($value['label'])) {
  727.                     $data['userShippingData'][$key] = array(
  728.                         "label" => strip_tags($value['label']),
  729.                         "value" => strip_tags($value['value'])
  730.                     );
  731.                 }
  732.             }
  733.         }
  734.         // As some servers escape the double quotes in the HTML code sent via POST,
  735.         // let's check if we have to unescape the payment HTML code using a test HTML sent by JS
  736.         // Do just 3 tries to avoid unwanted loops
  737.         $i = 3;
  738.         while (isset($data['payment']['htmlCheck']) && $i-- > 0 && $data['payment']['htmlCheck'] != "<a href=\"http://google.it\">escapecheck</a>") {
  739.             $data['payment']['htmlCheck'] = stripcslashes($data['payment']['htmlCheck']);
  740.             $data['payment']['html'] = stripcslashes($data['payment']['html']);
  741.         }
  742.         $this->orderData = $data;
  743.     }
  744.  
  745.     function setCouponData($data)
  746.     {
  747.         $this->couponData = $data;
  748.     }
  749.  
  750.     function setPublicFolder($path)
  751.     {
  752.         $this->publicFolder = $path;
  753.     }
  754.    
  755.     /**
  756.      * Check if the current IP can use a coupon code without spoofing
  757.      * 
  758.      * @return boolean
  759.      */
  760.     function canCheckCoupon() {
  761.         $path = "../" . $this->publicFolder . "/nospoof.txt";
  762.         if (!isset($_SERVER['REMOTE_ADDR']) || !@file_exists($path))
  763.             return true;
  764.         foreach (explode("\r\n", @file_get_contents($path)) as $line) {
  765.             $columns = explode("|", $line);
  766.             if (count($columns) == 3 && $columns[0] == $_SERVER['REMOTE_ADDR'] && strtotime($columns[1]) > time() - 60 && $columns[2] * 1 >= $this->couponRequestsPerMinute)
  767.                 return false;
  768.         }
  769.         return true;
  770.     }
  771.  
  772.     /**
  773.      * Save the current user fingerprint. Keeps track of the requests number for each IP address.
  774.      * 
  775.      * @return void
  776.      */
  777.     function saveFingerPrint() {
  778.         if (!isset($_SERVER['REMOTE_ADDR']))
  779.             return;
  780.  
  781.         $path = "../" . $this->publicFolder . "/nospoof.txt";
  782.         $content = "";
  783.         $old_content = "";
  784.         // Remove the old data from the file to avoid it to become too large
  785.         if (@file_exists($path))
  786.             $old_content = @file_get_contents($path);
  787.         $found = false;
  788.         foreach (explode("\r\n", $old_content) as $line) {
  789.             if (strlen($line) !== 0) {
  790.                 $columns = explode("|", $line);
  791.                 // If the line contains the current IP, let's check the last request date
  792.                 if ($columns[0] == $_SERVER['REMOTE_ADDR']) {
  793.                     if (strtotime($columns[1]) < time() - 60)
  794.                         $columns[2] = 0;
  795.                     $content .= $_SERVER['REMOTE_ADDR'] . "|" . date("Y-m-d H:i:s") . "|" . (($columns[2] * 1) + 1) . "\r\n";
  796.                     $found = true;
  797.                 } else if (strtotime($columns[1]) > time() - 60) {
  798.                     // Otherwise, let's save the entry only if it's recent
  799.                     $content .= $columns . "\r\n";
  800.                 }
  801.             }
  802.         }
  803.         if (!$found)
  804.             $content .= $_SERVER['REMOTE_ADDR'] . "|" . date('Y-m-d H:i:s') . "|1" . "\r\n";
  805.         @file_put_contents($path,  $content);
  806.     }
  807.  
  808.     /**
  809.      * Provide the discount data of a coupon code
  810.      * 
  811.      * @param  string $coupon The coupon code
  812.      * 
  813.      * @return string         The data in JSON format
  814.      */
  815.     function checkCoupon($coupon)
  816.     {
  817.         // Avoid spoofing by allowing only 6 tries in 1 minute
  818.         if ($this->couponRequestsPerMinute !== 0) {
  819.             if (!$this->canCheckCoupon())
  820.                 return "false";
  821.             $this->saveFingerPrint();
  822.         }
  823.  
  824.         $coupon = trim($coupon);
  825.  
  826.         if (!is_array($this->couponData))
  827.             return "false";
  828.  
  829.         // Check the cart coupon
  830.         if (isset($this->couponData['cart']) && $this->couponData['cart']['coupon'] == $coupon)
  831.             return '{ "type": "cart", "amount": ' . number_format($this->couponData['cart']['amount'], 4, '.', '') . ' }';
  832.  
  833.         // Check the products coupon
  834.         if (isset($this->couponData['products'])) {
  835.             $products = array();
  836.             foreach ($this->couponData['products'] as $productId => $productCoupon)
  837.                 if ($productCoupon == $coupon)
  838.                     $products[] = '"' . $productId . '"';
  839.             if (count($products))
  840.                 return '{ "type": "product", "ids": [' . implode(", ", $products) . '] }';    
  841.         }
  842.  
  843.         // No coupon!
  844.         return "false";
  845.     }
  846.  
  847.     /**
  848.      * Send the order email
  849.      * 
  850.      * @param boolean $isOwner true to send the owner's email
  851.      * @param string $from from address
  852.      * @param string $to to address
  853.      * 
  854.      * @return boolean
  855.      */
  856.     function sendEmail($isOwner, $from, $to)
  857.     {
  858.         
  859.         global $ImMailer;
  860.  
  861.         $separationLine = "<tr><td colspan=\"2\" style=\"margin: 10px 0; height: 10px; font-size: 0.1px; border-bottom: 1px solid [email:emailBackground];\"> </td></tr>\n";
  862.         $opt = 0;
  863.         $vat = 0;
  864.         $userDataTxt = "";
  865.         $userDataHtml = "";
  866.         $userDataCSVH = Array();
  867.         $userDataCSV = Array();
  868.         $shippingDataTxt = "";
  869.         $shippingDataHtml = "";
  870.         $shippingDataCSVH = Array();
  871.         $shippingDataCSV = Array();
  872.         $orderDataTxt = "";
  873.         $orderDataHTML = "";
  874.         $orderDataCSV = "";
  875.  
  876.         //
  877.         //    Set the invoice data
  878.         //
  879.         if (isset($this->orderData['userInvoiceData']) && is_array($this->orderData['userInvoiceData'])) {
  880.             $i = 0;
  881.             foreach ($this->orderData['userInvoiceData'] as $key => $value) {
  882.                 if (trim($value['value']) != "") {
  883.                     // Is it an email?
  884.                     if (preg_match('/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])' . '(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i', $value['value'])) {
  885.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td><a href=\"mailto:" . $value['value'] . "\">". $value['value'] . "</a></td>";
  886.                     } else if (preg_match('/^http[s]?:\/\/[a-zA-Z0-9\.\-]{2,}\.[a-zA-Z]{2,}/', $value['value'])) {
  887.                         // Is it an URL?
  888.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td><a href=\"" . $value['value'] . "\">". $value['value'] . "</a></td>";
  889.                     } else {
  890.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['value']) . "</td>";
  891.                     }
  892.  
  893.                     $userDataTxt .= $value['label'] . ": " . $value['value'] . "\n";
  894.                     $userDataHtml .= "\n\t\t\t<tr" . ($i%2 ? " bgcolor=\"[email:bodyBackgroundOdd]\"" : "") . ">" . $f . "\n\t\t\t</tr>";
  895.                     $userDataCSVH[] = $value['label'];
  896.                     $userDataCSV[] = $value['value'];
  897.                     $i++;
  898.                 }
  899.             }
  900.             if ($userDataHtml != "")
  901.                 $userDataHtml = "\n\t\t<table width=\"100%\" style=\"font: inherit;\">" . $userDataHtml . "\n\t\t</table>";
  902.         }
  903.  
  904.         //
  905.         //    Set the shipping data
  906.         //
  907.         if (isset($this->orderData['userShippingData']) && is_array($this->orderData['userShippingData'])) {
  908.             $i = 0;
  909.             foreach ($this->orderData['userShippingData'] as $key => $value) {
  910.                 if (trim($value['value']) != "") {
  911.                     // Is it an email?
  912.                     if (preg_match('/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])' . '(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i', $value['value'])) {
  913.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td><a href=\"mailto:" . $value['value'] . "\">". $value['value'] . "</a></td>";
  914.                     } else if (preg_match('/^http[s]?:\/\/[a-zA-Z0-9\.\-]{2,}\.[a-zA-Z]{2,}/', $value['value'])) {
  915.                         // Is it an URL?
  916.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td><a href=\"" . $value['value'] . "\">". $value['value'] . "</a></td>";
  917.                     } else {
  918.                         $f = "\n\t\t\t\t<td><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['label']) . ":</b></td>\n\t\t\t\t<td>" . str_replace(array("\\'", '\\"'), array("'", '"'), $value['value']) . "</td>";
  919.                     }
  920.  
  921.                     $shippingDataTxt .= $value['label'] . ": " . $value['value'] . "\n";
  922.                     $shippingDataHtml .= "\n\t\t\t<tr" . ($i%2 ? " bgcolor=\"[email:bodyBackgroundOdd]\"" : "") . ">" . $f . "\n\t\t\t</tr>";
  923.                     $shippingDataCSVH[] = $value['label'];
  924.                     $shippingDataCSV[] = $value['value'];
  925.                     $i++;
  926.                 }
  927.             }
  928.             if ($shippingDataHtml != "")
  929.                 $shippingDataHtml = "\n\t\t<table width=\"100%\" style=\"font: inherit;\">" . $shippingDataHtml . "\n\t\t</table>";
  930.         }
  931.         $userDataCSV = @implode(";", $userDataCSVH) . "\n" . @implode(";", $userDataCSV);
  932.         $shippingDataCSV = @implode(";", $shippingDataCSVH) . "\n" . @implode(";", $shippingDataCSV);
  933.         
  934.         //
  935.         //    Set the products data
  936.         //
  937.         if (isset($this->orderData['products']) && is_array($this->orderData['products'])) {
  938.             $i = 0;
  939.             foreach ($this->orderData['products'] as $key => $value)
  940.                 $opt = (isset($value["option"]) && $value["option"] != "null");
  941.             $vat = ($this->settings['vat_type'] != "none");
  942.             $colspan = 3 + ($opt ? 1 : 0) + ($vat ? 1 : 0);
  943.             $orderDataHTML = "<table cellpadding=\"5\" width=\"100%\" style=\"font: inherit; border-collapse: collapse;\">
  944.                                 <tr bgcolor=\"[email:bodyBackgroundOdd]\">
  945.                                     <td style=\"border: 1px solid [email:bodyBackgroundBorder];\">
  946.                                         <b>" . l10n("cart_name") . "</b>
  947.                                     </td>" .
  948.                                     ($opt ?
  949.                                         "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; min-width: 80px;\">
  950.                                             <b>" . l10n("product_option") . "</b>
  951.                                         </td>" : "") .
  952.                                     "<td style=\"border: 1px solid [email:bodyBackgroundBorder];\">
  953.                                         <b>" . l10n("cart_qty") . "</b>
  954.                                     </td>
  955.                                     <td style=\"border: 1px solid [email:bodyBackgroundBorder]; min-width: 70px;\">
  956.                                         <b>" . l10n("cart_price") . "</b>
  957.                                     </td>" .
  958.                                     ($vat ?
  959.                                         "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; min-width: 70px;\">
  960.                                             <b>" . ($this->settings['vat_type'] == "included" ? l10n("cart_vat_included") : l10n("cart_vat")) ."</b>
  961.                                         </td>" : "") .
  962.                                     "<td  style=\"border: 1px solid [email:bodyBackgroundBorder];\">
  963.                                         <b>" . l10n("cart_subtot") . "</b>
  964.                                     </td>
  965.                                 </tr>\n";
  966.  
  967.             $orderDataCSV = l10n("cart_name") . ";" . l10n("cart_descr") . ";" . ($opt ? l10n("product_option") . ";" : "") . l10n("cart_qty") . ";" . l10n("cart_price") . ";" . ($vat ? l10n("cart_vat") .";" : "") . l10n("cart_subtot");
  968.             foreach ($this->orderData['products'] as $key => $value) {
  969.                 // CSV
  970.                 $orderDataCSV .= "\n" 
  971.                 . strip_tags(str_replace(array("\n", "\r"), "", $value["name"])) . ";" 
  972.                 . strip_tags(str_replace(array("\n", "\r"), "", $value["description"])) . ";" 
  973.                 . (($opt && $value["option"] != "null") ? $value["option"] . ( $value["suboption"] != "null" ? $value["suboption"] . ";" : "") : "")
  974.                 . $value["quantity"] . ";"
  975.                 . ($this->settings['vat_type'] == "excluded" ? $value["singlePrice"] : $value['singlePricePlusVat']) . ";"
  976.                 . ($vat ? $value["vat"] .";" : "")
  977.                 . ($this->settings['vat_type'] == "excluded" ? $value["price"] : $value['pricePlusVat']);
  978.  
  979.                 // Txt
  980.                 $orderDataTxt .= 
  981.                 strip_tags(str_replace(array("\n", "\r"), "", $value["name"]))
  982.                 . (($opt && $value["option"] != "null") ? " " . $value["option"] . ( $value["suboption"] != "null" ? " " . $value["suboption"] : "") : "")
  983.                 . "- " . strip_tags(str_replace(array("\n", "\r"), "", $value["description"])) . "\n "
  984.                 . $value["quantity"] . " x " 
  985.                 . ( $this->settings['vat_type'] == "excluded" ?
  986.                     "(" . $value["singlePrice"] . " + " . l10n("cart_vat") . " " . $value["vat"] . ")"
  987.                 :
  988.                     $value["singlePricePlusVat"]
  989.                 )
  990.                 . " = " . ($this->settings['vat_type'] == "excluded" ? $value["price"] : $value['pricePlusVat']) . "\n\n";
  991.  
  992.                 // HTML
  993.                 $orderDataHTML .= "\n\t\t\t\t<tr valign=\"top\" style=\"vertical-align: top\"" . ($i%2 ? " bgcolor=\"#EEEEEE\"" : "") . ">
  994.                                                 <td style=\"border: 1px solid [email:bodyBackgroundBorder];\">" . $value["name"] . "<br />" . $value["description"] . "</td>" .
  995.                                                 ($opt ? "<td style=\"border: 1px solid [email:bodyBackgroundBorder];\">" . (($value["option"] != "null") ? $value["option"] . (($value["suboption"] != "null") ? $value["suboption"] : "") : "") . "</td>" : "") .
  996.                                                 "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $value["quantity"] . "</td>" .
  997.                                                 ($this->settings['vat_type'] == "excluded" ? 
  998.                                                     "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . ($value["singlePrice"] == $value['singleFullPrice'] ? $value['singlePrice'] : $value['singlePrice'] . ' <span style="text-decoration: line-through;">' . $value['singleFullPrice'] . "</span>") . "</td>"
  999.                                                 :
  1000.                                                     "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . ($value["singlePricePlusVat"] == $value['singleFullPricePlusVat'] ? $value['singlePricePlusVat'] : $value['singlePricePlusVat'] . ' <span style="text-decoration: line-through;">' . $value['singleFullPricePlusVat'] . "</span>") . "</td>"
  1001.                                                 )
  1002.                                                  .
  1003.                                                 ($vat ? "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $value["vat"] ."</td>" : "") .
  1004.                                                 "<td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . ($this->settings['vat_type'] == "excluded" ? $value["price"] : $value['pricePlusVat']) . "</td>
  1005.                                             </tr>\n";
  1006.                 $i++;
  1007.             }
  1008.         }
  1009.  
  1010.         //
  1011.         //    Shipping
  1012.         //
  1013.         if (isset($this->orderData['shipping']) && is_array($this->orderData['shipping'])) {
  1014.             $orderDataHTML .= "\n\t\t\t<tr>" . 
  1015.                                         ($this->settings['vat_type'] != "none" ?
  1016.                                             "<td colspan=\"" . ($colspan - 1) . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . l10n('cart_shipping') . ": " . $this->orderData['shipping']['name'] . "</td>" .
  1017.                                             "<td  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['shipping']['vat'] . "</td>"
  1018.                                         :
  1019.                                             "<td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . l10n('cart_shipping') . ": " . $this->orderData['shipping']['name'] . "</td>"
  1020.                                         )
  1021.                                         . "<td  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . ($this->settings['vat_type'] == "excluded" ? $this->orderData['shipping']['price'] : $this->orderData['shipping']['pricePlusVat']) . "</td>
  1022.                                     </tr>";
  1023.             $orderDataTxt .= "\n" . l10n('cart_shipping') . " - " . $this->orderData['shipping']['name'] . ": " . ($this->settings['vat_type'] == "excluded" ? $this->orderData['shipping']['price'] : $this->orderData['shipping']['pricePlusVat']);
  1024.         }
  1025.  
  1026.         //
  1027.         //    Payment
  1028.         //
  1029.         if (isset($this->orderData['payment']) && is_array($this->orderData['payment'])) {
  1030.             $orderDataHTML .= "\n\t\t\t<tr>" . 
  1031.                                         ($this->settings['vat_type'] != "none" ?
  1032.                                             "<td colspan=\"" . ($colspan - 1) . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . l10n('cart_payment') . ": " . $this->orderData['payment']['name'] . "</td>" .
  1033.                                             "<td  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['payment']['vat'] . "</td>"
  1034.                                         :
  1035.                                             "<td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . l10n('cart_payment') . ": " . $this->orderData['payment']['name'] . "</td>"
  1036.                                         )
  1037.                                         . "<td  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . ($this->settings['vat_type'] == "excluded" ? $this->orderData['payment']['price'] : $this->orderData['payment']['pricePlusVat']) . "</td>
  1038.                                     </tr>";
  1039.             $orderDataTxt .= "\n" . l10n('cart_payment') . " - " . $this->orderData['payment']['name'] . ": " . ($this->settings['vat_type'] == "excluded" ? $this->orderData['payment']['price'] : $this->orderData['payment']['pricePlusVat']);
  1040.         }
  1041.  
  1042.         //
  1043.         //  Coupon
  1044.         //
  1045.         if (isset($this->orderData['coupon']) && $this->orderData['coupon'] !== "") {
  1046.             $orderDataHTML .= "\n\t\t\t<tr>
  1047.                                     <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . l10n('cart_coupon', "Coupon Code") . "</td>
  1048.                                     <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['coupon'] . "</td>
  1049.                                 </tr>";
  1050.             $orderDataTxt .= "\n" . l10n('cart_coupon', "Coupon Code")  . ": " . $this->orderData['coupon'];      
  1051.         }
  1052.  
  1053.         //
  1054.         //  Total amounts
  1055.         //
  1056.         switch ($this->settings['vat_type']) {
  1057.             case "excluded":
  1058.                 $orderDataHTML .= "\n\t\t\t<tr>
  1059.                                         <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right; font-weight: bold;\">" . l10n('cart_vat') . "</td>
  1060.                                         <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['totalVat'] . "</td>
  1061.                                     </tr>";
  1062.                 $orderDataHTML .= "\n\t\t\t<tr>
  1063.                                         <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right; font-weight: bold;\">" . l10n('cart_total_vat') . "</td>
  1064.                                         <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['totalPricePlusVat'] . "</td>
  1065.                                     </tr>";
  1066.                 $orderDataTxt .= "\n" . l10n('cart_vat')  . ": " . $this->orderData['totalVat'];
  1067.                 $orderDataTxt .= "\n" . l10n('cart_total_vat')  . ": " . $this->orderData['totalPricePlusVat'];
  1068.             break;
  1069.             case "included": 
  1070.                 $orderDataHTML .= "\n\t\t\t<tr>
  1071.                                         <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right; font-weight: bold;\">" . l10n('cart_total_vat') . "</td>
  1072.                                         <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['totalPricePlusVat'] . "</td>
  1073.                                     </tr>";
  1074.                 $orderDataHTML .= "\n\t\t\t<tr>
  1075.                                         <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right; font-weight: bold;\">" . l10n('cart_vat_included') . "</td>
  1076.                                         <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['totalVat'] . "</td>
  1077.                                     </tr>";
  1078.                 $orderDataTxt .= "\n" . l10n('cart_total_vat')  . ": " . $this->orderData['totalPricePlusVat'];
  1079.                 $orderDataTxt .= "\n" . l10n('cart_vat_included')  . ": " . $this->orderData['totalVat'];
  1080.             break;
  1081.             case "none":
  1082.                 $orderDataHTML .= "\n\t\t\t<tr>
  1083.                                         <td colspan=\"" . $colspan . "\"  style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right; font-weight: bold;\">" . l10n('cart_total_price') . "</td>
  1084.                                         <td style=\"border: 1px solid [email:bodyBackgroundBorder]; text-align: right;\">" . $this->orderData['totalPricePlusVat'] . "</td>
  1085.                                     </tr>";
  1086.                 $orderDataTxt .= "\n" . l10n('cart_total_price')  . ": " . $this->orderData['totalPricePlusVat'];
  1087.             break;
  1088.         }
  1089.         $orderDataHTML .= "</table>";
  1090.  
  1091.         $txtMsg = "";
  1092.         $htmlMsg = "<table border=0 width=\"100%\" style=\"font: inherit;\">\n";
  1093.  
  1094.         //
  1095.         // Order number
  1096.         // 
  1097.         $htmlMsg .= "<tr><td colspan=\"2\" style=\"text-align: center; font-weight: bold;font-size: 1.11em\">" . l10n('cart_order_no') . ": " . $this->orderData['orderNo'] . "</td></tr>";
  1098.         $txtMsg .= str_replace("<br>", "\n", l10n('cart_order_no') . ": " . $this->orderData['orderNo']);
  1099.  
  1100.         //
  1101.         //  Opening message
  1102.         //
  1103.         if (!$isOwner) {
  1104.             $htmlMsg .= "\n<tr><td colspan=\"2\">" . $this->settings['email_opening'] . "</td></tr>";
  1105.             $txtMsg .= "\n\n" . strip_tags(str_replace("<br />", "\n", $this->settings['email_opening']));
  1106.         }
  1107.  
  1108.         // Customer's data
  1109.         if ($shippingDataHtml != "") {
  1110.             $htmlMsg .= "\n<tr style=\"vertical-align: top\" valign=\"top\">\n\t<td style=\"width: 50%; padding: 20px 0;\">\n\t\t<h3 style=\"font-size: 1.11em\">" . l10n('cart_vat_address') . "</h3>\n\t\t" . $userDataHtml . "\n\t</td>";
  1111.             $htmlMsg .= "\n\t<td style=\"width: 50%; padding: 20px 0;\">\n\t\t<h3 style=\"font-size: 1.11em\">" . l10n('cart_shipping_address') . "</h3>\n\t\t" . $shippingDataHtml . "</td>\n\t</tr>";
  1112.  
  1113.             $txtMsg .= "\n" . str_replace("<br />", "\n", l10n('cart_vat_address') . "\n" . $userDataTxt);
  1114.             $txtMsg .= "\n" . str_replace("<br />", "\n", l10n('cart_shipping_address') . "\n" . $shippingDataTxt);
  1115.         } else {
  1116.             $htmlMsg .= "\n<tr>\n\t<td colspan=\"2\" style=\"padding: 20px 0 0 0;\">\n\t\t<h3 style=\"font-size: 1.11em\">" . l10n('cart_vat_address') . "/" . l10n('cart_shipping_address') . "</h3>\n\t\t" . $userDataHtml . "</td>\n</tr>";
  1117.             $txtMsg .= "\n" . str_replace("<br />", "\n", l10n('cart_vat_address') . "/" . l10n('cart_shipping_address') . "\n" . $userDataTxt);
  1118.         }
  1119.  
  1120.         $htmlMsg .= $separationLine;
  1121.  
  1122.         // Products
  1123.         $htmlMsg .=  "<tr><td colspan=\"2\" style=\"padding: 5px 0 0 0;\"><h3 style=\"font-size: 1.11em\">" . l10n('cart_product_list') . "</h3>" . $orderDataHTML . "</td></tr>";
  1124.         $txtMsg .= "\n\n" . str_replace("<br />", "\n", l10n('cart_product_list') . "\n" . $orderDataTxt);
  1125.  
  1126.         $htmlMsg .= $separationLine;
  1127.  
  1128.         // Payment
  1129.         if (isset($this->orderData['payment']) && is_array($this->orderData['payment'])) {
  1130.             $htmlMsg .= "<tr>
  1131.                             <td colspan=\"2\" style=\"padding: 5px 0 0 0;\">
  1132.                                 <h3 style=\"font-size: 1.11em\">" . l10n('cart_payment') . "</h3>" .
  1133.                                 nl2br($this->orderData['payment']['name']) .( !$isOwner ? '<br />' . nl2br($this->orderData['payment']['email_text']) . ($this->orderData['payment']['html'] != "" ? '<div style="text-align: center; margin-top: 20px;">' . $this->orderData['payment']['html'] . '</div>' : "") : "" ) .
  1134.                             "</td>
  1135.                         </tr>";
  1136.             $txtMsg .= "\n\n" . str_replace("<br />", "\n", l10n('cart_payment') . "\n" . $this->orderData['payment']['name'] . ( !$isOwner ? "\n" . $this->orderData['payment']['email_text'] : "" ));
  1137.  
  1138.             $htmlMsg .= $separationLine;
  1139.         }
  1140.  
  1141.         // Shipping
  1142.         if (isset($this->orderData['shipping']) && is_array($this->orderData['shipping'])) {
  1143.             $htmlMsg .= "<tr>
  1144.                             <td colspan=\"2\" style=\"padding: 5px 0 0 0;\">
  1145.                                 <h3 style=\"font-size: 1.11em\">" . l10n('cart_shipping') . "</h3>" .
  1146.                                 nl2br($this->orderData['shipping']['name']) . ( !$isOwner ? '<br />' . nl2br($this->orderData['shipping']['email_text']) : "" ) .
  1147.                             "</td>
  1148.                         </tr>";
  1149.             $txtMsg .= "\n\n" . str_replace("<br />", "\n", l10n('cart_shipping') . "\n" . $this->orderData['shipping']['name'] . ( !$isOwner ? "\n" . $this->orderData['shipping']['email_text'] : "" ));
  1150.         }
  1151.  
  1152.         //
  1153.         //  Closing message
  1154.         //
  1155.         if (!$isOwner) {
  1156.             $htmlMsg .= $separationLine;
  1157.             $htmlMsg .= "\n<tr><td colspan=\"2\" style=\"padding: 5px 0 0 0;\">" . $this->settings['email_closing'] . "</td></tr>";
  1158.             $txtMsg .= "\n\n" . strip_tags(str_replace("<br />", "\n", $this->settings['email_closing']));
  1159.         }
  1160.         
  1161.         // Close the html table
  1162.         $htmlMsg .= "</table>\n";
  1163.  
  1164.         $attachments = array();
  1165.         if ($this->settings['useCSV'] && $isOwner) {
  1166.             $txtMsg .= $userDataCSV . "\n" . $orderDataCSV;
  1167.             $attachments[] = array("name" => "user_data.csv", "content" => $userDataCSV, "mime" => "text/csv");
  1168.             $attachments[] = array("name" => "order_data.csv", "content" => $orderDataCSV, "mime" => "text/csv");
  1169.         }
  1170.         return $ImMailer->send($from, $to, l10n('cart_order_no') . " " . $this->orderData['orderNo'], $txtMsg, $htmlMsg, $attachments);
  1171.     }
  1172.  
  1173.     /**
  1174.      * Send the order email to the owner
  1175.      * @return boolean
  1176.      */
  1177.     function sendOwnerEmail()
  1178.     {
  1179.         return $this->sendEmail(true, $this->settings['owner_email'], $this->settings['owner_email']);
  1180.     }
  1181.  
  1182.     /**
  1183.      * Send the order email to the customer
  1184.      * @return boolean
  1185.      */
  1186.     function sendCustomerEmail()
  1187.     {
  1188.         return $this->sendEmail(false, $this->settings['owner_email'], $this->orderData['userInvoiceData']['Email']['value']);
  1189.     }
  1190.  
  1191.     
  1192.     /**
  1193.      * Set the database connection data
  1194.      * 
  1195.      * @param String $host        
  1196.      * @param String $user        
  1197.      * @param String $pwd         
  1198.      * @param String $db          
  1199.      * @param String $table_prefix
  1200.      *
  1201.      * @return Boolean
  1202.      */
  1203.     function setDatabaseConnection($host, $user, $pwd, $db, $table_prefix)
  1204.     {
  1205.         $this->table_prefix = $table_prefix;
  1206.         $this->db = new ImDb($host, $user, $pwd, $db);
  1207.         if ($this->db->testConnection())
  1208.             return true;
  1209.         $this->db = false;
  1210.         return false;
  1211.     }
  1212.  
  1213.     /**
  1214.      * Close the database connection
  1215.      * 
  1216.      * @return void
  1217.      */
  1218.     function closeDatabaseConnection()
  1219.     {
  1220.         if ($this->db)
  1221.             $this->db->closeConnection();
  1222.     }
  1223.  
  1224.     /**
  1225.      * Save the order to DB
  1226.      * 
  1227.      * @return boolean
  1228.      */
  1229.     function saveOrderToDB()
  1230.     {
  1231.         if (!$this->db)
  1232.             return false;
  1233.         // Create the tables
  1234.         if (!$this->db->tableExists($this->table_prefix . "orders")) {
  1235.             $this->db->createTable(
  1236.                 $this->table_prefix . $this->settings['orders_table'],
  1237.                 array(
  1238.                     "id" => array('type' => 'VARCHAR(16)', 'primary' => true),
  1239.                     "ts" => array('type' => 'TIMESTAMP'),
  1240.                     "ip" => array('type' => 'VARCHAR(16)'),
  1241.                     "price" => array('type' => 'FLOAT'),
  1242.                     "vat" => array('type' => 'FLOAT'),
  1243.                     "price_plus_vat" => array('type' => 'FLOAT'),
  1244.                     "currency" => array('type' => 'VARCHAR(4)'),
  1245.                     "shipping_name" => array('type' => 'VARCHAR(32)'),
  1246.                     "shipping_price" => array('type' => 'FLOAT'),
  1247.                     "shipping_vat" => array('type' => 'FLOAT'),
  1248.                     "shipping_price_plus_vat" => array('type' => 'FLOAT'),
  1249.                     "payment_name" => array('type' => 'VARCHAR(32)'),
  1250.                     "payment_price" => array('type' => 'FLOAT'),
  1251.                     "payment_vat" => array('type' => 'FLOAT'),
  1252.                     "payment_price_plus_vat" => array('type' => 'FLOAT'),
  1253.                     "coupon" => array("type" => "VARCHAR(32)"),
  1254.                     "vat_type" => array("type" => "VARCHAR(8)")
  1255.                 )
  1256.             );
  1257.             $this->db->createTable(
  1258.                 $this->table_prefix . $this->settings['products_table'],
  1259.                 array(
  1260.                     "order_id" => array('type' => 'VARCHAR(16)', 'primary' => true),
  1261.                     "product_id" => array('type' => 'VARCHAR(16)', 'primary' => true),
  1262.                     "option" => array('type' => 'VARCHAR(32)', 'primary' => true),
  1263.                     "suboption" => array('type' => 'VARCHAR(32)', 'primary' => true),
  1264.                     "price" => array('type' => 'FLOAT'),
  1265.                     "vat" => array('type' => 'FLOAT'),
  1266.                     "price_plus_vat" => array('type' => 'FLOAT'),
  1267.                     "quantity" => array('type' => 'INT(11)'),
  1268.                     "name" => array('type' => 'TEXT')
  1269.                 )
  1270.             );
  1271.             $this->db->createTable(
  1272.                 $this->table_prefix . $this->settings['invoice_addresses_table'],
  1273.                 array(
  1274.                     "order_id" => array('type' => 'VARCHAR(16)', 'primary' => true),
  1275.                     "label" => array('type' => 'VARCHAR(32)', 'primary' => true),
  1276.                     "index" => array('type' => 'INT(11)'),
  1277.                     "value" => array('type' => 'TEXT')
  1278.                 )
  1279.             );
  1280.             $this->db->createTable(
  1281.                 $this->table_prefix . $this->settings['shipping_addresses_table'],
  1282.                 array(
  1283.                     "order_id" => array('type' => 'VARCHAR(16)', 'primary' => true),
  1284.                     "label" => array('type' => 'VARCHAR(32)', 'primary' => true),
  1285.                     "index" => array('type' => 'INT(11)'),
  1286.                     "value" => array('type' => 'TEXT')
  1287.                 )
  1288.             );
  1289.         }
  1290.  
  1291.         // Check if the current order number already exists
  1292.         do {
  1293.             $res = $this->db->query("SELECT id FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE id='" . $this->db->escapeString($this->orderData['orderNo']) ."'");
  1294.             if (count($res))
  1295.                 $this->orderData['orderNo'] .= rand(0, 9);
  1296.         } while (count($res));
  1297.  
  1298.         // Save the order data
  1299.         $this->db->query(
  1300.             "INSERT INTO `" . $this->table_prefix . $this->settings['orders_table'] . "` "
  1301.             . "(id, ts, ip, vat_type, price, vat, price_plus_vat, currency, shipping_name, shipping_price, shipping_vat, shipping_price_plus_vat, payment_name, payment_price, payment_vat, payment_price_plus_vat, coupon) VALUES("
  1302.             . "'" . $this->db->escapeString($this->orderData['orderNo']) . "',
  1303.             '" . date("Y-m-d H:i:s") . "',
  1304.             '" . $_SERVER['REMOTE_ADDR'] . "',
  1305.             '" . $this->settings['vat_type'] . "',
  1306.             " . $this->orderData['rawTotalPrice'] . ",
  1307.             " . $this->orderData['rawTotalVat'] . ",
  1308.             " . $this->orderData['rawTotalPricePlusVat'] . ",
  1309.             '" . $this->orderData['currency'] . "',
  1310.             '" . (isset($this->orderData['shipping']) ? $this->orderData['shipping']['name'] : ''). "',
  1311.             " . (isset($this->orderData['shipping']) ? $this->orderData['shipping']['rawPrice'] : 0) . ",
  1312.             " . (isset($this->orderData['shipping']) ? $this->orderData['shipping']['rawVat'] : 0) . ",
  1313.             " . (isset($this->orderData['shipping']) ? $this->orderData['shipping']['rawPricePlusVat'] : 0) . ",
  1314.             '" . (isset($this->orderData['payment']) ? $this->orderData['payment']['name'] : '') . "',
  1315.             " . (isset($this->orderData['payment']) ? $this->orderData['payment']['rawPrice'] : 0) . ",
  1316.             " . (isset($this->orderData['payment']) ? $this->orderData['payment']['rawVat'] : 0). ",
  1317.             " . (isset($this->orderData['payment']) ? $this->orderData['payment']['rawPricePlusVat'] : 0) . ",            
  1318.             '" . (isset($this->orderData['coupon']) ? $this->orderData['coupon'] : '') . "'
  1319.             )"
  1320.         );
  1321.  
  1322.         // Save the products
  1323.         if (isset($this->orderData['products']) && is_array($this->orderData['products'])) {
  1324.             $qdata = array();
  1325.             $query = "INSERT INTO `" . $this->table_prefix . $this->settings['products_table']. "` (
  1326.                     `order_id`,
  1327.                     `product_id`,
  1328.                     `option`,
  1329.                     `suboption`,
  1330.                     `price`,
  1331.                     `vat`,
  1332.                     `price_plus_vat`,
  1333.                     `quantity`,
  1334.                     `name`
  1335.                 ) VALUES";
  1336.             foreach ($this->orderData['products'] as $key => $product) {
  1337.                 $qdata[] = "(
  1338.                     '" . $this->db->escapeString($this->orderData['orderNo']) . "',
  1339.                     '" . $this->db->escapeString($key) . "',
  1340.                     '" . $this->db->escapeString(isset($product['option']) ? $product['option'] : '') . "',
  1341.                     '" . $this->db->escapeString(isset($product['suboption']) ? $product['suboption'] : '') . "',
  1342.                     " . $product['rawPrice'] . ",
  1343.                     " . $product['rawVat'] . ",
  1344.                     " . $product['rawPricePlusVat'] . ",
  1345.                     " . $product['quantity'] . ",
  1346.                     '" . $this->db->escapeString($product['name']) . "'
  1347.                 )";
  1348.             }
  1349.             $query .= implode(",", $qdata);
  1350.             $this->db->query($query);
  1351.         }
  1352.  
  1353.         // Save the invoice data
  1354.         if (isset($this->orderData['userInvoiceData']) && is_array($this->orderData['userInvoiceData'])) {
  1355.             $qdata = array();
  1356.             $index = 0;
  1357.             $query = "INSERT INTO `" . $this->table_prefix . $this->settings['invoice_addresses_table'] . "` (
  1358.                 `order_id`,
  1359.                 `label`,
  1360.                 `index`,
  1361.                 `value`
  1362.             ) VALUES";
  1363.             foreach ($this->orderData['userInvoiceData'] as $field) {
  1364.                 if ($field['value'] != "") {
  1365.                     $qdata[] = "(
  1366.                         '" . $this->db->escapeString($this->orderData['orderNo']) . "',
  1367.                         '" . $this->db->escapeString($field['label']) . "',
  1368.                         '" . $index++ . "',
  1369.                         '" . $this->db->escapeString($field['value']) . "'
  1370.                     )";
  1371.                 }
  1372.             }
  1373.             $query .= implode(",", $qdata);
  1374.             $this->db->query($query);
  1375.         }
  1376.  
  1377.         // Save the shipping data
  1378.         if (isset($this->orderData['userShippingData']) && is_array($this->orderData['userShippingData'])) {
  1379.             $qdata = array();
  1380.             $index = 0;
  1381.             $query = "INSERT INTO `" . $this->table_prefix . $this->settings['shipping_addresses_table'] . "` (
  1382.                 `order_id`,
  1383.                 `label`,
  1384.                 `index`,
  1385.                 `value`
  1386.             ) VALUES";
  1387.             foreach ($this->orderData['userShippingData'] as $field) {
  1388.                 if ($field['value'] != "") {
  1389.                     $qdata[] = "(
  1390.                         '" . $this->db->escapeString($this->orderData['orderNo']) . "',
  1391.                         '" . $this->db->escapeString($field['label']) . "',
  1392.                         '" . $index++ . "',
  1393.                         '" . $this->db->escapeString($field['value']) . "'
  1394.                     )";
  1395.                 }
  1396.             }
  1397.             $query .= implode(",", $qdata);
  1398.             $this->db->query($query);
  1399.         }
  1400.  
  1401.         return $this->orderData['orderNo'];
  1402.     }
  1403.  
  1404.     /**
  1405.      * Delete an order from the DB
  1406.      * @param  String $id
  1407.      * @return void              
  1408.      */
  1409.     function deleteOrderFromDb($id)
  1410.     {
  1411.         if (!$this->db)
  1412.             return false;
  1413.         $id = $this->db->escapeString($id);
  1414.         $this->db->query("DELETE FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE `id`='" . $id . "'" );
  1415.         $this->db->query("DELETE FROM `" . $this->table_prefix . $this->settings['invoice_addresses_table'] . "` WHERE `order_id`='" . $id . "'" );
  1416.         $this->db->query("DELETE FROM `" . $this->table_prefix . $this->settings['shipping_addresses_table'] . "` WHERE `order_id`='" . $id . "'" );
  1417.         $this->db->query("DELETE FROM `" . $this->table_prefix . $this->settings['products_table'] . "` WHERE `order_id`='" . $id . "'" );
  1418.     }
  1419.  
  1420.     /**
  1421.      * Get a list of the orders in the DB
  1422.      *
  1423.      * @param Number $pagination_start
  1424.      * @param Number $pagination_length
  1425.      * @param String $filter Filter the result matching this string
  1426.      * 
  1427.      * @return array
  1428.      */
  1429.     function getOrders($pagination_start, $pagination_length, $filter = "")
  1430.     {
  1431.         $result = array(
  1432.             "orders" => array(),
  1433.             "paginationCount" => 0
  1434.         );
  1435.         if (!$this->db)
  1436.             return $result;
  1437.         // Search for specific orders
  1438.         if (strlen($filter)) {
  1439.             $ids = array();
  1440.             // Search in the customer's data
  1441.             foreach ($this->db->query("SELECT order_id FROM `" . $this->table_prefix . $this->settings['invoice_addresses_table'] . "` WHERE value LIKE '%" . $this->db->escapeString($filter) . "%'") as $order) {
  1442.                 $ids[] = "'" . $order['order_id'] . "'";
  1443.             }
  1444.             // Search in the orders's data
  1445.             foreach ($this->db->query("SELECT id FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE `id` LIKE '%" . $this->db->escapeString($filter) . "%'") as $order) {
  1446.                 $ids[] = "'" . $order['id'] . "'";
  1447.             }
  1448.             if (count($ids) > 0) {
  1449.                 $result['orders'] = $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE id IN (" . implode(",", $ids) . ") ORDER BY `ts` DESC LIMIT " . $pagination_start . ", " . $pagination_length);
  1450.                 // Set the pagination maximum length
  1451.                 $ordersCount = $this->db->query("SELECT COUNT(*) AS c FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE id IN (" . implode(",", $ids) . ")");
  1452.                 $result['paginationCount'] = $ordersCount[0]['c'];
  1453.             }
  1454.         } else {
  1455.             $results = $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` ORDER BY `ts` DESC LIMIT " . $pagination_start . ", " . $pagination_length);
  1456.             if (!is_bool($results)) {
  1457.                 $result['orders'] = $results;
  1458.                 // Set the pagination maximum length
  1459.                 $ordersCount = $this->db->query("SELECT COUNT(*) AS c FROM `" . $this->table_prefix . $this->settings['orders_table'] . "`");
  1460.                 $result['paginationCount'] = $ordersCount[0]['c'];
  1461.             }
  1462.         }
  1463.         return $result;
  1464.     }
  1465.  
  1466.     /**
  1467.      * Get an order
  1468.      * @param  String $id The order ID
  1469.      * @return Array      The order data
  1470.      */
  1471.     function getOrder($id)
  1472.     {
  1473.         $result = array();
  1474.         $order = $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['orders_table'] . "` WHERE id='" . $this->db->escapeString($id) . "'");
  1475.         if (!count($order))
  1476.             return array();
  1477.         $result['order'] = $order[0];
  1478.         $result['products'] = $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['products_table'] . "` WHERE order_id='" . $this->db->escapeString($id) . "'");
  1479.         $result['invoice']= $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['invoice_addresses_table'] . "` WHERE order_id='" . $this->db->escapeString($id) . "' ORDER BY `index`");
  1480.         $result['shipping'] = $this->db->query("SELECT * FROM `" . $this->table_prefix . $this->settings['shipping_addresses_table'] . "` WHERE order_id='" . $this->db->escapeString($id) . "' ORDER BY `index`");
  1481.         return $result;
  1482.     }
  1483.  
  1484. }
  1485.  
  1486.  
  1487.  
  1488.  
  1489. /**
  1490.  * This file stores the class used to add/remove/edit comments
  1491.  *
  1492.  * @category X5engine
  1493.  * @package  X5engine
  1494.  * @license  Copyright by Incomedia http://incomedia.eu
  1495.  * @link     http://websitex5.com
  1496.  */
  1497.  
  1498. /**
  1499.  * Use this class to store comments
  1500.  * 
  1501.  * @category X5engine
  1502.  * @package  X5engine
  1503.  * @license  Copyright by Incomedia http://incomedia.eu
  1504.  * @link     http://websitex5.com
  1505.  */
  1506. class ImComment
  1507. {
  1508.  
  1509.     var $comments = array();
  1510.     var $error = 0;
  1511.  
  1512.     /**
  1513.      * Get the comments from a file
  1514.      * 
  1515.      * @param string $file The source file path
  1516.      * 
  1517.      * @return void
  1518.      */
  1519.     function loadFromXML($file)
  1520.     {
  1521.         if (!file_exists($file)) {
  1522.             $this->comments = array();
  1523.             return;
  1524.         }
  1525.  
  1526.         $xmlstring = @file_get_contents($file); 
  1527.         if (strpos($xmlstring, "<?xml") !== false) {
  1528.             $xml = new imXML();
  1529.  
  1530.             // Remove the garbage (needed to avoid loosing comments when the xml string is malformed)
  1531.             $xmlstring = preg_replace('/<([0-9]+)>.*<\/\1>/i', '', $xmlstring);
  1532.             $xmlstring = preg_replace('/<comment>\s*<\/comment>/i', '', $xmlstring);
  1533.             
  1534.             $comments = $xml->parse_string($xmlstring);
  1535.             if ($comments !== false && is_array($comments)) {
  1536.                 $tc = array();
  1537.                 if (!isset($comments['comment'][0]) || !is_array($comments['comment'][0]))
  1538.                     $comments['comment'] = array($comments['comment']);
  1539.                 for ($i = 0; $i < count($comments['comment']); $i++) {
  1540.                     foreach ($comments['comment'][$i] as $key => $value) {
  1541.                         if ($key == "timestamp" && strpos($value, "-") == 2) {
  1542.                             // The v8 and v9 timestamp was inverted. For compatibility, let's convert it to the correct format.
  1543.                             // The v10 format is yyyy-mm-dd hh:ii:ss
  1544.                             // The v8 and v9 format is dd-mm-yyyy hh:ii:ss
  1545.                             $value = preg_replace("/([0-9]{2})\-([0-9]{2})\-([0-9]{4}) ([0-9]{2})\:([0-9]{2})\:([0-9]{2})/", "$3-$2-$1 $4:$5:$6", $value);
  1546.                         }
  1547.                         $tc[$i][$key] = str_replace(array("\\'", '\\"'), array("'", '"'), htmlspecialchars_decode($value));
  1548.                     }
  1549.                 }
  1550.                 $this->comments = $tc;
  1551.             } else {
  1552.                 // The comments cannot be retrieved. The XML is jammed.
  1553.                 // Do a backup copy of the file and then reset the xml.
  1554.                 // Hashed names ensure that a file is not copied more than once
  1555.                 $n = $file . "_version_" . md5($xmlstring);
  1556.                 if (!@file_exists($n))
  1557.                     @copy($file, $n);
  1558.                 $this->comments = array();
  1559.             }
  1560.         } else {
  1561.             $this->loadFromOldFile($file);
  1562.         }
  1563.     }
  1564.  
  1565.     /**
  1566.      * Get the comments from a v8 comments file
  1567.      * 
  1568.      * @param string $file The source file path
  1569.      *
  1570.      * @return void
  1571.      */
  1572.     function loadFromOldFile($file)
  1573.     {
  1574.         if (!@file_exists($file)) {
  1575.             $this->comments = array();
  1576.             return;
  1577.         }
  1578.         $f = @file_get_contents($file);
  1579.         $f = explode("\n", $f);
  1580.         for ($i = 0;$i < count($f)-1; $i += 6) {
  1581.             $c[$i/6]['name'] = stripslashes($f[$i]);
  1582.             $c[$i/6]['email'] = $f[$i+1];
  1583.             $c[$i/6]['url'] = $f[$i+2];
  1584.             $c[$i/6]['body'] = stripslashes($f[$i+3]);
  1585.             $c[$i/6]['timestamp'] = preg_replace("/([0-9]{2})\-([0-9]{2})\-([0-9]{4}) ([0-9]{2})\:([0-9]{2})\:([0-9]{2})/", "$3-$2-$1 $4:$5:$6", $f[$i+4]);
  1586.             $c[$i/6]['approved'] = $f[$i+5];
  1587.             $c[$i/6]['rating'] = 0;
  1588.         }
  1589.         $this->comments = $c;
  1590.     }
  1591.  
  1592.     /**
  1593.      * Save the comments in a xml file
  1594.      * 
  1595.      * @param string $file The destination file path
  1596.      *
  1597.      * @return boolean
  1598.      */
  1599.     function saveToXML($file)
  1600.     {
  1601.         // If the count is 0, delete the file and exit
  1602.         if (count($this->comments) === 0) {
  1603.             if (@file_exists($file))
  1604.                 @unlink($file);
  1605.             return true;
  1606.         }
  1607.  
  1608.         // If the folder doesn't exists, try to create it
  1609.         $dir = @dirname($file);
  1610.         if ($dir != "" && $dir != "/" && $dir != "." && $dir != "./" && !file_exists($dir)) {
  1611.             @mkdir($dir, 0777, true);
  1612.         }
  1613.  
  1614.         $xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  1615.         $xml .= "<comments>\n";
  1616.         $i = 0;
  1617.         foreach ($this->comments as $comment) {
  1618.             $txml = "";
  1619.             foreach ($comment as $key => $value) {
  1620.                 // Well formed content only
  1621.                 if (!preg_match('/[0-9]+/', $key) && in_array(gettype($value), array('string', 'integer', 'double'))) {
  1622.                     $code = str_replace(array("\\'", '\\"', "\\\""), array("'", '"', "\""), preg_replace('/[\n\r\t]*/', '', nl2br($value)));
  1623.                     $txml .= "\t\t<" . $key . "><![CDATA[" . htmlspecialchars($code) . "]]></" . $key . ">\n";
  1624.                 }
  1625.             }
  1626.             if ($txml != "")
  1627.                 $xml .= "\t<comment>\n" . $txml . "\t</comment>\n";
  1628.         }
  1629.         $xml .= "</comments>";
  1630.  
  1631.         if ((is_writable($file) || !file_exists($file))) {
  1632.             if (!$f = @fopen($file, 'w+')) {
  1633.                 $this->error = -3;
  1634.                 return false;
  1635.             } else {
  1636.                 if (flock($f, LOCK_EX)) {
  1637.                     $locked = 1;
  1638.                 }
  1639.  
  1640.                 if (fwrite($f, $xml) === false) {
  1641.                     $this->error = -4;
  1642.                     return false;
  1643.                 } else {
  1644.                     if($locked)
  1645.                         flock($f, LOCK_UN);
  1646.                     fclose($f);
  1647.                     $this->error = 0;
  1648.                     return true;
  1649.                 }
  1650.             }
  1651.         } else {
  1652.             $this->error = -2;
  1653.             return false;
  1654.         }
  1655.     }
  1656.  
  1657.  
  1658.     /**
  1659.      * Save the comments in a DB
  1660.      * 
  1661.      * @param string $host     The host name
  1662.      * @param string $user     The user name
  1663.      * @param string $password The user password
  1664.      * @param string $db       The db name
  1665.      * @param string $table    The db table
  1666.      * @param string $postid   The post id
  1667.      * 
  1668.      * @return boolean
  1669.      */
  1670.     function saveToDb($host, $user, $password, $db, $table, $postid)
  1671.     {    
  1672.         // TODO: Avoid collisions and simplify update/delete the changed rows instead of deleting and rebuilding the table
  1673.         
  1674.         $db = new ImDb($host, $user, $password, $db);
  1675.         if (!$db->testConnection())
  1676.             return false;
  1677.  
  1678.         // Delete the comments
  1679.         $db->query("DELETE FROM `" . $table . "` WHERE postid='" . $db->escapeString($postid) . "'");
  1680.  
  1681.         if (count($this->comments) === 0)
  1682.             return true;
  1683.  
  1684.         // Create the fields definition
  1685.         $fields = array(
  1686.             "postid" => array(
  1687.                 "type" => (is_string($postid) ? "VARCHAR(32)" : "INT(11)"),
  1688.                 "primary" => true
  1689.             ),
  1690.             "commentid" => array(
  1691.                 "type" => "INT(11)",
  1692.                 "primary" => true
  1693.             ),
  1694.         );
  1695.         // Find the fields of each comment
  1696.         foreach ($this->comments as $comment) {
  1697.             foreach ($comment as $key => $value) {
  1698.                 if (!in_array($key, array_keys($fields))) {
  1699.                     if ($key == "ts" || $key == "timestamp" || $key == "date")
  1700.                         $fields[$key] = array("type" => "TIMESTAMP");
  1701.                     else
  1702.                         $fields[$key] = array("type" => "TEXT");
  1703.                 }
  1704.             }
  1705.         }
  1706.         $db->createTable($table, $fields);
  1707.  
  1708.         // Resave them
  1709.         $i = 0;
  1710.         $r = true;
  1711.         foreach ($this->comments as $comment) {
  1712.             $values = array();
  1713.             $keys = array();
  1714.             foreach ($comment as $key => $value) {
  1715.                 $keys[] = $key;
  1716.                 $values[] = "'" . $this->filterCode($value, true) . "'";
  1717.             }
  1718.             $query = "INSERT INTO `" . $table . "` (postid,commentid," . implode(",", $keys) . ") VALUES ('" . $postid . "'," . $i++ . "," . implode(",", $values) . ")";
  1719.             $r = $r && $db->query($query);
  1720.             if (!$r)
  1721.                 echo $db->error() . PHP_EOL;
  1722.         }
  1723.         $db->closeConnection();
  1724.         return $r;
  1725.     }
  1726.  
  1727.     /**
  1728.      * Load the comments from a DB
  1729.      * 
  1730.      * @param string $host     The host name
  1731.      * @param string $user     The user name
  1732.      * @param string $password The user password
  1733.      * @param string $db       The db name
  1734.      * @param string $table    The db table
  1735.      * @param string $postid   The post id
  1736.      * 
  1737.      * @return boolean
  1738.      */
  1739.     function loadFromDb($host, $user, $password, $db, $table, $postid)
  1740.     {
  1741.         $db = new ImDb($host, $user, $password, $db);
  1742.         if (!$db->testConnection())
  1743.             return false;
  1744.         $rows = $db->query("SELECT * FROM `" . $table . "` WHERE postid='" . $postid . "'");
  1745.         if (is_bool($rows)) {
  1746.             $this->comments = array();
  1747.             return false;
  1748.         }
  1749.  
  1750.         foreach ($rows as $row) {
  1751.             $comment = array();
  1752.             foreach ($row as $key => $value) {
  1753.                 // Filter some fields
  1754.                 if ($key != "postid" && $key != "commentid" && !is_numeric($key)) {
  1755.                     $comment[$key] = $value;
  1756.                 }
  1757.             }
  1758.             $this->comments[] = $comment;
  1759.         }
  1760.     }
  1761.  
  1762.  
  1763.     /**
  1764.      * Add a comment to a file
  1765.      * 
  1766.      * @param array $comment the array of data to store
  1767.      *
  1768.      * @return void
  1769.      */
  1770.     function add($comment)
  1771.     {
  1772.         foreach ($comment as $key => $value) {
  1773.             $comment[$key] = $this->filterCode($value, true);
  1774.         }
  1775.         $this->comments[] = $comment;
  1776.     }
  1777.  
  1778.     /**
  1779.      * Sort the array
  1780.      * 
  1781.      * @param string $orderby Field to compare when ordering the array
  1782.      * @param string $sort    Sort by ascending (asc) or descending (desc) order
  1783.      * 
  1784.      * @return void         
  1785.      */
  1786.     function sort($orderby = "", $sort = "desc")
  1787.     {
  1788.         if (count($this->comments) === 0)
  1789.             return;
  1790.  
  1791.         // Find where the comments has this field
  1792.         // This is useful to order using a field which is not present in every comment (like the ts field, which is missing in the stars-only vote type)
  1793.         $comment = null;
  1794.         for ($i=0; $i < count($this->comments) && $comment == null; $i++) { 
  1795.             if (isset($this->comments[$i][$orderby]))
  1796.                 $comment = $this->comments[$i];
  1797.         }
  1798.         if ($comment === null)
  1799.             return;
  1800.         
  1801.         // Order the array
  1802.         $symbol = (strtolower($sort) == "desc" ? '<' : '>');
  1803.         $compare = 'if (!isset($a["' . $orderby . '"]) || !isset($b["' . $orderby . '"])) return 0;';
  1804.         $compare .= 'if($a["' . $orderby . '"] == $b["' . $orderby . '"]) return 0; ';
  1805.  
  1806.         // The orderable field is a timestamp
  1807.         if (preg_match("/[0-9]{4}-[0-9]{2}-[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0-9]{2}/", $comment[$orderby]))
  1808.             $compare .= 'if (strtotime($a["' . $orderby . '"]) ' . $symbol . ' strtotime($b["' . $orderby . '"])) return -1; return 1;';
  1809.  
  1810.         // The orderable field is a number
  1811.         else if (is_numeric($comment[$orderby]))
  1812.             $compare .= 'if ($a["' . $orderby . '"] ' . $symbol . ' $b["' . $orderby . '"]) return -1; return 1;';
  1813.  
  1814.         // The orderable field is a string
  1815.         else if (is_string($comment[$orderby]))
  1816.             $compare .= 'return strcmp($a["' . $orderby . '"], $b["' . $orderby . '"]);';
  1817.  
  1818.         // Sort and return
  1819.         usort($this->comments, create_function('$a, $b', $compare));
  1820.     }
  1821.  
  1822.     /**
  1823.      * Get all the comments
  1824.      * 
  1825.      * @param string $orderby Field to compare when ordering the array
  1826.      * @param string $sort    Sort by ascending (asc) or descending (desc) order
  1827.      * 
  1828.      * @return array
  1829.      */
  1830.     function getAll($orderby = "", $sort = "desc")
  1831.     {
  1832.         if ($orderby == "" || count($this->comments) === 0)
  1833.             return $this->comments;
  1834.         
  1835.         $this->sort($orderby, $sort);
  1836.         
  1837.         return $this->comments;
  1838.     }
  1839.  
  1840.     /**
  1841.      * Get the comment n
  1842.      * 
  1843.      * @param integer $n The index of comment
  1844.      * 
  1845.      * @return array
  1846.      */
  1847.     function get($n)
  1848.     {
  1849.         if (isset($this->comments[$n]))
  1850.             return $this->comments[$n];
  1851.         return array();
  1852.     }
  1853.  
  1854.     /**
  1855.      * Replace the comment $n with $comment
  1856.      * 
  1857.      * @param integer $n       Comment number
  1858.      * @param array   $comment Comment data
  1859.      * 
  1860.      * @return boolean
  1861.      */
  1862.     function edit($n, $comment)
  1863.     {
  1864.         if (isset($this->comments[$n])) {
  1865.             $this->comments[$n] = $comment;
  1866.             return true;
  1867.         }
  1868.         return false;
  1869.     }
  1870.  
  1871.     /**
  1872.      * Delete the comment at $n
  1873.      * 
  1874.      * @param integer $n The index of the comment
  1875.      * 
  1876.      * @return void
  1877.      */
  1878.     function delete($n)
  1879.     {
  1880.         // Delete an element from the array and reset the indexes
  1881.         if (isset($this->comments[$n])) {
  1882.             $comments = $this->comments;
  1883.             $this->comments = array();
  1884.             for ($i = 0; $i < count($comments); $i++)
  1885.                 if ($i != $n)
  1886.                     $this->comments[] = $comments[$i];
  1887.             return true;
  1888.         } else {
  1889.             return false;
  1890.         }
  1891.     }
  1892.  
  1893.     /**
  1894.      * Clean the data from XSS
  1895.      * 
  1896.      * @param string  $str         The string to parse
  1897.      * @param boolean $allow_links true to allow links
  1898.      * 
  1899.      * @return string
  1900.      */
  1901.     function filterCode($str, $allow_links = false)
  1902.     {
  1903.         global $imSettings;
  1904.  
  1905.         if (gettype($str) != 'string')
  1906.             return "";
  1907.  
  1908.         // Remove javascript
  1909.         while (($start = imstripos($str, "<script")) !== false) {
  1910.             $end = imstripos($str, "</script>") + strlen("</script>");
  1911.             $str = substr($str, 0, $start) . substr($str, $end);
  1912.         }
  1913.  
  1914.         // Remove PHP Code
  1915.         while (($start = imstripos($str, "<?")) !== false) {
  1916.             $end = imstripos($str, "?>") + strlen("?>");
  1917.             $str = substr($str, 0, $start) . substr($str, $end);
  1918.         }
  1919.  
  1920.         // Remove ASP code
  1921.         while (($start = imstripos($str, "<%")) !== false) {
  1922.             $end = imstripos($str, "%>") + strlen("<%");
  1923.             $str = substr($str, 0, $start) . substr($str, $end);
  1924.         }
  1925.  
  1926.         // Allow only few tags
  1927.         $str = strip_tags($str, '<b><i><u>' . ($allow_links ? '<a>' : ''));
  1928.         
  1929.         // Remove XML injection code
  1930.         while (($start = imstripos($str, "<![CDATA[")) !== false) {    
  1931.             // Remove the entire XML block when possible
  1932.             if (imstripos($str, "]]>") !== false) {
  1933.                 $end = imstripos($str, "]]>") + strlen("]]>");
  1934.                 $str = substr($str, 0, $start) . substr($str, $end);
  1935.             } else {        
  1936.                 $str = str_replace("<![CDATA[", "", str_replace("<![cdata[", "", $str));
  1937.             }
  1938.         }
  1939.         while (($start = imstripos($str, "]]>")) !== false) {
  1940.             $str = str_replace("]]>", "", $str);
  1941.         }
  1942.  
  1943.         // Remove all the onmouseover, onclick etc attributes
  1944.         while (($res = preg_replace("/(<[\\s\\S]+) on.*\\=(['\"\"])[\\s\\S]+\\2/i", "\\1", $str)) != $str) {
  1945.             // Exit in case of error
  1946.             if ($res == null)
  1947.                 break;
  1948.             $str = $res;
  1949.         }
  1950.  
  1951.         $matches = array();
  1952.         preg_match_all('~<a.*>~isU', $str, $matches);
  1953.         for ($i = 0; $i < count($matches[0]); $i++) {
  1954.             if (imstripos($matches[0][$i], 'nofollow') === false && imstripos($matches[0][$i], $imSettings['general']['url']) === false) {
  1955.                 $result = trim($matches[0][$i], ">") . ' rel="nofollow">';
  1956.                 $str = str_replace(strtolower($matches[0][$i]), strtolower($result), $str);
  1957.             }
  1958.         }
  1959.  
  1960.         return $str;
  1961.     }
  1962.  
  1963.     /**
  1964.      * Provide the last error
  1965.      * 
  1966.      * @return int
  1967.      */
  1968.     function lastError()
  1969.     {
  1970.         return $this->error;
  1971.     }
  1972. }
  1973.  
  1974.  
  1975.  
  1976.  
  1977. class ImDb
  1978. {
  1979.  
  1980.     var $conn;
  1981.     var $db;
  1982.     var $db_name;
  1983.     var $engine = "MYISAM";
  1984.  
  1985.     /**
  1986.      * Define a new ImDb Object
  1987.      * (PHP5 Constructor)
  1988.      * 
  1989.      * @param string $host
  1990.      * @param string $user
  1991.      * @param string $pwd
  1992.      * @param string $db
  1993.      *
  1994.      * @return void
  1995.      */
  1996.     function __construct($host, $user, $pwd, $db)
  1997.     {
  1998.         $this->setUp($host, $user, $pwd, $db);
  1999.     }
  2000.  
  2001.     /**
  2002.      * Define a new ImDb Object
  2003.      * (PHP4 Constructor)
  2004.      * 
  2005.      * @param string $host
  2006.      * @param string $user
  2007.      * @param string $pwd
  2008.      * @param string $db
  2009.      *
  2010.      * @return void
  2011.      */ 
  2012.     function ImDb($host, $user, $pwd, $db)
  2013.     {
  2014.         $this->setUp($host, $user, $pwd, $db);
  2015.     }
  2016.  
  2017.     function setUp($host, $user, $pwd, $db)
  2018.     {
  2019.         $this->db_name = $db;
  2020.         $this->conn = @mysql_connect($host, $user, $pwd);        
  2021.         if ($this->conn === false)
  2022.             return;
  2023.         $this->db = @mysql_select_db($db, $this->conn);
  2024.         if ($this->db === false)
  2025.             return;
  2026.         if (function_exists('mysql_set_charset'))
  2027.             @mysql_set_charset("utf8", $this->conn);
  2028.         else
  2029.             @mysql_query('SET NAMES "utf8"', $this->conn);
  2030.     }
  2031.  
  2032.     /**
  2033.      * Check wheter the class is connected or not
  2034.      *
  2035.      * @return boolean
  2036.      */
  2037.     function testConnection()
  2038.     {
  2039.         return ($this->conn !== false && $this->db !== false);
  2040.     }
  2041.  
  2042.     /**
  2043.      * Close the connection
  2044.      * 
  2045.      * @return void
  2046.      */
  2047.     function closeConnection()
  2048.     {
  2049.         @mysql_close($this->conn);
  2050.     }
  2051.  
  2052.     /**
  2053.      * Create a new table or update an existing one. The $fields array must be passed as:
  2054.      * array( "field_name" => array(
  2055.      *     "type" => "TEXT"
  2056.      *     "null" => true
  2057.      *     "more" => "More data"
  2058.      * ))
  2059.      * @param string $name   The table name
  2060.      * @param array $fields  The table fields list
  2061.      * @return boolean
  2062.      */
  2063.     function createTable( $name, $fields )
  2064.     {
  2065.         $qfields = array();
  2066.         $primaries = array();
  2067.         $createResult = false;
  2068.  
  2069.         // If the table does not exists, create it
  2070.         if (!$this->tableExists($name)) {
  2071.             $query = "CREATE TABLE `" . $this->db_name . "`.`" . $name . "` (";
  2072.             foreach ($fields as $key => $value) {
  2073.                 $qfields[] = "`" . $key . "` " .
  2074.                             $value['type'] .
  2075.                             ($value['type'] == 'TEXT' ? " CHARACTER SET utf8 COLLATE utf8_unicode_ci" : "") .
  2076.                             (!isset($value['null']) || !$value['null'] ? " NOT NULL" : "") .
  2077.                             (isset($value['auto_increment']) ? " AUTO_INCREMENT" : "") .
  2078.                             (isset($value['more']) ? " " . $value['more'] : "");
  2079.                 if (isset($value['primary']) && $value['primary']) {
  2080.                     $primaries[] = "`" . $key . "`";
  2081.                 }
  2082.             }
  2083.             $query .= implode(",", $qfields);
  2084.             if (count($primaries))
  2085.                 $query .= ", PRIMARY KEY (" . implode(",", $primaries) . ")";
  2086.             $query .= ") ENGINE = " . $this->engine . " ;";
  2087.             $createResult = mysql_query($query, $this->conn);
  2088.         } else {
  2089.             $result = mysql_query("SHOW COLUMNS FROM `" . $this->db_name . "`.`" . $name . "`", $this->conn);
  2090.             if ($result) {
  2091.                 // Actual fields
  2092.                 $query = "ALTER TABLE `" . $this->db_name. "`.`" . $name . "`";
  2093.                 $act_fields = array();
  2094.                 while ($row = mysql_fetch_array($result))
  2095.                     $act_fields[] = $row[0];
  2096.                 // New fields
  2097.                 $new_fields = array_diff(array_keys($fields), $act_fields);
  2098.                 $new_fields = array_merge($new_fields); // Order the indexes
  2099.                 if (count($new_fields) > 0) {
  2100.                     foreach ($new_fields as $key) {
  2101.                         $qfields[] = " ADD `" . $key . "` " . $fields[$key]['type'] . 
  2102.                         ($fields[$key]['type'] == 'TEXT' ? " CHARACTER SET utf8 COLLATE utf8_unicode_ci" : "") .
  2103.                         (!isset($fields[$key]['null']) || !$fields[$key]['null'] ? " NOT NULL" : "") .
  2104.                         (isset($value['auto_increment']) ? " AUTO_INCREMENT" : "") .
  2105.                         (isset($fields[$key]['more']) ? " " . $fields[$key]['more'] : "");
  2106.                     }
  2107.                     $query .= implode(",", $qfields);
  2108.                     $createResult = mysql_query($query, $this->conn);
  2109.                 }
  2110.             }
  2111.         }
  2112.         return $createResult;
  2113.     }
  2114.  
  2115.     /**
  2116.      * Delete a table. Used often only for test purposes
  2117.      * 
  2118.      * @param string $table The table to delete
  2119.      * 
  2120.      * @return void
  2121.      */
  2122.     function deleteTable($table)
  2123.     {
  2124.         mysql_query("DROP TABLE " . $this->db_name . "." . $table, $this->conn);
  2125.     }
  2126.  
  2127.     /**
  2128.      * Check if the table exists in the current database
  2129.      * 
  2130.      * @param string $table The table name
  2131.      * 
  2132.      * @return boolean        true if the table exists
  2133.      */
  2134.     function tableExists($table)
  2135.     {
  2136.         $result = mysql_query("SHOW FULL TABLES FROM `" . $this->db_name . "` LIKE '" . mysql_real_escape_string($table, $this->conn) . "'", $this->conn);
  2137.         // Check that the name is correct (usage of LIKE is not correct if there are wildcards in the table name. Unfortunately MySQL 4 doesn't allow another syntax..)
  2138.         while (!is_bool($result) && $tb = mysql_fetch_array($result)) {
  2139.             if ($tb[0] == $table)
  2140.                 return true;
  2141.         }
  2142.         return false;
  2143.     }
  2144.  
  2145.     /**
  2146.      * Get the last error
  2147.      * 
  2148.      * @return array
  2149.      */
  2150.     function error()
  2151.     {
  2152.         return mysql_error();
  2153.     }
  2154.  
  2155.     /**
  2156.      * Provide the last inserted ID of the AUTOINCREMENT column
  2157.      * 
  2158.      * @return int The id of the latest insert operation
  2159.      */
  2160.     function lastInsertId()
  2161.     {
  2162.         $res = $this->query("SELECT LAST_INSERT_ID() AS `id`");
  2163.         if (count($res) > 0 && isset($res[0]['id'])) {
  2164.             return $res[0]['id'];
  2165.         }
  2166.         return 0;
  2167.     }
  2168.  
  2169.     /**
  2170.      * Execute a query
  2171.      * 
  2172.      * @param string $query The query
  2173.      * 
  2174.      * @return array        The query result
  2175.      */
  2176.     function query($query)
  2177.     {
  2178.         $result = mysql_query($query, $this->conn);
  2179.         if (!is_bool($result)) {
  2180.             $rows = array();
  2181.             while($row = mysql_fetch_array($result))
  2182.                 $rows[] = $row;
  2183.             return $rows;
  2184.         }
  2185.         return $result;
  2186.     }
  2187.  
  2188.     /**
  2189.      * Escape a string
  2190.      * 
  2191.      * @param string $string The string to escape
  2192.      * 
  2193.      * @return string
  2194.      */
  2195.     function escapeString($string)
  2196.     {
  2197.         if (!is_array($string)) {
  2198.             return mysql_real_escape_string($string, $this->conn);
  2199.         } else {
  2200.             for ($i = 0; $i < count($string); $i++)
  2201.                 $string[$i] = $this->escapeString($string[$i]);
  2202.             return $string;
  2203.         }
  2204.     }
  2205.  
  2206.     /**
  2207.      * Return the number of affected rows in the last query
  2208.      * 
  2209.      * @return integer
  2210.      */
  2211.     function affectedRows()
  2212.     {
  2213.         return mysql_affected_rows($this->conn);
  2214.     }
  2215. }
  2216.  
  2217.  
  2218.  
  2219.  
  2220. class DynamicObject
  2221. {
  2222.     var $body = "";    
  2223.     var $id;
  2224.     var $defaultText = "";
  2225.  
  2226.     function __construct($id)
  2227.     {
  2228.         $this->create($id);
  2229.     }
  2230.  
  2231.     function DynamicObject($id)
  2232.     {
  2233.         $this->create($id);
  2234.     }
  2235.  
  2236.     function create($id)
  2237.     {
  2238.         $this->id = $id;
  2239.     }
  2240.  
  2241.     function setDefaultText($text)
  2242.     {
  2243.         $this->defaultText = $text;
  2244.     }
  2245.  
  2246.     function setContent($content)
  2247.     {
  2248.         $this->body = $content;
  2249.     }
  2250.  
  2251.     function getContent()
  2252.     {
  2253.         if (strlen($this->body))
  2254.             return $this->body;
  2255.         return $this->defaultText;
  2256.     }
  2257.  
  2258.     /**
  2259.      * Setup the folder
  2260.      * 
  2261.      * @param string $folder The folder path to prepare
  2262.      * 
  2263.      * @return string
  2264.      */
  2265.     function prepFolder($folder)
  2266.     {
  2267.         if (strlen(trim($folder)) == 0)
  2268.             return "./";
  2269.  
  2270.         if (substr($folder, 0, -1) != "/")
  2271.             $folder .= "/";
  2272.  
  2273.         return $folder;
  2274.     }
  2275.  
  2276.     function loadFromFile($folder)
  2277.     {
  2278.         $folder = $this->prepFolder($folder);
  2279.         if (file_exists($folder . $this->id . ".txt"))
  2280.             $this->body = @file_get_contents($folder . $this->id . ".txt");
  2281.         else
  2282.             $this->body = "";
  2283.     }
  2284.  
  2285.     function saveToFile($folder)
  2286.     {
  2287.         $folder = $this->prepFolder($folder);
  2288.         if ($folder != "" && $folder != "/" && $folder != "." && $folder != "./" && !file_exists($folder)) {
  2289.             @mkdir($folder, 777, true);
  2290.         }
  2291.         return @file_put_contents($folder . $this->id . ".txt", $this->body);
  2292.     }
  2293.  
  2294.     function loadFromDb($host, $user, $password, $db, $table)
  2295.     {
  2296.         $db = new ImDb($host, $user, $password, $db);
  2297.         if (!$db->testConnection())
  2298.             return false;
  2299.         $data = $db->query("SELECT * FROM `" . $table . "` WHERE id='" . $db->escapeString($this->id) . "'");
  2300.         if (is_bool($data))
  2301.             return false;
  2302.         if (!isset($data[0]['body']))
  2303.             return false;
  2304.         $this->body = $data[0]['body'];
  2305.         return true;
  2306.     }
  2307.  
  2308.     function saveToDb($host, $user, $password, $db, $table)
  2309.     {
  2310.         $db = new ImDb($host, $user, $password, $db);
  2311.         if (!$db->testConnection())
  2312.             return false;
  2313.         $db->createTable(
  2314.             $table,
  2315.             array(
  2316.                 "id" => array('type' => 'VARCHAR(32)', 'primary' => true),
  2317.                 "body" => array('type' => 'TEXT')
  2318.             )
  2319.         );
  2320.         $exists = $db->query("SELECT * FROM `" . $table . "` WHERE id='" . $db->escapeString($this->id) . "'");
  2321.         if ($exists)
  2322.             return $db->query("UPDATE `" . $table . "` SET body='" . $db->escapeString($this->body) . "' WHERE id='" . $db->escapeString($this->id) . "'");
  2323.         return $db->query("INSERT INTO `" . $table . "` (id, body) VALUES ('" . $db->escapeString($this->id) . "', '" . $db->escapeString($this->body) . "')");
  2324.     }    
  2325. }
  2326.  
  2327.  
  2328.  
  2329.  
  2330. /**
  2331.  * Provide support for sending and saving the email form data
  2332.  */
  2333.  
  2334. class ImForm
  2335. {
  2336.  
  2337.     var $fields = array();
  2338.     var $files = array();
  2339.     var $answers = array();
  2340.  
  2341.     /**
  2342.      * Set the data of a field
  2343.      * 
  2344.      * @param string $label  The field label
  2345.      * @param strin  $value  The field value
  2346.      * @param string $dbname The name to use in the db
  2347.      * @param boolean $isSeparator True if this field must be used as separator in the email
  2348.      * 
  2349.      * @return boolean
  2350.      */
  2351.     function setField($label, $value, $dbname = "", $isSeparator = false)
  2352.     {
  2353.         $this->fields[] = array(
  2354.             "label"     => $label,
  2355.             "value"     => $value,
  2356.             "dbname"    => $dbname,
  2357.             "isSeparator" => $isSeparator
  2358.         );
  2359.         return true;
  2360.     }
  2361.  
  2362.     /**
  2363.      * Provide the currently set fields
  2364.      * 
  2365.      * @return array
  2366.      */
  2367.     function fields()
  2368.     {
  2369.         return $this->fields;
  2370.     }
  2371.  
  2372.     /**
  2373.      * Set a file field
  2374.      * 
  2375.      * @param string  $label      The field label
  2376.      * @param file    $value      The $_FILE[id] content
  2377.      * @param string  $folder     The folder in which the file must be saved
  2378.      * @param string  $dbname     The db column in which this filed must be saved
  2379.      * @param mixed   $extensions The extensions allowed for the file (string or array)
  2380.      * @param integer $maxsize    The max size (0 to not check this)
  2381.      * 
  2382.      * @param boolean
  2383.      */
  2384.     function setFile($label, $value, $folder = "", $dbname = "", $extensions = array(), $maxsize = 0)
  2385.     {
  2386.         if (is_string($extensions))
  2387.             $extensions = strlen($extensions) ? explode(",", strtolower($extensions)) : array();
  2388.  
  2389.         $exists = file_exists($value['tmp_name']);
  2390.         if (!$exists)
  2391.             return false;
  2392.         
  2393.         $fileExtension = strtolower(substr($value['name'], strpos($value['name'], ".") + 1));
  2394.         $extension = (count($extensions) == 0 || in_array($fileExtension, $extensions));
  2395.         $size = ($maxsize == 0 || $maxsize >= $value['size']);
  2396.  
  2397.         if (!$extension || !$size)
  2398.             return false;
  2399.             
  2400.         if ($folder != "" && substr($folder, 0, -1) != "/")
  2401.             $folder .= "/";
  2402.         $this->files[] = array(
  2403.             "value" => $value,
  2404.             "label" => $label,
  2405.             "dbname" => $dbname,
  2406.             "folder" => $folder,
  2407.             // Save the file content to set is as available for every istance in the class
  2408.             // This because after calling move_uploaded_file the temp file is not available anymore
  2409.             "content" => @file_get_contents($value['tmp_name'])
  2410.         );
  2411.         return true;
  2412.     }
  2413.  
  2414.     /**
  2415.      * Provides the currently set files
  2416.      *
  2417.      *  @return array
  2418.      */
  2419.     function files()
  2420.     {
  2421.         return $this->files;
  2422.     }
  2423.  
  2424.     /**
  2425.      * Set the answer to check
  2426.      * 
  2427.      * @param string $questionId The question id
  2428.      * @param string $answer     The correct answer
  2429.      *
  2430.      * @return void
  2431.      */
  2432.     function setAnswer($questionId, $answer)
  2433.     {
  2434.         $this->answers[$questionId] = $answer;
  2435.     }
  2436.  
  2437.     /**
  2438.      * Check if the answer $answer is correct for question $questionId
  2439.      * 
  2440.      * @param  string $questionId The question id
  2441.      * @param  string $answer     The answer
  2442.      * 
  2443.      * @return boolean
  2444.      */
  2445.     function checkAnswer($questionId, $answer)
  2446.     {
  2447.         $questionId += "";
  2448.         return (isset($this->answers[$questionId]) && trim(strtolower($this->answers[$questionId])) == trim(strtolower($answer)));
  2449.     }
  2450.  
  2451.     /**
  2452.      * Provides the currently set answers
  2453.      * 
  2454.      * @return array
  2455.      */
  2456.     function answers()
  2457.     {
  2458.         return $this->answers;
  2459.     }
  2460.  
  2461.     /**
  2462.      * Save the data in the database
  2463.      * 
  2464.      * @param  string $host
  2465.      * @param  string $user
  2466.      * @param  string $passwd
  2467.      * @param  string $database
  2468.      * @param  string $table
  2469.      * 
  2470.      * @return boolean
  2471.      */
  2472.     function saveToDb($host, $user, $passwd, $database, $table)
  2473.     {
  2474.         $db = new ImDb($host, $user, $passwd, $database);
  2475.         if (!$db->testConnection())
  2476.             return false;
  2477.  
  2478.         $fields = array();
  2479.         $names = array();
  2480.         $values = array();
  2481.  
  2482.         $i = 0;
  2483.         foreach ($this->fields as $field) {
  2484.             if (!$field['isSeparator']) {
  2485.                 $name = isset($field['dbname']) && $field['dbname'] !== "" ? $field['dbname'] : "field_" . $i++;
  2486.                 $fields[$name] = array(
  2487.                     "type" => "TEXT"
  2488.                 );
  2489.                 $names[] = "`" . $name . "`";
  2490.                 $values[] = "'" . $db->escapeString(is_array($field['value']) ? implode(", ", $field['value']) : $field['value']) . "'";
  2491.             }
  2492.         }
  2493.         $i = 0;
  2494.         foreach ($this->files as $file) {
  2495.             $fieldname = isset($file['dbname']) && $file['dbname'] !== "" ? $file['dbname'] : "file_" . $i++;
  2496.             $filename = $this->findFileName($file['folder'], $file['value']['name']);
  2497.             $fields[$fieldname] = array(
  2498.                 "type" => "TEXT"
  2499.             );
  2500.             $names[] = "`" . $fieldname . "`";
  2501.             $values[] = "'" . $db->escapeString($filename) . "'";
  2502.             // Create and check the folder
  2503.             $folder = "../";
  2504.             if (($pos = strpos($file['folder'], "/")) === 0)
  2505.                 $file['folder'] = substr($file['folder'], 1);
  2506.             $folder .= $file['folder'];
  2507.             if ($folder != "../" && !file_exists($folder))
  2508.                 @mkdir($folder, 0777, true);
  2509.             $folder = str_replace("//", "/", $folder .= $filename);
  2510.             // Save the file
  2511.             @move_uploaded_file($file['value']['tmp_name'], $folder);
  2512.         }
  2513.  
  2514.         // Create the table
  2515.         $db->createTable($table, $fields);
  2516.  
  2517.         // Save the fields data
  2518.         $query = "INSERT INTO `" . $table . "` (" . implode(",", $names) . ") VALUES (" . implode(",", $values) . ")";
  2519.         $db->query($query);
  2520.         $db->closeConnection();
  2521.         return true;
  2522.     }
  2523.  
  2524.     /**
  2525.      * Find a free filename
  2526.      * 
  2527.      * @param  string $folder   The folder in which the file is being saved
  2528.      * @param  string $tmp_name The filename
  2529.      * 
  2530.      * @return string           The new name
  2531.      */
  2532.     function findFileName($folder, $tmp_name)
  2533.     {
  2534.         $pos = strrpos($tmp_name, ".");
  2535.         $ext = ($pos !== false ? substr($tmp_name, $pos) : "");
  2536.         $fname = basename($tmp_name, $ext);            
  2537.         do {
  2538.             $rname = $fname . "_" . rand(0, 10000) .  $ext;
  2539.         } while (file_exists($folder . $rname));
  2540.         return $rname;
  2541.     }
  2542.  
  2543.     /**
  2544.      * Send the email to the site's owner
  2545.      * 
  2546.      * @param  string  $from
  2547.      * @param  string  $to
  2548.      * @param  string  $subject
  2549.      * @param  string  $text    The email body
  2550.      * @param  boolean $csv     Attach the CSV files?
  2551.      * 
  2552.      * @return boolean
  2553.      */
  2554.     function mailToOwner($from, $to, $subject, $text, $csv = false)
  2555.     {
  2556.         global $ImMailer;
  2557.  
  2558.         //Form Data
  2559.         $txtData = strip_tags($text);
  2560.         if (strlen($txtData))
  2561.              $txtData .= "\n\n";
  2562.         $htmData = nl2br($text);
  2563.         if (strlen($htmData))
  2564.             $htmData .= "\n<br><br>\n";
  2565.         $htmData .= "<table border=0 width=\"100%\" style=\"[email:contentStyle]\">\r\n";
  2566.         $csvHeader = "";
  2567.         $csvData = "";
  2568.         $firstField = true;
  2569.         
  2570.         foreach ($this->fields as $field) {
  2571.             if ($field['isSeparator']) {
  2572.                 //
  2573.                 // This field is a form separator
  2574.                 // 
  2575.                 $txtData .= (!$firstField ? "\r\n" : "") . $field['label'] . "\r\n" . str_repeat("=", strlen($field['label'])) . "\r\n";
  2576.                 $htmData .= "<tr valign=\"top\"><td colspan=\"2\" style=\"" . (!$firstField ? "padding-top: 8px;" : "") . " border-bottom: 1px solid [email:bodySeparatorBorderColor];\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $field['label']) . "</b></td></tr>\r\n";
  2577.             } else {
  2578.                 //
  2579.                 // This field is a classic form field
  2580.                 // 
  2581.                 $label = ($field['label'] != "" ? $field['label'] . ": " : "");
  2582.                 if (is_array($field['value'])) {
  2583.                     $txtData .= $label . implode(", ", $field['value']) . "\r\n";
  2584.                     $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . $label . "</b></td><td>" . implode(", ", $field['value']) . "</td></tr>\r\n";
  2585.                     if ($csv) {
  2586.                         $csvHeader .= $field['label'] . ";";
  2587.                         $csvData .= implode(", ", $field['value']) . ";";
  2588.                     }
  2589.                 } else {        
  2590.                     $txtData .= $label . $field['value'] . "\r\n";
  2591.                     // Is it an email?
  2592.                     if (preg_match('/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])' . '(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i', $field['value'])) {
  2593.                         $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td><a href=\"mailto:" . $field['value'] . "\">". $field['value'] . "</a></td></tr>\r\n";
  2594.                     } else if (preg_match('/^http[s]?:\/\/[a-zA-Z0-9\.\-]{2,}\.[a-zA-Z]{2,}/', $field['value'])) {
  2595.                         // Is it an URL?
  2596.                         $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td><a href=\"" . $field['value'] . "\">". $field['value'] . "</a></td></tr>\r\n";
  2597.                     } else {
  2598.                         $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td>" . str_replace(array("\\'", '\\"'), array("'", '"'), $field['value']) . "</td></tr>\r\n";
  2599.                     }
  2600.                     if ($csv) {
  2601.                         $csvHeader .= str_replace(array("\\'", '\\"'), array("'", '"'), $field['label']) . ";";
  2602.                         $csvData .= str_replace(array("\\'", '\\"'), array("'", '"'), $field['value']) . ";";
  2603.                     }
  2604.                 }
  2605.             }
  2606.             $firstField = false;
  2607.         }
  2608.  
  2609.         $htmData .= "</table>";
  2610.         $attachments = array();
  2611.         if ($csv) {
  2612.             $attachments[] = array(
  2613.                 "name" => "form_data.csv", 
  2614.                 "content" => $csvHeader . "\n" . $csvData,
  2615.                 "mime" => "text/csv"
  2616.             );
  2617.         }
  2618.         foreach ($this->files as $file) {
  2619.             $attachments[] = array(
  2620.                 'name' => $file['value']['name'],
  2621.                 'content' => $file['content'],
  2622.                 'mime' => $file['value']['type']
  2623.             );
  2624.         }
  2625.         return $ImMailer->send($from, $to, $subject, $txtData, $htmData, $attachments);
  2626.     }
  2627.  
  2628.     /**
  2629.      * Send the email to the site's customer
  2630.      * 
  2631.      * @param  string  $from
  2632.      * @param  string  $to
  2633.      * @param  string  $subject
  2634.      * @param  string  $text    The email body
  2635.      * @param  boolean $summary Append the data to the email? (It's not an attachment)
  2636.      * 
  2637.      * @return boolean
  2638.      */
  2639.     function mailToCustomer($from, $to, $subject, $text, $csv = false)
  2640.     {
  2641.         global $ImMailer;
  2642.  
  2643.         //Form Data
  2644.         $txtData = strip_tags($text);
  2645.         if (strlen($txtData))
  2646.             $txtData .= "\n\n";
  2647.         $htmData = nl2br($text);
  2648.         if (strlen($htmData))
  2649.             $htmData .= "\n<br><br>\n";
  2650.         $csvHeader = "";
  2651.         $csvData = "";
  2652.         $firstField = true;
  2653.         
  2654.         if ($csv) {
  2655.             $htmData .= "<table border=0 width=\"100%\" style=\"[email:contentStyle]\">\r\n";
  2656.             foreach ($this->fields as $field) {
  2657.                 if ($field['isSeparator']) {
  2658.                     //
  2659.                     // This field is a form separator
  2660.                     // 
  2661.                     $txtData .= (!$firstField ? "\r\n" : "") . $field['label'] . "\r\n" . str_repeat("=", strlen($field['label'])) . "\r\n";
  2662.                     $htmData .= "<tr valign=\"top\"><td colspan=\"2\" style=\"" . (!$firstField ? "padding-top: 8px;" : "") . " border-bottom: 1px solid [email:bodySeparatorBorderColor];\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $field['label']) . "</b></td></tr>\r\n";
  2663.                 } else {
  2664.                     //
  2665.                     // This field is a classic form field
  2666.                     // 
  2667.                     $label = ($field['label'] != "" ? $field['label'] . ": " : "");
  2668.                     if (is_array($field['value'])) {
  2669.                         $txtData .= $label . implode(", ", $field['value']) . "\r\n";
  2670.                         $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . $label . "</b></td><td>" . implode(", ", $field['value']) . "</td></tr>\r\n";
  2671.                         if ($csv) {
  2672.                             $csvHeader .= $field['label'] . ";";
  2673.                             $csvData .= implode(", ", $field['value']) . ";";
  2674.                         }
  2675.                     } else {                        
  2676.                         $txtData .= $label . $field['value'] . "\r\n";
  2677.                         // Is it an email?
  2678.                         if (preg_match('/^([a-z0-9])(([-a-z0-9._])*([a-z0-9]))*\@([a-z0-9])' . '(([a-z0-9-])*([a-z0-9]))+' . '(\.([a-z0-9])([-a-z0-9_-])?([a-z0-9])+)+$/i', $field['value'])) {
  2679.                             $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td><a href=\"mailto:" . $field['value'] . "\">". $field['value'] . "</a></td></tr>\r\n";
  2680.                         } else if (preg_match('/^http[s]?:\/\/[a-zA-Z0-9\.\-]{2,}\.[a-zA-Z]{2,}/', $field['value'])) {
  2681.                             // Is it an URL?
  2682.                             $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td><a href=\"" . $field['value'] . "\">". $field['value'] . "</a></td></tr>\r\n";
  2683.                         } else {
  2684.                             $htmData .= "<tr valign=\"top\"><td width=\"25%\"><b>" . str_replace(array("\\'", '\\"'), array("'", '"'), $label) . "</b></td><td>" . str_replace(array("\\'", '\\"'), array("'", '"'), $field['value']) . "</td></tr>\r\n";
  2685.                         }
  2686.                         if ($csv) {
  2687.                             $csvHeader .= str_replace(array("\\'", '\\"'), array("'", '"'), $field['label']) . ";";
  2688.                             $csvData .= str_replace(array("\\'", '\\"'), array("'", '"'), $field['value']) . ";";
  2689.                         }
  2690.                     }
  2691.                 }
  2692.                 $firstField = false;
  2693.             }
  2694.             $htmData .= "</table>\n";
  2695.         }
  2696.         
  2697.         return $ImMailer->send($from, $to, $subject, $txtData, $htmData);
  2698.     }
  2699. }
  2700.  
  2701.  
  2702.  
  2703. /**
  2704.  * Private area
  2705.  * @access public
  2706.  */
  2707. class imPrivateArea
  2708. {
  2709.  
  2710.     var $session_type;
  2711.     var $session_uname;
  2712.     var $session_uid;
  2713.     var $session_gids;
  2714.     var $session_page;
  2715.     var $cookie_name;
  2716.     var $salt;
  2717.     var $db = false;
  2718.     var $db_table;
  2719.  
  2720.     // PHP 5
  2721.     function __contruct()
  2722.     {
  2723.         $this->setup();
  2724.     }
  2725.  
  2726.     // PHP 4
  2727.     function imPrivateArea()
  2728.     {
  2729.         $this->setup();
  2730.     }
  2731.  
  2732.     function setup() {
  2733.         global $imSettings;
  2734.  
  2735.         $this->session_type      = "im_access_utype";
  2736.         $this->session_uname     = "im_access_uname";
  2737.         $this->session_real_name = "im_access_real_name";
  2738.         $this->session_page      = "im_access_request_page";
  2739.         $this->session_uid       = "im_access_uid";
  2740.         $this->session_gids      = "im_access_gids";
  2741.         $this->cookie_name       = "im_access_cookie_uid";
  2742.         $this->salt              = $imSettings['general']['salt'];
  2743.     }
  2744.  
  2745.     /**
  2746.      * Encode the string
  2747.      * 
  2748.      * @param  string $string The string to encode
  2749.      * @param  $key The encryption key
  2750.      * 
  2751.      * @return string    The encoded string
  2752.      */
  2753.     function _encode($s, $k)
  2754.     {
  2755.         $r = array();
  2756.         for($i = 0; $i < strlen($s); $i++)
  2757.             $r[] = ord($s[$i]) + ord($k[$i % strlen($k)]);
  2758.  
  2759.         // Try to encode it using base64
  2760.         if (function_exists("base64_encode") && function_exists("base64_decode"))
  2761.             return base64_encode(implode('.', $r));
  2762.  
  2763.         return implode('.', $r);
  2764.     }
  2765.  
  2766.     /**
  2767.      * Decode the string
  2768.      * 
  2769.      * @param  string $s The string to decode
  2770.      * @param  string $k The encryption key
  2771.      * @return string    The decoded string
  2772.      */
  2773.     function _decode($s, $k)
  2774.     {
  2775.  
  2776.         // Try to decode it using base64
  2777.         if (function_exists("base64_encode") && function_exists("base64_decode"))
  2778.             $s = base64_decode($s);
  2779.  
  2780.         $s = explode(".", $s);
  2781.         $r = array();
  2782.         for($i = 0; $i < count($s); $i++)
  2783.             $r[$i] = chr($s[$i] - ord($k[$i % strlen($k)]));
  2784.         return implode('', $r);
  2785.     }
  2786.  
  2787.     /**
  2788.      * Login
  2789.      * 
  2790.      * @access public
  2791.      * 
  2792.      * @param uname Username (string)
  2793.      * @param pwd Password (string)
  2794.      */
  2795.     function login($uname, $pwd)
  2796.     {
  2797.         global $imSettings;
  2798.  
  2799.         if (!strlen($uname) || !strlen($pwd))
  2800.             return -2;
  2801.  
  2802.         // Check if the user exists in the hardcoded file
  2803.         if (isset($imSettings['access']['users'][$uname]) && $imSettings['access']['users'][$uname]['password'] == $pwd) {
  2804.             $this->_setSession(
  2805.                 "1",
  2806.                 $imSettings['access']['users'][$uname]['id'],
  2807.                 $imSettings['access']['users'][$uname]['groups'],
  2808.                 $uname,
  2809.                 $imSettings['access']['users'][$uname]['name']
  2810.             );
  2811.             return 0;
  2812.         }
  2813.         // Check if the user exists in the DB and it's validated
  2814.         if (!$this->db)
  2815.             return -1;
  2816.         $user = $this->db->query("SELECT * FROM `" . $this->db_table . "` WHERE BINARY `username`='" . $this->db->escapeString($uname) . "' AND BINARY `password`='" . $this->db->escapeString($pwd) . "'");
  2817.         if (!is_array($user) || !count($user))
  2818.             return -2;
  2819.         if (!$user[0]['validated'])
  2820.             return -5;
  2821.         $this->_setSession("0", $user[0]['id'], isset($imSettings['access']['webregistrations_gid']) ? array($imSettings['access']['webregistrations_gid']) : array(), $user[0]['username'], $user[0]['realname']);
  2822.         return 0;
  2823.     }
  2824.  
  2825.     /**
  2826.      * Set the session after the login
  2827.      *
  2828.      * @param string $type "0" or "1"
  2829.      * @param string $uid
  2830.      * @param Array  $gids
  2831.      * @param string $uname   
  2832.      * @param string $realname
  2833.      */
  2834.     function _setSession($type, $uid, $gids, $uname, $realname)
  2835.     {
  2836.         @session_regenerate_id();
  2837.         $_SESSION[$this->session_type]      = $this->_encode($type, $this->salt);
  2838.         $_SESSION[$this->session_uid]       = $this->_encode($uid, $this->salt);
  2839.         $_SESSION[$this->session_uname]     = $this->_encode($uname, $this->salt);
  2840.         $_SESSION[$this->session_real_name] = $this->_encode($realname, $this->salt);
  2841.         $_SESSION[$this->session_gids]      = $gids;
  2842.         $_SESSION['HTTP_USER_AGENT']        = md5($_SERVER['HTTP_USER_AGENT'] . $this->salt);
  2843.         @setcookie($this->cookie_name, $this->_encode($uid, $this->salt), 0, "/"); // Expires when the browser is closed
  2844.     }
  2845.  
  2846.     /**
  2847.      * Logout
  2848.      * 
  2849.      * @access public
  2850.      */
  2851.     function logout()
  2852.     {
  2853.         $_SESSION[$this->session_type]  = "";
  2854.         $_SESSION[$this->session_uname] = "";
  2855.         $_SESSION[$this->session_uid]   = "";
  2856.         $_SESSION[$this->session_page]  = "";
  2857.         $_SESSION[$this->session_gids]  = array();
  2858.         $_SESSION['HTTP_USER_AGENT']    = "";
  2859.         @setcookie($this->cookie_name, "", time() - 3600, "/");
  2860.         $_COOKIE[$this->cookie_name]    = "";
  2861.     }
  2862.  
  2863.     /**
  2864.      * Save the referrer page
  2865.      * 
  2866.      * @access public
  2867.      */
  2868.     function savePage()
  2869.     {
  2870.         global $imSettings;
  2871.         $url = basename($_SERVER['PHP_SELF']);
  2872.         if (isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']))
  2873.             $url .= "?" . $_SERVER['QUERY_STRING'];
  2874.         $_SESSION[$this->session_page] = $this->_encode($url, $this->salt);
  2875.     }
  2876.  
  2877.     /**
  2878.      * Return to the referrer page
  2879.      * 
  2880.      * @access public
  2881.      */
  2882.     function getSavedPage()
  2883.     {
  2884.         global $imSettings;
  2885.         if (isset($_SESSION[$this->session_page]) && $_SESSION[$this->session_page] != "")
  2886.             return $this->_decode($_SESSION[$this->session_page], $this->salt);
  2887.         return false;
  2888.     }
  2889.  
  2890.     /**
  2891.      * Get an array of data about the logged user
  2892.      * @access public
  2893.      */
  2894.     function who_is_logged()
  2895.     {
  2896.         global $imSettings;
  2897.         if (isset($_SESSION[$this->session_uname]) && $_SESSION[$this->session_uname] != "" && isset($_SESSION[$this->session_uname])) {
  2898.             $uname = $this->_decode($_SESSION[$this->session_uname], $this->salt);
  2899.             return array(
  2900.                 "username" => $uname,
  2901.                 "uid"      => $this->_decode($_SESSION[$this->session_uid], $this->salt),
  2902.                 "realname" => $this->_decode($_SESSION[$this->session_real_name], $this->salt),
  2903.                 "groups"   => $_SESSION[$this->session_gids]
  2904.             );
  2905.         }
  2906.         return false;
  2907.     }
  2908.  
  2909.     /**
  2910.      * Check if the logged user can access to a page
  2911.      * 
  2912.      * @access public
  2913.      * 
  2914.      * @param page The page id (string)
  2915.      */
  2916.     function checkAccess($page)
  2917.     {
  2918.         global $imSettings;
  2919.  
  2920.         //
  2921.         // The session can live only in the same browser
  2922.         //
  2923.  
  2924.         if (!isset($_SESSION[$this->session_type]) || $_SESSION[$this->session_type] == "" || !isset($_SESSION[$this->session_uid]) || $_SESSION[$this->session_uid] == "")
  2925.             return -3;
  2926.  
  2927.         if (!isset($_SESSION['HTTP_USER_AGENT']) || $_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'] . $this->salt))
  2928.             return -2;
  2929.  
  2930.         if ($this->_decode($_SESSION[$this->session_type], $this->salt) == "0" && $_SESSION[$this->session_uid] != "") {
  2931.             if (!@in_array($page, $imSettings['access']['waitingpages']))
  2932.                 return -4;
  2933.             return 0;
  2934.         }
  2935.         $uid = $this->_decode($_SESSION[$this->session_uid], $this->salt);
  2936.         if (!@in_array($uid, $imSettings['access']['pages'][$page]) && !@in_array($uid, $imSettings['access']['admins']))
  2937.             return -8; // The active user cannot access to this page
  2938.         return 0;
  2939.     }
  2940.  
  2941.     /**
  2942.      * Get the user's landing page
  2943.      * 
  2944.      * @access public
  2945.      */
  2946.     function getLandingPage()
  2947.     {
  2948.         global $imSettings;
  2949.         if (!isset($_SESSION[$this->session_type]) || !isset($_SESSION[$this->session_uname]) || $_SESSION[$this->session_uname] === '' || !isset($_SESSION[$this->session_uid]) || $_SESSION[$this->session_uid] === '')
  2950.             return false;
  2951.  
  2952.         if ($this->_decode($_SESSION[$this->session_type], $this->salt) == "0")
  2953.             return $imSettings['access']['entrancepage'];
  2954.  
  2955.         return $imSettings['access']['users'][$this->_decode($_SESSION[$this->session_uname], $this->salt)]['page'];
  2956.     }
  2957.  
  2958.     /**
  2959.      * Convert a status code to a text message
  2960.      * 
  2961.      * @param  int $code A status code
  2962.      * 
  2963.      * @return string
  2964.      */
  2965.     function messageFromStatusCode($code)
  2966.     {
  2967.         switch ($code) {
  2968.  
  2969.             // Error
  2970.             case -8 : return l10n("private_area_account_not_allowed", "Your account is not allowed to access the selected page");
  2971.             case -7 : return l10n("private_area_lostpassword_error", "We cannot find your data.");
  2972.             case -6 : return l10n("private_area_user_already_exists", "The user already exists.");
  2973.             case -5 : return l10n("private_area_not_validated", "Your account is not yet validated.");
  2974.             case -4 : return l10n("private_area_waiting", "Your account is not yet active.");
  2975.             //case -3 : return l10n("private_area_not_allowed", "A login is required to access this page.");
  2976.             case -2 : return l10n("private_area_login_error", "Wrong username or password.");
  2977.             case -1 : return l10n("private_area_generic_error", "Generic error.");
  2978.  
  2979.             // Success
  2980.             case 2  : return l10n('private_area_validation_sent', 'We sent you a validation email.');
  2981.             case 3  : return l10n('private_area_registration_success', 'You are now registered.');
  2982.             case 4  : return l10n('private_area_lostpassword_success', 'We sent you an email with your password.');
  2983.  
  2984.             default : return "";
  2985.         }
  2986.     }
  2987.  
  2988.     /**
  2989.      * Redirect in a session safe mode. IIS requires this.
  2990.      * 
  2991.      * @param  string $to
  2992.      * 
  2993.      * @return void
  2994.      */
  2995.     function sessionSafeRedirect($to)
  2996.     {
  2997.         exit('<!DOCTYPE html><html lang="it" dir="ltr"><head><title>Loading...</title><meta http-equiv="refresh" content="1; url=' . $to . '"></head><body><p style="text-align: center;">Loading...</p></body></html>');
  2998.     }
  2999.  
  3000.     /**
  3001.      * Get the user data
  3002.      * @param  String $id The username
  3003.      * @return Array The user's data or null if the user is not found
  3004.      */
  3005.     function getUserByUsername($username)
  3006.     {
  3007.         global $imSettings;
  3008.         
  3009.         // Search in the file
  3010.         if (isset($imSettings['access']['users'][$username])) {
  3011.             $user = $imSettings['access']['users'][$username];
  3012.             return array(
  3013.                 "id"        => $user['id'],
  3014.                 "ts"        => "",
  3015.                 "ip"        => "",
  3016.                 "username"  => $username,
  3017.                 "password"  => $user['password'],
  3018.                 "realname"  => $user['name'],
  3019.                 "email"     => $user['email'],
  3020.                 "key"       => "",
  3021.                 "validated" => true,
  3022.                 "groups"    => $user['groups']
  3023.             );
  3024.         }
  3025.         // Search in the DB
  3026.         $res = $this->db->query("SELECT * FROM `" . $this->db_table . "` WHERE `username`='" . $this->db->escapeString($username) . "'");
  3027.         if (count($res) > 0) {
  3028.             $user = $res[0];
  3029.             return array(
  3030.                 "id"        => $user['id'],
  3031.                 "ts"        => $user['ts'],
  3032.                 "ip"        => $user['ip'],
  3033.                 "username"  => $user['username'],
  3034.                 "password"  => $user['password'],
  3035.                 "realname"  => $user['realname'],
  3036.                 "email"     => $user['email'],
  3037.                 "key"       => $user['key'],
  3038.                 "validated" => $user['validated'],
  3039.                 "groups"    => array($imSettings['access']['webregistrations_gid'])
  3040.             );
  3041.         }
  3042.         return null;
  3043.     }
  3044.  
  3045.      
  3046.     function getUsersById($ids = array())
  3047.     {
  3048.         if (is_string($ids)) {
  3049.             if (strlen($ids))
  3050.                 $ids = array($ids);
  3051.             else
  3052.                 $ids = array();
  3053.         }
  3054.  
  3055.         $res = $this->db->query("SELECT * FROM `" . $this->db_table . "`" . (count($ids) ? " WHERE `id` IN (" . implode(",", $ids) . ")" : ""));
  3056.         $users = array();
  3057.         foreach ($res as $user) {
  3058.             $users[] = array(
  3059.                 "id"        => $user['id'],
  3060.                 "ts"        => $user['ts'],
  3061.                 "ip"        => $user['ip'],
  3062.                 "username"  => $user['username'],
  3063.                 "password"  => $user['password'],
  3064.                 "realname"  => $user['realname'],
  3065.                 "email"     => $user['email'],
  3066.                 "key"       => $user['key'],
  3067.                 "validated" => $user['validated']
  3068.             );
  3069.         }
  3070.         return $users;
  3071.     }
  3072.     
  3073.     /**
  3074.      * Setup the db connection
  3075.      * 
  3076.      * @param string $host
  3077.      * @param string $username
  3078.      * @param string $password
  3079.      * @param string $dbname
  3080.      * @param string $dbtable
  3081.      */
  3082.     function setDBData($host, $username, $password, $dbname, $dbtable)
  3083.     {
  3084.         $this->db = new ImDb($host, $username, $password, $dbname);
  3085.         $this->db_table = $dbtable;
  3086.         if (!$this->db->testConnection())
  3087.             die("Unable to connect to DB");
  3088.     }
  3089.     
  3090.     /**
  3091.      * Get an encoded JSON list of the waiting users' data
  3092.      *
  3093.      * @param  string $encKey The encryption key used to encode the json data
  3094.      * 
  3095.      * @return string
  3096.      */
  3097.     function getWaitingUsers($encKey = "")
  3098.     {
  3099.         if (!$this->db || !$this->db->tableExists($this->db_table))
  3100.             return "";
  3101.         $users = array(
  3102.             "extra" => array("timestamp" => date("Y-m-d H:i:s")),
  3103.             "users" => $this->getUsersById()
  3104.         );
  3105.         return json_encode($users);
  3106.     }
  3107.  
  3108.     /**
  3109.      * Validate the waiting users listed in $ids. It must be an array of DB ids
  3110.      * 
  3111.      * @param  array  $dbid
  3112.      * 
  3113.      * @return bool
  3114.      */
  3115.     function validateWaitingUserById($dbids = array())
  3116.     {
  3117.         if (!is_array($dbids))
  3118.             $dbids = array($dbids);
  3119.         if (!count($dbids))
  3120.             return false;
  3121.         $this->db->query("UPDATE `" . $this->db_table . "` SET `validated`=1, ts=ts WHERE `validated`=0 AND `id` IN (" . implode(",", $this->db->escapeString($dbids)) . ")");
  3122.         return $this->db->affectedRows() > 0;
  3123.     }
  3124.  
  3125.     /**
  3126.      * Validate the waiting users listed in $keys. It must be an array of DB keys.
  3127.      * 
  3128.      * @param  array $keys
  3129.      * @param  boolean $login Automatically login the user if validation is succesful
  3130.      * 
  3131.      * @return booleal
  3132.      */
  3133.     function validateWaitingUserByKey($keys = array(), $login = false)
  3134.     {
  3135.         $user = false;
  3136.         if (!is_array($keys))
  3137.             $keys = array($keys);
  3138.  
  3139.         if ($login && count($keys) == 1) {
  3140.             $user = $this->db->query("SELECT `username`, `password` FROM `" . $this->db_table . "` WHERE `key`='" . $this->db->escapeString($keys[0]) . "'");
  3141.             if (is_bool($user))
  3142.                 return false;
  3143.             $user = $user[0];
  3144.         }
  3145.         $this->db->query("UPDATE `" . $this->db_table . "` SET `validated`=1, `ts`=NOW(), `ip`='" . $this->db->escapeString($_SERVER['REMOTE_ADDR']) . "' WHERE `validated`=0 AND `key` IN ('" . implode("','", $this->db->escapeString($keys)) . "')");
  3146.         if ($user && $this->db->affectedRows())
  3147.             return $this->login($user['username'], $user['password']) == 0;
  3148.         return $this->db->affectedRows() > 0;
  3149.     }
  3150.  
  3151.     /**
  3152.      * Remove the remaining waiting users
  3153.      *
  3154.      * @param  string $ts          Remove only the users registered before this timestamp.
  3155.      * @param  array  $usersToKeep Remove all the users but keep the ones listed in this array
  3156.      * 
  3157.      * @return void
  3158.      */
  3159.     function removeWaitingUsers($ts, $usersToKeep = array())
  3160.     {
  3161.         if (!$this->db || !$this->db->tableExists($this->db_table))
  3162.             return;
  3163.         $query = "DELETE FROM `" . $this->db_table . "` WHERE `ts`<='" . $this->db->escapeString($ts) . "'";
  3164.         if (!is_array($usersToKeep))
  3165.             $usersToKeep = array($usersToKeep);
  3166.         if (count($usersToKeep))
  3167.             $query .= " AND id NOT IN (" . implode(",", $this->db->escapeString($usersToKeep)) . ")";
  3168.         $this->db->query($query);
  3169.     }
  3170.  
  3171.     /**
  3172.      * Get the validation key of user $dbid
  3173.      * 
  3174.      * @param  string $dbid
  3175.      * 
  3176.      * @return string The validation key
  3177.      */
  3178.     function getKeyFromId($dbid)
  3179.     {
  3180.         $key = $this->db->query("SELECT `key` FROM `" . $this->db_table . "` WHERE `id`=" . (int)$dbid);
  3181.         if (!is_bool($key) && count($key))
  3182.             return $key[0]['key'];
  3183.         return false;
  3184.     }
  3185.  
  3186.     /**
  3187.      * Create the users table if it doesn't exist
  3188.      * 
  3189.      * @return void
  3190.      */
  3191.     function createUsersTable()
  3192.     {
  3193.         if (!$this->db || $this->db->tableExists($this->db_table))
  3194.             return;
  3195.         $this->db->createTable(
  3196.             $this->db_table,
  3197.             array(
  3198.                 "id"        => array('type' => 'INT(11)', 'primary' => true, 'auto_increment' => true),
  3199.                 "ts"        => array('type' => 'TIMESTAMP'),
  3200.                 "ip"        => array('type' => 'VARCHAR(16)'),
  3201.                 "username"  => array('type' => 'TEXT'),
  3202.                 "password"  => array('type' => 'TEXT'),
  3203.                 "realname"  => array('type' => 'TEXT'),
  3204.                 "email"     => array('type' => 'TEXT'),
  3205.                 "key"       => array('type' => 'VARCHAR(32)'),
  3206.                 "validated" => array('type' => 'INT(1)')
  3207.             )
  3208.         );
  3209.     }
  3210.  
  3211.     /**
  3212.      * Register a new user
  3213.      * 
  3214.      * @param string $username
  3215.      * @param string $password
  3216.      * @param string $email   
  3217.      * @param string $validated
  3218.      * 
  3219.      * @return Number the user's ID or the error number (-1: user already exists, -2: generic error)
  3220.      */
  3221.     function registerNewUser($username, $password, $realname, $email, $validated)
  3222.     {
  3223.         global $imSettings;
  3224.  
  3225.         if (!$this->db)
  3226.             return -1;
  3227.         if (!strlen($username) || !strlen($password) || !strlen($email))
  3228.             return -1;
  3229.  
  3230.         $this->createUsersTable();
  3231.  
  3232.         // Check if the user already exists in the hardcoded file
  3233.         if (isset($imSettings['access']['users'][$username]))
  3234.             return -6;
  3235.  
  3236.         // Check if the user already exists in the DB as validated user
  3237.         if (count($this->db->query("SELECT  `username` FROM `" . $this->db_table . "` WHERE `username`='" . $this->db->escapeString($username) . "' AND `validated`='1'")))
  3238.             return -6;
  3239.  
  3240.         // Check if the user already exists in the DB as not validated user
  3241.         if (count($res = $this->db->query("SELECT  `id`, `username` FROM `" . $this->db_table . "` WHERE `username`='" . $this->db->escapeString($username) . "' AND `validated`='0'")))
  3242.             return $res[0]['id'];
  3243.  
  3244.         // Create the user's record
  3245.         $this->db->query("INSERT INTO `" . $this->db_table . "` (`ts`, `ip`, `username`, `password`, `realname`, `email`, `key`, `validated`) VALUES (" .
  3246.             "'" . date("Y-m-d H:i:s") . "'," .
  3247.             "'" . $this->db->escapeString($_SERVER['REMOTE_ADDR']) . "'," .
  3248.             "'" . $this->db->escapeString($username) . "'," .
  3249.             "'" . $this->db->escapeString($password) . "'," .
  3250.             "'" . $this->db->escapeString($realname) . "'," .
  3251.             "'" . $this->db->escapeString($email) . "'," .
  3252.             "'" . md5($username . $password . date("U") . rand(1000, 9999)) . "'," .
  3253.             "'" . $this->db->escapeString($validated) . "'" .
  3254.         ")");
  3255.         return $this->db->lastInsertId();
  3256.     }
  3257.  
  3258.     /**
  3259.      * Notify the registration of a new user
  3260.      * 
  3261.      * @param  int    $id    
  3262.      * @param  string $emailTo
  3263.      * 
  3264.      * @return void
  3265.      */
  3266.     function sendNotificationEmail($id, $emailTo)
  3267.     {
  3268.         global $ImMailer;
  3269.         global $imSettings;
  3270.         $html = "";
  3271.  
  3272.         $user = $this->getUsersById($id);
  3273.         $user = $user[0];
  3274.         if (is_bool($user) || !count($user))
  3275.             return;
  3276.  
  3277.         $subject = str_replace("[FIELD]", $imSettings['general']['url'], l10n("private_area_newregistration_subject", "A new user registered to your private area at [FIELD]"));
  3278.         $html .= nl2br(str_replace(
  3279.                 array("[FIELD]", "\n"),
  3280.                 array($imSettings['general']['url'], "<br />\n"),
  3281.                 l10n("private_area_newregistration_body", "Here's his data.")
  3282.             )) . "<br /><br />\n\n";
  3283.         $html .= "<b>" . l10n("private_area_realname", "Name") . ":</b> " . $user['realname'] . "<br />\n";
  3284.         $html .= "<b>" . l10n("private_area_username", "Username") . ":</b> " . $user['username'] . "<br />\n";
  3285.         $html .= "<b>" . l10n("private_area_email", "Email") . ":</b> " . $user['email'] . "<br />\n";
  3286.         $html .= "<b>" . l10n("private_area_ip", "IP") . ":</b> " . $user['ip'] . "<br />\n";
  3287.         $html .= "<b>" . l10n("private_area_ts", "Time") . ":</b> " . $user['ts'] . "<br />\n";
  3288.  
  3289.         $ImMailer->send(strlen($user['email']) ? $user['email'] : $emailTo, $emailTo, $subject, strip_tags($html), $html);
  3290.     }
  3291.  
  3292.     /**
  3293.      * Send the validation email for the user indentified by $id
  3294.      *
  3295.      * @param  string $id
  3296.      * @param  string $emailFrom [description]
  3297.      * 
  3298.      * @return void
  3299.      */
  3300.     function sendValidationEmail($dbid, $emailFrom)
  3301.     {
  3302.         global $ImMailer;
  3303.         global $imSettings;
  3304.  
  3305.         $html = "";
  3306.  
  3307.         $user = $this->getUsersById($dbid);
  3308.         $user = $user[0];
  3309.         if (is_bool($user) || !count($user))
  3310.             return;
  3311.  
  3312.         $subject = str_replace("[FIELD]", $imSettings['general']['url'], l10n("private_area_validation_subject", "Validate your account on [FIELD]"));
  3313.         $html .= l10n("private_area_validation_body", "Click here to validate your account:") . " ";
  3314.         $html .= "<a href=\"" . $imSettings['general']['url'] . "/imlogin.php?validate=" . $user['key'] . "\">";
  3315.         $html .= $imSettings['general']['url'] . "/imlogin.php?validate=" . $user['key'];
  3316.         $html .= "</a>";
  3317.  
  3318.         $ImMailer->send($emailFrom, $user['email'], $subject, strip_tags($html), $html);
  3319.     }
  3320.  
  3321.     /**
  3322.      * Notify to the admin that this user has lost his password
  3323.      * 
  3324.      * @param  string $data The user's email or username
  3325.      * @param  string $emailFrom
  3326.      * 
  3327.      * @return boolean
  3328.      */
  3329.     function sendLostPasswordEmail($data, $emailFrom)
  3330.     {
  3331.         global $ImMailer;
  3332.         global $imSettings;
  3333.  
  3334.         $username = false;
  3335.         $password = false;
  3336.         $emailTo = false;
  3337.  
  3338.         $query = "SELECT `email`, `username`, `password` FROM `" . $this->db_table . "` ";
  3339.         $query .= "WHERE username='" . $this->db->escapeString($data) ."' OR email='" . $this->db->escapeString($data) ."'";
  3340.         $user = $this->db->query($query);
  3341.         if (!is_bool($user) && count($user)) {
  3342.             $emailTo = $user[0]['email'];
  3343.             $username = $user[0]['username'];
  3344.             $password = $user[0]['password'];
  3345.         } else {
  3346.             foreach ($imSettings['access']['users'] as $uname => $user) {
  3347.                 // If the email identify a user, send the message to him, otherwise send a message to the admin
  3348.                 if ($uname == $data || $user['email'] == $data) {
  3349.                     $emailTo = strlen($user['email']) ? $user['email'] : false;
  3350.                     $username = $uname;
  3351.                     $password = $user['password'];
  3352.                     break;
  3353.                 }
  3354.             }
  3355.         }
  3356.  
  3357.         if (!$username || !$password)
  3358.             return false;
  3359.  
  3360.         if (!$emailTo) {
  3361.             // Send an email to the admin
  3362.             $emailTo = $emailFrom;
  3363.             $subject = str_replace("[FIELD]", $imSettings['general']['url'], l10n("private_area_password_recovery_subject_admin", "Password recovery request from [FIELD]"));
  3364.             $html = nl2br(str_replace(
  3365.                 array("[FIELD]", "[URL]", "\n"),
  3366.                 array($username, $imSettings['general']['url'], "<br />\n"),
  3367.                 l10n("private_area_password_recovery_body_admin", "The user [FIELD] on [URL] wants to recover his own username and password.")
  3368.             ));
  3369.         } else {
  3370.             // Send an email to the user
  3371.             $subject = str_replace("[FIELD]", $imSettings['general']['url'], l10n("private_area_password_recovery_subject_user", "Password recovered for [FIELD]"));
  3372.             $html = l10n("private_area_password_recovery_body_user", "Here is your account data: ") . "<br /><br />\n\n";
  3373.             $html .= "<b>" . l10n("private_area_username", "Username") . ":</b> " . $username . "<br />\n";
  3374.             $html .= "<b>" . l10n("private_area_password", "Password") . ":</b> " . $password . "<br />\n";
  3375.         }
  3376.  
  3377.         $ImMailer->send($emailFrom, $emailTo, $subject, strip_tags($html), $html);
  3378.         return true;
  3379.     }
  3380.  
  3381. }
  3382.  
  3383. /**
  3384.  * Contains the methods used by the search engine
  3385.  * @access public
  3386.  */
  3387. class imSearch {
  3388.  
  3389.     var $scope;
  3390.     var $page;
  3391.     var $results_per_page;
  3392.  
  3393.     function __construct()
  3394.     {
  3395.         $this->setScope();
  3396.         $this->results_per_page = 10;
  3397.     }
  3398.  
  3399.     function imSearch()
  3400.     {
  3401.         $this->setScope();
  3402.         $this->results_per_page = 10;
  3403.     }
  3404.  
  3405.     /**
  3406.      * Loads the pages defined in search.inc.php  to the search scope
  3407.      * @access public
  3408.      */
  3409.     function setScope()
  3410.     {
  3411.         global $imSettings;
  3412.         $scope = $imSettings['search']['general']['defaultScope'];
  3413.  
  3414.         // Logged users can search in their private pages
  3415.         $pa = new imPrivateArea();
  3416.         if ($user = $pa->who_is_logged()) {
  3417.             foreach ($imSettings['search']['general']['extendedScope'] as $key => $value) {
  3418.                 if (in_array($user['uid'], $imSettings['access']['pages'][$key]))
  3419.                     $scope[] = $value;
  3420.             }
  3421.         }
  3422.  
  3423.         $this->scope = $scope;
  3424.     }
  3425.  
  3426.     /**
  3427.      * Do the pages search
  3428.      * @access public
  3429.      * @param queries The search query (array)
  3430.      */
  3431.     function searchPages($queries)
  3432.     {
  3433.         
  3434.         global $imSettings;
  3435.         $html = "";
  3436.         $found_content = array();
  3437.         $found_count = array();
  3438.  
  3439.         if (is_array($this->scope)) {
  3440.             foreach ($this->scope as $filename) {
  3441.                 $count = 0;
  3442.                 $weight = 0;
  3443.                 $file_content = @implode("\n", file($filename));
  3444.                 if (function_exists("html_entity_decode"))
  3445.                     $file_content = html_entity_decode($file_content, ENT_COMPAT, 'UTF-8');
  3446.  
  3447.                 // Remove the page menu
  3448.                 while (stristr($file_content, "<div id=\"imPgMn\"") !== false) {
  3449.                     $style_start = imstripos($file_content, "<div id=\"imPgMn\"");
  3450.                     $style_end = imstripos($file_content, "</div", $style_start);
  3451.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3452.                     $file_content = str_replace($style, "", $file_content);
  3453.                 }
  3454.  
  3455.                 // Remove the breadcrumbs
  3456.                 while (stristr($file_content, "<div id=\"imBreadcrumb\"") !== false) {
  3457.                     $style_start = imstripos($file_content, "<div id=\"imBreadcrumb\"");
  3458.                     $style_end = imstripos($file_content, "</div", $style_start);
  3459.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3460.                     $file_content = str_replace($style, "", $file_content);
  3461.                 }
  3462.  
  3463.                 // Remove CSS
  3464.                 while (stristr($file_content, "<style") !== false) {
  3465.                     $style_start = imstripos($file_content, "<style");
  3466.                     $style_end = imstripos($file_content, "</style", $style_start);
  3467.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3468.                     $file_content = str_replace($style, "", $file_content);
  3469.                 }
  3470.  
  3471.                 // Remove JS
  3472.                 while (stristr($file_content, "<script") !== false) {
  3473.                     $style_start = imstripos($file_content, "<script");
  3474.                     $style_end = imstripos($file_content, "</script", $style_start);
  3475.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3476.                     $file_content = str_replace($style, "", $file_content);
  3477.                 }
  3478.  
  3479.                 // Remove PHP
  3480.                 while (stristr($file_content, "<?php") !== false) {
  3481.                     $style_start = imstripos($file_content, "<?php");
  3482.                     $style_end = imstripos($file_content, "?>", $style_start) !== false ? imstripos($file_content, "?>", $style_start) + 2 : strlen($file_content);
  3483.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3484.                     $file_content = str_replace($style, "", $file_content);
  3485.                 }
  3486.                 $file_title = "";
  3487.  
  3488.                 // Get the title of the page
  3489.                 preg_match('/\<title\>([^\<]*)\<\/title\>/', $file_content, $matches);
  3490.                 if (count($matches) > 1)
  3491.                     $file_title = $matches[1];
  3492.                 else {
  3493.                     preg_match('/\<h2\>([^\<]*)\<\/h2\>/', $file_content, $matches);
  3494.                     if (count($matches) > 1)
  3495.                         $file_title = $matches[1];
  3496.                 }
  3497.  
  3498.                 if ($file_title != "") {
  3499.                     foreach ($queries as $query) {
  3500.                         $title = imstrtolower($file_title);
  3501.                         while (($title = stristr($title, $query)) !== false) {
  3502.                             $weight += 5;
  3503.                             $count++;
  3504.                             $title = substr($title, strlen($query));
  3505.                         }
  3506.                     }
  3507.                 }
  3508.  
  3509.                 // Get the keywords
  3510.                 preg_match('/\<meta name\=\"keywords\" content\=\"([^\"]*)\" \/>/', $file_content, $matches);
  3511.                 if (count($matches) > 1) {
  3512.                     $keywords = $matches[1];
  3513.                     foreach ($queries as $query) {
  3514.                         $tkeywords = imstrtolower($keywords);
  3515.                         while (($tkeywords = stristr($tkeywords, $query)) !== false) {
  3516.                             $weight += 4;
  3517.                             $count++;
  3518.                             $tkeywords = substr($tkeywords, strlen($query));
  3519.                         }
  3520.                     }
  3521.                 }
  3522.  
  3523.                 // Get the description
  3524.                 preg_match('/\<meta name\=\"description\" content\=\"([^\"]*)\" \/>/', $file_content, $matches);
  3525.                 if (count($matches) > 1) {
  3526.                     $keywords = $matches[1];
  3527.                     foreach ($queries as $query) {
  3528.                         $tkeywords = imstrtolower($keywords);
  3529.                         while (($tkeywords = stristr($tkeywords, $query)) !== false) {
  3530.                             $weight += 3;
  3531.                             $count++;
  3532.                             $tkeywords = substr($tkeywords, strlen($query));
  3533.                         }
  3534.                     }
  3535.                 }
  3536.  
  3537.                 // Remove the page title from the result
  3538.                 while (stristr($file_content, "<h2") !== false) {
  3539.                     $style_start = imstripos($file_content, "<h2");
  3540.                     $style_end = imstripos($file_content, "</h2", $style_start);
  3541.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3542.                     $file_content = str_replace($style, "", $file_content);
  3543.                 }
  3544.  
  3545.                 $page_pos = strpos($file_content, "<div id=\"imContent\">") + strlen("<div id=\"imContent\">");
  3546.                 $page_end = strpos($file_content, "<div id=\"imBtMn\">");
  3547.                 if ($page_end == false)
  3548.                     $page_end = strpos($file_content, "</body>");
  3549.                 $file_content = strip_tags(substr($file_content, $page_pos, $page_end-$page_pos));
  3550.                 $t_file_content = imstrtolower($file_content);
  3551.  
  3552.                 foreach ($queries as $query) {
  3553.                     $file = $t_file_content;
  3554.                     while (($file = stristr($file, $query)) !== false) {
  3555.                         $count++;
  3556.                         $weight++;
  3557.                         $file = substr($file, strlen($query));
  3558.                     }
  3559.                 }
  3560.  
  3561.                 if ($count > 0) {
  3562.                     $found_count[$filename] = $count;
  3563.                     $found_weight[$filename] = $weight;
  3564.                     $found_content[$filename] = $file_content;
  3565.                     if ($file_title == "")
  3566.                         $found_title[$filename] = $filename;
  3567.                     else
  3568.                         $found_title[$filename] = $file_title;
  3569.                 }
  3570.             }
  3571.         }
  3572.  
  3573.         if (count($found_count)) {
  3574.             arsort($found_weight);
  3575.             $i = 0;
  3576.             foreach ($found_weight as $name => $weight) {
  3577.                 $count = $found_count[$name];
  3578.                 $i++;
  3579.                 if (($i > $this->page*$this->results_per_page) && ($i <= ($this->page+1)*$this->results_per_page)) {
  3580.                     $title = strip_tags($found_title[$name]);
  3581.                     $file = $found_content[$name];
  3582.                     $file = strip_tags($file);
  3583.                     $ap = 0;
  3584.                     $filelen = strlen($file);
  3585.                     $text = "";
  3586.                     for ($j=0; $j<($count > 6 ? 6 : $count); $j++) {
  3587.                         $minpos = $filelen;
  3588.                         $word = "";
  3589.                         foreach ($queries as $query) {
  3590.                             if ($ap < $filelen && ($pos = strpos(strtoupper($file), strtoupper($query), $ap)) !== false) {
  3591.                                 if ($pos < $minpos) {
  3592.                                     $minpos = $pos;
  3593.                                     $word = $query;
  3594.                                 }
  3595.                             }
  3596.                         }
  3597.                         $prev = explode(" ", substr($file, $ap, $minpos-$ap));
  3598.                         if (count($prev) > ($ap > 0 ? 9 : 8))
  3599.                             $prev = ($ap > 0 ? implode(" ", array_slice($prev, 0, 8)) : "") . " ... " . implode(" ", array_slice($prev, -8));
  3600.                         else
  3601.                             $prev = implode(" ", $prev);
  3602.                         if (strlen($word)) {
  3603.                             $text .= $prev . "<strong>" . substr($file, $minpos, strlen($word)) . "</strong>";
  3604.                             $ap = $minpos + strlen($word);
  3605.                         }
  3606.                     }
  3607.                     $next = explode(" ", substr($file, $ap));
  3608.                     if (count($next) > 9)
  3609.                         $text .= implode(" ", array_slice($next, 0, 8)) . "...";
  3610.                     else
  3611.                         $text .= implode(" ", $next);
  3612.                     $text = str_replace("|", "", $text);
  3613.                     $text = str_replace("<br />", " ", $text);
  3614.                     $text = str_replace("<br>", " ", $text);
  3615.                     $text = str_replace("\n", " ", $text);
  3616.                     $html .= "<div class=\"imSearchPageResult\"><h3><a class=\"imCssLink\" href=\"" . $name . "\">" . strip_tags($title, "<b><strong>") . "</a></h3>" . strip_tags($text, "<b><strong>") . "<div class=\"imSearchLink\"><a class=\"imCssLink\" href=\"" . $name . "\">" . $imSettings['general']['url'] . "/" . $name . "</a></div></div>\n";
  3617.                 }
  3618.             }
  3619.             $html = preg_replace_callback('/\\s+/', create_function('$matches', 'return implode(\' \', $matches);'), $html);
  3620.             $html .= "<div class=\"imSLabel\"> </div>\n";
  3621.         }
  3622.  
  3623.         return array("content" => $html, "count" => count($found_content));
  3624.     }
  3625.  
  3626.     function searchBlog($queries)
  3627.     {
  3628.         
  3629.         global $imSettings;
  3630.         $html = "";
  3631.         $found_content = array();
  3632.         $found_count = array();
  3633.  
  3634.         if (isset($imSettings['blog']) && is_array($imSettings['blog']['posts'])) {
  3635.             foreach ($imSettings['blog']['posts'] as $key => $value) {
  3636.                 $count = 0;
  3637.                 $weight = 0;
  3638.                 $filename = 'blog/index.php?id=' . $key;
  3639.                 $file_content = $value['body'];
  3640.                 // Rimuovo le briciole dal contenuto
  3641.                 while (stristr($file_content, "<div id=\"imBreadcrumb\"") !== false) {
  3642.                     $style_start = imstripos($file_content, "<div id=\"imBreadcrumb\"");
  3643.                     $style_end = imstripos($file_content, "</div", $style_start);
  3644.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3645.                     $file_content = str_replace($style, "", $file_content);
  3646.                 }
  3647.  
  3648.                 // Rimuovo gli stili dal contenuto
  3649.                 while (stristr($file_content, "<style") !== false) {
  3650.                     $style_start = imstripos($file_content, "<style");
  3651.                     $style_end = imstripos($file_content, "</style", $style_start);
  3652.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3653.                     $file_content = str_replace($style, "", $file_content);
  3654.                 }
  3655.                 // Rimuovo i JS dal contenuto
  3656.                 while (stristr($file_content, "<script") !== false) {
  3657.                     $style_start = imstripos($file_content, "<script");
  3658.                     $style_end = imstripos($file_content, "</script", $style_start);
  3659.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3660.                     $file_content = str_replace($style, "", $file_content);
  3661.                 }
  3662.                 $file_title = "";
  3663.  
  3664.                 // Rimuovo il titolo dal risultato
  3665.                 while (stristr($file_content, "<h2") !== false) {
  3666.                     $style_start = imstripos($file_content, "<h2");
  3667.                     $style_end = imstripos($file_content, "</h2", $style_start);
  3668.                     $style = substr($file_content, $style_start, $style_end - $style_start);
  3669.                     $file_content = str_replace($style, "", $file_content);
  3670.                 }
  3671.  
  3672.                 // Conto il numero di match nel titolo
  3673.                 foreach ($queries as $query) {
  3674.                     $t_count = @preg_match_all('/' . preg_quote($query, '/') . '/', imstrtolower($value['title']), $matches);
  3675.                     if ($t_count !== false) {
  3676.                         $weight += ($t_count * 4);
  3677.                         $count += $t_count;
  3678.                     }
  3679.                 }
  3680.  
  3681.                 // Conto il numero di match nei tag
  3682.                 foreach ($queries as $query) {
  3683.                     if (in_array($query, $value['tag'])) {
  3684.                         $count++;
  3685.                         $weight += 4;
  3686.                     }
  3687.                 }
  3688.  
  3689.                 $title = "Blog >> " . $value['title'];
  3690.  
  3691.                 // Cerco nel contenuto
  3692.                 foreach ($queries as $query) {
  3693.                     $file = imstrtolower($file_content);
  3694.                     while (($file = stristr($file, $query)) !== false) {
  3695.                         $count++;
  3696.                         $weight++;
  3697.                         $file = substr($file, strlen($query));
  3698.                     }
  3699.                 }
  3700.  
  3701.                 if ($count > 0) {
  3702.                     $found_count[$filename] = $count;
  3703.                     $found_weight[$filename] = $weight;
  3704.                     $found_content[$filename] = $file_content;
  3705.                     $found_breadcrumbs[$filename] = "<div class=\"imBreadcrumb\" style=\"display: block; padding-bottom: 3px;\">" . l10n('blog_published_by') . "<strong> " . $value['author'] . " </strong>" . l10n('blog_in') . " <a href=\"blog/index.php?category=" . $value['category'] . "\" target=\"_blank\" rel=\"nofollow\">" . $value['category'] . "</a> · " . $value['timestamp'] . "</div>";
  3706.                     if ($title == "")
  3707.                         $found_title[$filename] = $filename;
  3708.                     else
  3709.                         $found_title[$filename] = $title;
  3710.                 }
  3711.             }
  3712.         }
  3713.  
  3714.         if (count($found_count)) {
  3715.             arsort($found_weight);
  3716.             $i = 0;
  3717.             foreach ($found_weight as $name => $weight) {
  3718.                 $count = $found_count[$name];
  3719.                 $i++;
  3720.                 if (($i > $this->page*$this->results_per_page) && ($i <= ($this->page+1)*$this->results_per_page)) {
  3721.                     $title = strip_tags($found_title[$name]);
  3722.                     $file = $found_content[$name];
  3723.                     $file = strip_tags($file);
  3724.                     $ap = 0;
  3725.                     $filelen = strlen($file);
  3726.                     $text = "";
  3727.                     for ($j=0;$j<($count > 6 ? 6 : $count);$j++) {
  3728.                         $minpos = $filelen;
  3729.                         foreach ($queries as $query) {
  3730.                             if ($ap < $filelen && ($pos = strpos(strtoupper($file), strtoupper($query), $ap)) !== false) {
  3731.                                 if ($pos < $minpos) {
  3732.                                     $minpos = $pos;
  3733.                                     $word = $query;
  3734.                                 }
  3735.                             }
  3736.                         }
  3737.                         $prev = explode(" ", substr($file, $ap, $minpos-$ap));
  3738.                         if(count($prev) > ($ap > 0 ? 9 : 8))
  3739.                             $prev = ($ap > 0 ? implode(" ", array_slice($prev, 0, 8)) : "") . " ... " . implode(" ", array_slice($prev, -8));
  3740.                         else
  3741.                             $prev = implode(" ", $prev);
  3742.                         $text .= $prev . "<strong>" . substr($file, $minpos, strlen($word)) . "</strong> ";
  3743.                         $ap = $minpos + strlen($word);
  3744.                     }
  3745.                     $next = explode(" ", substr($file, $ap));
  3746.                     if(count($next) > 9)
  3747.                         $text .= implode(" ", array_slice($next, 0, 8)) . "...";
  3748.                     else
  3749.                         $text .= implode(" ", $next);
  3750.                     $text = str_replace("|", "", $text);
  3751.                     $html .= "<div class=\"imSearchBlogResult\"><h3><a class=\"imCssLink\" href=\"" . $name . "\">" . strip_tags($title, "<b><strong>") . "</a></h3>" . strip_tags($found_breadcrumbs[$name], "<b><strong>") . "\n" . strip_tags($text, "<b><strong>") . "<div class=\"imSearchLink\"><a class=\"imCssLink\" href=\"" . $name . "\">" . $imSettings['general']['url'] . "/" . $name . "</a></div></div>\n";
  3752.                 }
  3753.             }
  3754.             echo "  <div class=\"imSLabel\"> </div>\n";
  3755.         }
  3756.  
  3757.         $html = preg_replace_callback('/\\s+/', create_function('$matches', 'return implode(\' \', $matches);'), $html);
  3758.         return array("content" => $html, "count" => count($found_content));
  3759.     }
  3760.  
  3761.     // Di questa funzione manca la paginazione!
  3762.     function searchProducts($queries)
  3763.     {
  3764.         
  3765.         global $imSettings;
  3766.         $html = "";
  3767.         $found_products = array();
  3768.         $found_count = array();
  3769.  
  3770.         foreach ($imSettings['search']['products'] as $id => $product) {
  3771.             $count = 0;
  3772.             $weight = 0;
  3773.             $t_title = strip_tags(imstrtolower($product['name']));
  3774.             $t_description = strip_tags(imstrtolower($product['description']));
  3775.  
  3776.             // Conto il numero di match nel titolo
  3777.             foreach ($queries as $query) {
  3778.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', $t_title, $matches);
  3779.                 if ($t_count !== false) {
  3780.                     $weight += ($t_count * 4);
  3781.                     $count += $t_count;
  3782.                 }
  3783.             }
  3784.  
  3785.             // Conto il numero di match nella descrizione
  3786.             foreach ($queries as $query) {
  3787.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', $t_description, $matches);
  3788.                 if ($t_count !== false) {
  3789.                     $weight++;
  3790.                     $count += $t_count;
  3791.                 }
  3792.             }
  3793.  
  3794.             if ($count > 0) {
  3795.                 $found_products[$id] = $product;
  3796.                 $found_weight[$id] = $weight;
  3797.                 $found_count[$id] = $count;
  3798.             }
  3799.         }
  3800.  
  3801.         if (count($found_count)) {
  3802.             arsort($found_weight);
  3803.             $i = 0;
  3804.             foreach ($found_products as $id => $product) {
  3805.                 $i++;
  3806.                 if (($i > $this->page*$this->results_per_page) && ($i <= ($this->page+1)*$this->results_per_page)) {
  3807.                     $count = $found_count[$id];
  3808.                     $html .= "<div class=\"imSearchProductResult\">
  3809.                     <h3 style=\"clear: both;\">" . $product['name'] . "</h3>";
  3810.                     $html .= "<div class=\"imSearchProductDescription\">";
  3811.                     $html .= $product['image'];
  3812.                     $html .= strip_tags($product['description']) . "</div>";
  3813.                     $html .= "<div class=\"imSearchProductPrice\">" . $product['price'];
  3814.                     $html .= " <img src=\"cart/images/cart-add.png\" onclick=\"x5engine.cart.ui.addToCart('" . $id . "', 1);\" style=\"cursor: pointer; vertical-align: middle;\" /></div>";
  3815.                     $html .= "</div>";
  3816.                 }
  3817.             }
  3818.         }
  3819.  
  3820.         return array("content" => $html, "count" => count($found_products));
  3821.     }
  3822.  
  3823.     // Di questa funzione manca la paginazione!
  3824.     function searchImages($queries)
  3825.     {
  3826.         
  3827.         global $imSettings;
  3828.         $id = 0;
  3829.         $html = "";
  3830.         $found_images = array();
  3831.         $found_count = array();
  3832.  
  3833.         foreach ($imSettings['search']['images'] as $image) {
  3834.             $count = 0;
  3835.             $weight = 0;
  3836.             $t_title = strip_tags(imstrtolower($image['title']));
  3837.             $t_description = strip_tags(imstrtolower($image['description']));
  3838.  
  3839.             // Conto il numero di match nel titolo
  3840.             foreach ($queries as $query) {
  3841.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', $t_title, $matches);
  3842.                 if ($t_count !== false) {
  3843.                     $weight += ($t_count * 4);
  3844.                     $count += $t_count;
  3845.                 }
  3846.             }
  3847.  
  3848.             // Conto il numero di match nella location
  3849.             foreach ($queries as $query) {
  3850.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', imstrtolower($image['location']), $matches);
  3851.                 if ($t_count !== false) {
  3852.                     $weight += ($t_count * 2);
  3853.                     $count += $t_count;
  3854.                 }
  3855.             }
  3856.  
  3857.             // Conto il numero di match nella descrizione
  3858.             foreach ($queries as $query) {
  3859.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', $t_description, $matches);
  3860.                 if ($t_count !== false) {
  3861.                     $weight++;
  3862.                     $count += $t_count;
  3863.                 }
  3864.             }
  3865.  
  3866.             if ($count > 0) {
  3867.                 $found_images[$id] = $image;
  3868.                 $found_weight[$id] = $weight;
  3869.                 $found_count[$id] = $count;
  3870.             }
  3871.  
  3872.             $id++;
  3873.         }
  3874.  
  3875.         if (count($found_count)) {
  3876.             arsort($found_weight);
  3877.             $i = 0;
  3878.             foreach ($found_images as $id => $image) {
  3879.                 $i++;
  3880.                 if (($i > $this->page*$this->results_per_page) && ($i <= ($this->page+1)*$this->results_per_page)) {
  3881.                     $count = $found_count[$id];
  3882.                     $html .= "<div class=\"imSearchImageResult\">";
  3883.                     $html .= "<div class=\"imSearchImageResultContent\"><a href=\"" . $image['page'] . "\"><img src=\"" . $image['src'] . "\" /></a></div>";
  3884.                     $html .= "<div class=\"imSearchImageResultContent\">";
  3885.                     $html .= "<h3>" . $image['title'];
  3886.                     if ($image['location'] != "")
  3887.                         $html .= " (" . $image['location'] . ")";
  3888.                     $html .= "</h3>";
  3889.                     $html .= strip_tags($image['description']);
  3890.                     $html .= "</div>";
  3891.                     $html .= "</div>";
  3892.                 }
  3893.             }
  3894.         }
  3895.  
  3896.         return array("content" => $html, "count" => count($found_images));
  3897.     }
  3898.  
  3899.     // Di questa funzione manca la paginazione!
  3900.     function searchVideos($queries)
  3901.     {
  3902.         
  3903.         global $imSettings;
  3904.         $id = 0;
  3905.         $found_count = array();
  3906.         $found_videos = array();
  3907.         $html = "";
  3908.         $month = 7776000;
  3909.  
  3910.         foreach ($imSettings['search']['videos'] as $video) {
  3911.             $count = 0;
  3912.             $weight = 0;
  3913.             $t_title = strip_tags(imstrtolower($video['title']));
  3914.             $t_description = strip_tags(imstrtolower($video['description']));
  3915.  
  3916.             // Conto il numero di match nei tag
  3917.             foreach ($queries as $query) {
  3918.                 $t_count = preg_match_all('/\\s*' . preg_quote($query, '/') . '\\s*/', imstrtolower($video['tags']), $matches);
  3919.                 if ($t_count !== false) {
  3920.                     $weight += ($t_count * 10);
  3921.                     $count += $t_count;
  3922.                 }
  3923.             }
  3924.  
  3925.             // I video pi├╣ recenti hanno maggiore peso in proporzione
  3926.             $time = strtotime($video['date']);
  3927.             $ago = strtotime("-3 months");
  3928.             if ($time - $ago > 0)
  3929.                 $weight += 5 * max(0, ($time - $ago)/$month);
  3930.  
  3931.             // Conto il numero di match nel titolo
  3932.             foreach ($queries as $query) {
  3933.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', $t_title, $matches);
  3934.                 if ($t_count !== false) {
  3935.                     $weight += ($t_count * 4);
  3936.                     $count += $t_count;
  3937.                 }
  3938.             }
  3939.  
  3940.             // Conto il numero di match nella categoria
  3941.             foreach ($queries as $query) {
  3942.                 $t_count = preg_match_all('/' . preg_quote($query, '/') . '/', imstrtolower($video['category']), $matches);
  3943.                 if ($t_count !== false) {
  3944.                     $weight += ($t_count * 2);
  3945.                     $count += $t_count;
  3946.                 }
  3947.             }
  3948.  
  3949.             // Conto il numero di match nella descrizione
  3950.             foreach ($queries as $query) {
  3951.                 $t_count = preg_match_all('/' . preg_quote($query) . '/', $t_description, $matches);
  3952.                 if ($t_count !== false) {
  3953.                     $weight++;
  3954.                     $count += $t_count;
  3955.                 }
  3956.             }
  3957.  
  3958.             if ($count > 0) {
  3959.                 $found_videos[$id] = $video;
  3960.                 $found_weight[$id] = $weight;
  3961.                 $found_count[$id] = $count;
  3962.             }
  3963.  
  3964.             $id++;
  3965.         }
  3966.  
  3967.         if ($found_count) {
  3968.             arsort($found_weight);
  3969.             foreach ($found_videos as $id => $video) {
  3970.                 $i++;
  3971.                 if (($i > $this->page*$this->results_per_page) && ($i <= ($this->page+1)*$this->results_per_page)) {
  3972.                     $count = $found_count[$id];
  3973.                     $html .= "<div class=\"imSearchVideoResult\">";
  3974.                     $html .= "<div class=\"imSearchVideoResultContent\"><a href=\"" . $video['page'] . "\"><img src=\"" . $video['src'] . "\" /></a></div>";
  3975.                     $html .= "<div class=\"imSearchVideoResultContent\">";
  3976.                     $html .= "<h3>" . $video['title'];
  3977.                     if (!$video['familyfriendly'])
  3978.                         $html .= " <span style=\"color: red; text-decoration: none;\">[18+]</span>";
  3979.                     $html .= "</h3>";
  3980.                     $html .= strip_tags($video['description']);
  3981.                     if ($video['duration'] > 0) {
  3982.                         if (function_exists('date_default_timezone_set'))
  3983.                             date_default_timezone_set('UTC');
  3984.                         $html .= "<span class=\"imSearchVideoDuration\">" . l10n('search_duration') . ": " . date("H:i:s", $video['duration']) . "</span>";
  3985.                     }
  3986.                     $html .= "</div>";
  3987.                     $html .= "</div>";
  3988.                 }
  3989.             }
  3990.         }
  3991.  
  3992.         return array("content" => $html, "count" => count($found_videos));
  3993.     }
  3994.  
  3995.     /**
  3996.      * Start the site search
  3997.      * 
  3998.      * @param array  $keys The search keys as string (string)
  3999.      * @param string $page Page to show (integer)
  4000.      *
  4001.      * @return void
  4002.      */
  4003.     function search($keys, $page = 0)
  4004.     {
  4005.         
  4006.         global $imSettings;
  4007.  
  4008.         $html = "";
  4009.         $content = "";
  4010.  
  4011.         //$html .= "<h2 id=\"imPgTitle\" class=\"searchPageTitle\">" . l10n('search_results') . "</h2>\n";
  4012.         $html .= "<div class=\"searchPageContainer\">";
  4013.         $html .= "<div class=\"imPageSearchField\"><form method=\"get\" action=\"imsearch.php\">";
  4014.         $html .= "<input style=\"width: 200px; font: 8pt Tahoma; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255); padding: 3px; border: 1px solid rgb(0, 0, 0); vertical-align: middle;\" class=\"search_field\" value=\"" . htmlentities($keys) . "\" type=\"text\" name=\"search\" />";
  4015.         $html .= "<input style=\"height: 21px; font: 8pt Tahoma; color: rgb(0, 0, 0); background-color: rgb(211, 211, 211); margin-left: 6px; padding: 3px 3px; border: 1px solid rgb(0, 0, 0); vertical-align: middle; cursor: pointer;\" type=\"submit\" value=\"" . l10n('search_search') . "\">";
  4016.         $html .= "</form></div>\n";
  4017.  
  4018.         if ($keys == "" || $keys == null) {
  4019.             $html .= "<div style=\"margin-top: 15px; text-align: center; font-weight: bold;\">" . l10n('search_empty') . "</div>\n";
  4020.             echo $html;
  4021.             return false;
  4022.         }
  4023.  
  4024.         $search = trim(imstrtolower($keys));
  4025.         $this->page = $page;
  4026.  
  4027.         if ($search != "") {
  4028.             $queries = explode(" ", $search);
  4029.             $blog = array("count" => 0);
  4030.             $products = array("count" => 0);
  4031.             $images = array("count" => 0);
  4032.             $videos = array("count" => 0);
  4033.  
  4034.             // Pages
  4035.             $pages = $this->searchPages($queries);
  4036.             if ($pages['count'] > 0) {
  4037.                 $content .= "<div id=\"imSearchWebPages\">" . $pages['content'] . "</div>\n";
  4038.             }
  4039.  
  4040.             // Blog
  4041.             if (isset($imSettings['blog']) && is_array($imSettings['blog']['posts']) && count($imSettings['blog']['posts']) > 0) {
  4042.                 $blog = $this->searchBlog($queries);
  4043.                 if ($blog['count'] > 0) {
  4044.                     $content .= "<div id=\"imSearchBlog\">" . $blog['content'] . "</div>\n";
  4045.                 }
  4046.             }
  4047.  
  4048.             // Products
  4049.             if (is_array($imSettings['search']['products']) && count($imSettings['search']['products']) > 0) {
  4050.                 $products = $this->searchProducts($queries);
  4051.                 if ($products['count'] > 0) {
  4052.                     $content .= "<div id=\"imSearchProducts\">" . $products['content'] . "</div>\n";
  4053.                 }
  4054.             }
  4055.  
  4056.             // Images
  4057.             if (is_array($imSettings['search']['images']) && count($imSettings['search']['images']) > 0) {
  4058.                 $images = $this->searchImages($queries);
  4059.                 if ($images['count'] > 0) {
  4060.                     $content .= "<div id=\"imSearchImages\">" . $images['content'] . "</div>\n";
  4061.                 }
  4062.             }
  4063.  
  4064.             // Videos
  4065.             if (is_array($imSettings['search']['videos']) && count($imSettings['search']['videos']) > 0) {
  4066.                 $videos = $this->searchVideos($queries);
  4067.                 if ($videos['count'] > 0) {
  4068.                     $content .= "<div id=\"imSearchVideos\">" . $videos['content'] . "</div>\n";
  4069.                 }
  4070.             }
  4071.  
  4072.             $results_count = max($pages['count'], $blog['count'], $products['count'], $images['count'], $videos['count']);
  4073.  
  4074.             if ($pages['count'] == 0 && $blog['count'] == 0 && $products['count'] == 0 && $images['count'] == 0 && $videos['count'] == 0) {
  4075.                 $html .= "<div style=\"text-align: center; font-weight: bold;\">" . l10n('search_empty') . "</div>\n";
  4076.             } else {
  4077.                 $sidebar = "<ul>\n";
  4078.                 if ($pages['count'] > 0)
  4079.                     $sidebar .= "\t<li><span class=\"imScMnTxt\"><a href=\"#imSearchWebPages\" onclick=\"return x5engine.imSearch.Show('#imSearchWebPages')\">" . l10n('search_pages') . " (" . $pages['count'] . ")</a></span></li>\n";
  4080.                 if ($blog['count'] > 0)
  4081.                     $sidebar .= "\t<li><span class=\"imScMnTxt\"><a href=\"#imSearchBlog\" onclick=\"return x5engine.imSearch.Show('#imSearchBlog')\">" . l10n('search_blog') . " (" . $blog['count'] . ")</a></span></li>\n";
  4082.                 if ($products['count'] > 0)
  4083.                     $sidebar .= "\t<li><span class=\"imScMnTxt\"><a href=\"#imSearchProducts\" onclick=\"return x5engine.imSearch.Show('#imSearchProducts')\">" . l10n('search_products') . " (" . $products['count'] . ")</a></span></li>\n";
  4084.                 if ($images['count'] > 0)
  4085.                     $sidebar .= "\t<li><span class=\"imScMnTxt\"><a href=\"#imSearchImages\" onclick=\"return x5engine.imSearch.Show('#imSearchImages')\">" . l10n('search_images') . " (" . $images['count'] . ")</a></span></li>\n";
  4086.                 if ($videos['count'] > 0)
  4087.                     $sidebar .= "\t<li><span class=\"imScMnTxt\"><a href=\"#imSearchVideos\" onclick=\"return x5engine.imSearch.Show('#imSearchVideos')\">" . l10n('search_videos') . " (" . $videos['count'] . ")</a></span></li>\n";
  4088.                 $sidebar .= "</ul>\n";
  4089.  
  4090.                 $html .= "<div id=\"imSearchResults\">\n";
  4091.                 if ($imSettings['search']['general']['menu_position'] == "left") {
  4092.                     $html .= "\t<div id=\"imSearchSideBar\" style=\"float: left;\">" . $sidebar . "</div>\n";
  4093.                     $html .= "\t<div id=\"imSearchContent\" style=\"float: right;\">" . $content . "</div>\n";
  4094.                 } else {
  4095.                     $html .= "\t<div id=\"imSearchContent\" style=\"float: left;\">" . $content . "</div>\n";
  4096.                     $html .= "\t<div id=\"imSearchSideBar\" style=\"float: right;\">" . $sidebar . "</div>\n";
  4097.                 }
  4098.                 $html .= "</div>\n";
  4099.             }
  4100.  
  4101.             // Pagination
  4102.             if ($results_count > $this->results_per_page) {
  4103.                 $html .= "<div style=\"text-align: center; clear: both;\">";
  4104.                 // Back
  4105.                 if ($page > 0) {
  4106.                     $html .= "<a href=\"imsearch.php?search=" . implode("+", $queries) . "&page=" . ($page - 1) . "\"><<</a> ";
  4107.                 }
  4108.  
  4109.                 // Central pages
  4110.                 $start = max($page - 5, 0);
  4111.                 $end = min($page + 10 - $start, ceil($results_count/$this->results_per_page));
  4112.  
  4113.                 for ($i = $start; $i < $end; $i++) {
  4114.                     if ($i != $this->page)
  4115.                         $html .= "<a href=\"imsearch.php?search=" . implode("+", $queries) . "&page=" . $i . "\">" . ($i + 1) . "</a> ";
  4116.                     else
  4117.                         $html .= ($i + 1) . " ";
  4118.                 }
  4119.  
  4120.                 // Next
  4121.                 if ($results_count > ($page + 1) * $this->results_per_page) {
  4122.                     $html .= "<a href=\"imsearch.php?search=" . implode("+", $queries) . "&page=" . ($page + 1) . "\">>></a>";
  4123.                 }
  4124.                 $html .= "</div>";
  4125.             }
  4126.  
  4127.         } else
  4128.             $html .= "<div style=\"margin-top: 15px; text-align: center; font-weight: bold;\">" . l10n('search_empty') . "</div>\n";
  4129.  
  4130.         $html .= "</div>";
  4131.  
  4132.         echo $html;
  4133.     }
  4134. }
  4135.  
  4136.  
  4137. /**
  4138.  * Contains the methods used to style and send emails
  4139.  * @access public
  4140.  */
  4141. class ImSendEmail
  4142. {
  4143.  
  4144.     var $header;
  4145.     var $footer;
  4146.     var $bodyBackground;
  4147.     var $bodyBackgroundEven;
  4148.     var $bodyBackgroundOdd;
  4149.     var $bodyBackgroundBorder;
  4150.     var $bodySeparatorBorderColor;
  4151.     var $emailBackground;
  4152.     var $emailContentStyle;
  4153.     var $emailType = "html";
  4154.     var $exposeWsx5 = true;
  4155.  
  4156.     function setExpose($expose)
  4157.     {
  4158.         $this->exposeWsx5 = $expose;
  4159.     }
  4160.  
  4161.     function setHTMLHeader($header)
  4162.     {
  4163.         $this->header = $header;
  4164.     }
  4165.  
  4166.     function setHTMLFooter($footer)
  4167.     {
  4168.         $this->footer = $footer;
  4169.     }
  4170.  
  4171.     function setBodyBackground($val)
  4172.     {
  4173.         $this->bodyBackground = $val;
  4174.     }
  4175.  
  4176.     function setBodyBackgroundEven($val)
  4177.     {
  4178.         $this->bodyBackgroundEven = $val;
  4179.     }
  4180.  
  4181.     function setBodyBackgroundOdd($val)
  4182.     {
  4183.         $this->bodyBackgroundOdd = $val;
  4184.     }
  4185.  
  4186.     function setBodyBackgroundBorder($val)
  4187.     {
  4188.         $this->bodyBackgroundBorder = $val;
  4189.     }
  4190.  
  4191.     function setEmailBackground($val)
  4192.     {
  4193.         $this->emailBackground = $val;
  4194.     }
  4195.  
  4196.     function setEmailContentStyle($val)
  4197.     {
  4198.         $this->emailContentStyle = $val;
  4199.     }
  4200.  
  4201.     function setBodySeparatorBorderColor($val)
  4202.     {
  4203.         $this->bodySeparatorBorderColor = $val;
  4204.     }
  4205.  
  4206.     function setEmailType($type) {
  4207.         $this->emailType = $type;
  4208.     }
  4209.  
  4210.     /**
  4211.      * Apply the CSS style to the HTML code
  4212.      * @param  string $html The HTML code
  4213.      * @return string       The styled HTML code
  4214.      */
  4215.     function styleHTML($html)
  4216.     {
  4217.         $html = str_replace("[email:contentStyle]", $this->emailContentStyle, $html);
  4218.         $html = str_replace("[email:bodyBackground]", $this->bodyBackground, $html);
  4219.         $html = str_replace("[email:bodyBackgroundBorder]", $this->bodyBackgroundBorder, $html);
  4220.         $html = str_replace("[email:bodyBackgroundOdd]", $this->bodyBackgroundOdd, $html);
  4221.         $html = str_replace("[email:bodyBackgroundEven]", $this->bodyBackgroundEven, $html);
  4222.         $html = str_replace("[email:bodySeparatorBorderColor]", $this->bodySeparatorBorderColor, $html);
  4223.         $html = str_replace("[email:emailBackground]", $this->emailBackground, $html);
  4224.         return $html;
  4225.     }
  4226.  
  4227.     /**
  4228.      * Send an email
  4229.      * 
  4230.      * @param string $from        Self explanatory
  4231.      * @param string $to          Self explanatory
  4232.      * @param string $subject     Self explanatory
  4233.      * @param string $text        Self explanatory
  4234.      * @param string $html        Self explanatory
  4235.      * @param array  $attachments Self explanatory
  4236.      * 
  4237.      * @return boolean
  4238.      */
  4239.     function send($from = "", $to = "", $subject = "", $text = "", $html = "", $attachments = array())
  4240.     {
  4241.         $email = new imEMail($from, $to, $subject, "utf-8");
  4242.         $email->setExpose($this->exposeWsx5);
  4243.         $email->setText($text);
  4244.         $email->setHTML($this->header . $this->styleHTML($html) . $this->footer);
  4245.         $email->setStandardType($this->emailType);
  4246.         foreach ($attachments as $a) {
  4247.             if (isset($a['name']) && isset($a['content']) && isset($a['mime'])) {
  4248.                 $email->attachFile($a['name'], $a['content'], $a['mime']);
  4249.             }
  4250.         }
  4251.         return $email->send();
  4252.     }
  4253.  
  4254.     /**
  4255.      * Restore some special chars escaped previously in WSX5
  4256.      * 
  4257.      * @param string $str The string to be restored
  4258.      *
  4259.      * @return string
  4260.      */
  4261.     function restoreSpecialChars($str)
  4262.     {
  4263.         $str = str_replace("{1}", "'", $str);
  4264.         $str = str_replace("{2}", "\"", $str);
  4265.         $str = str_replace("{3}", "\\", $str);
  4266.         $str = str_replace("{4}", "<", $str);
  4267.         $str = str_replace("{5}", ">", $str);
  4268.         return $str;
  4269.     }
  4270.  
  4271.     /**
  4272.      * Decode the Unicode escaped chars like %u1239
  4273.      * 
  4274.      * @param string $str The string to be decoded
  4275.      *
  4276.      * @return string
  4277.      */
  4278.     function decodeUnicodeString($str)
  4279.     {
  4280.         $res = '';
  4281.  
  4282.         $i = 0;
  4283.         $max = strlen($str) - 6;
  4284.         while ($i <= $max) {
  4285.             $character = $str[$i];
  4286.             if ($character == '%' && $str[$i + 1] == 'u') {
  4287.                 $value = hexdec(substr($str, $i + 2, 4));
  4288.                 $i += 6;
  4289.  
  4290.                 if ($value < 0x0080) // 1 byte: 0xxxxxxx
  4291.                     $character = chr($value);
  4292.                 else if ($value < 0x0800) // 2 bytes: 110xxxxx 10xxxxxx
  4293.                     $character = chr((($value & 0x07c0) >> 6) | 0xc0) . chr(($value & 0x3f) | 0x80);
  4294.                 else // 3 bytes: 1110xxxx 10xxxxxx 10xxxxxx
  4295.                 $character = chr((($value & 0xf000) >> 12) | 0xe0) . chr((($value & 0x0fc0) >> 6) | 0x80) . chr(($value & 0x3f) | 0x80);
  4296.             } else
  4297.                 $i++;
  4298.  
  4299.             $res .= $character;
  4300.         }
  4301.         return $res . substr($str, $i);
  4302.     }
  4303. }
  4304.  
  4305. /**
  4306.  * Server Test Class
  4307.  * @access public
  4308.  */
  4309. class imTest {
  4310.  
  4311.     /*
  4312.      * Session check
  4313.      */
  4314.     function session_test()
  4315.     {
  4316.         
  4317.         if (!isset($_SESSION))
  4318.             return false;
  4319.         $_SESSION['imAdmin_test'] = "test_message";
  4320.         return ($_SESSION['imAdmin_test'] == "test_message");
  4321.     }
  4322.  
  4323.     /*
  4324.      * Writable files check
  4325.      */
  4326.     function writable_folder_test($dir)
  4327.     {
  4328.         if (!file_exists($dir) && $dir != "" && $dir != "./.")
  4329.             @mkdir($dir, 0777, true);
  4330.  
  4331.         $fp = @fopen(pathCombine(array($dir, "imAdmin_test_file")), "w");
  4332.         if (!$fp)
  4333.             return false;
  4334.         if (@fwrite($fp, "test") === false)
  4335.             return false;
  4336.         @fclose($fp);
  4337.         if (!@file_exists(pathCombine(array($dir, "imAdmin_test_file"))))
  4338.             return false;
  4339.         @unlink(pathCombine(array($dir, "imAdmin_test_file")));
  4340.         return true;
  4341.     }
  4342.  
  4343.     /*
  4344.      * PHP Version check
  4345.      */
  4346.     function php_version_test()
  4347.     {   
  4348.         if (!function_exists("version_compare") || version_compare(PHP_VERSION, '4.0.0') < 0)
  4349.             return false;
  4350.         return true;
  4351.     }
  4352.  
  4353.     /*
  4354.      * MySQL Connection check
  4355.      */
  4356.     function mysql_test($host, $user, $pwd, $name)
  4357.     {
  4358.         $db = new ImDb($host, $user, $pwd, $name);
  4359.         if (!$db->testConnection())
  4360.             return false;
  4361.         $db->closeConnection();
  4362.         return true;
  4363.     }
  4364.  
  4365.     /*
  4366.      * Do the test
  4367.      */
  4368.     function doTest($expected, $value, $title, $message)
  4369.     {
  4370.         if ($expected == $value)
  4371.             echo "<div class=\"imTest pass\">" . $title . "<span>PASS</span></div>";
  4372.         else
  4373.             echo "<div class=\"imTest fail\">" . $title . "<span>FAIL</span><p>" . $message . "</p></div>";
  4374.     }
  4375. }
  4376.  
  4377.  
  4378.  
  4379. /**
  4380.  * This file stores the class used to show a topic
  4381.  *
  4382.  * @category X5engine
  4383.  * @package  X5engine
  4384.  * @license  Copyright by Incomedia http://incomedia.eu
  4385.  * @link     http://websitex5.com
  4386.  */
  4387. class ImTopic
  4388. {
  4389.  
  4390.     var $id;
  4391.     var $comments    = null;
  4392.     var $table       = "";
  4393.     var $folder      = "";
  4394.     var $host        = "";
  4395.     var $user        = "";
  4396.     var $pwd         = "";
  4397.     var $database    = "";
  4398.     var $ratingImage = "";
  4399.     var $storageType = "xml";
  4400.     var $basepath    = "";
  4401.     var $posturl     = "";
  4402.     var $title       = "";
  4403.  
  4404.     /**
  4405.      * Constructor for PHP5
  4406.      * 
  4407.      * @param string $id       The topic id
  4408.      * @param string $basepath The base path
  4409.      * @param string $postUrl  The URL to post to
  4410.      *
  4411.      * @return void
  4412.      */
  4413.     function __construct($id, $basepath = "", $postUrl = "")
  4414.     {
  4415.         $this->setUp($id, $basepath, $postUrl);
  4416.     }
  4417.  
  4418.     /**
  4419.      * Constructor for PHP4
  4420.      * 
  4421.      * @param string $id       The topic id
  4422.      * @param string $basepath The base path
  4423.      * @param string $postUrl  The URL to post to
  4424.      *
  4425.      * @return void
  4426.      */
  4427.     function ImTopic($id, $basepath = "", $postUrl = "")
  4428.     {
  4429.         $this->setUp($id, $basepath, $postUrl);
  4430.     }
  4431.  
  4432.     /**
  4433.      * Do the constructor actions
  4434.      * 
  4435.      * @param string $id       The topic is
  4436.      * @param string $basepath The basepath of the page which loads the topic
  4437.      * @param string $postUrl  The URL to post to
  4438.      *
  4439.      * @return void
  4440.      */
  4441.     function setUp($id, $basepath = "", $postUrl = "")
  4442.     {
  4443.         $this->id = $id;
  4444.         if (strlen($postUrl)) {
  4445.             $this->posturl = trim($postUrl, "?&");
  4446.             $this->posturl .=(strpos($this->posturl, "?") === false ? "?" : "&");
  4447.         } else {
  4448.             $this->posturl = basename($_SERVER['PHP_SELF']) . "?";
  4449.         }
  4450.         $this->basepath = $this->prepFolder($basepath);
  4451.         // Create the comments array
  4452.         $this->comments = new ImComment();
  4453.     }
  4454.  
  4455.     /**
  4456.      * Set the path to wich the data is posted to
  4457.      * 
  4458.      * @param string $posturl The url to post to
  4459.      *
  4460.      * @return void
  4461.      */
  4462.     function setPostUrl($posturl)
  4463.     {
  4464.         $this->posturl = $posturl . (strpos($posturl, "?") === 0 ? "?" : "&");
  4465.     }
  4466.  
  4467.     /**
  4468.      * Set the title of this topic
  4469.      * 
  4470.      * @param string $title
  4471.      *
  4472.      * @return  void
  4473.      */
  4474.     function setTitle($title)
  4475.     {
  4476.         $this->title = $title;
  4477.     }
  4478.  
  4479.     /**
  4480.      * Return the encrypted filename of a string
  4481.      * @param  string $str
  4482.      * @return string
  4483.      */
  4484.     function encFileName($str)
  4485.     {
  4486.         return substr(md5($str), 0, 8) . substr($str, -4);
  4487.     }
  4488.  
  4489.     /**
  4490.      * Load the data from the xml file
  4491.      * 
  4492.      * @param string $folder The file's folder
  4493.      * 
  4494.      * @return void
  4495.      */
  4496.     function loadXML($folder = "")
  4497.     {
  4498.         if ($this->comments == null)
  4499.             return;
  4500.  
  4501.         $this->folder = $this->prepFolder($folder);
  4502.         $encName = $this->encFileName($this->id);
  4503.         // Check if the encrypted filename exists
  4504.         if (file_exists($this->basepath . $this->folder . $encName))
  4505.             $this->comments->loadFromXML($this->basepath . $this->folder . $encName);
  4506.         // If the encrypted filename doesn't exist, try the normal filename
  4507.         else
  4508.             $this->comments->loadFromXML($this->basepath . $this->folder . $this->id);
  4509.         $this->storageType = "xml";
  4510.     }
  4511.  
  4512.     /**
  4513.      * Save to xml
  4514.      * 
  4515.      * @param string $folder The folder where is saved the file
  4516.      * 
  4517.      * @return boolean
  4518.      */
  4519.     function saveXML($folder = "")
  4520.     {
  4521.         if ($this->comments == null)
  4522.             return;
  4523.  
  4524.         $encName = $this->encFileName($this->id);
  4525.         $folder = $folder != "" ? $this->prepFolder($folder) : $this->folder;
  4526.         if ($this->comments->saveToXML($this->basepath . $folder . $encName)) {
  4527.             // If the comments can be saved, check if the non-encrypted file exists. If so, delete it.
  4528.             if (file_exists($this->basepath . $this->folder . $this->id))
  4529.                 unlink($this->basepath . $this->folder . $this->id);
  4530.             return true;
  4531.         }
  4532.         return false;
  4533.     }
  4534.  
  4535.     /**
  4536.      * Setup the folder
  4537.      * 
  4538.      * @param string $folder The folder path to prepare
  4539.      * 
  4540.      * @return string
  4541.      */
  4542.     function prepFolder($folder)
  4543.     {
  4544.         if (strlen(trim($folder)) == 0)
  4545.             return "./";
  4546.  
  4547.         if (substr($folder, 0, -1) != "/")
  4548.             $folder .= "/";
  4549.  
  4550.         return $folder;
  4551.     }
  4552.  
  4553.  
  4554.     /**
  4555.      * Load the data from the database
  4556.      * 
  4557.      * @param string $host  The dbname
  4558.      * @param string $user  The db user name
  4559.      * @param string $pwd   The db user password
  4560.      * @param string $db    The db name
  4561.      * @param string $table The db table
  4562.      * 
  4563.      * @return void
  4564.      */
  4565.     function loadDb($host, $user, $pwd, $db, $table)
  4566.     {
  4567.         if ($this->comments == null)
  4568.             return;
  4569.  
  4570.         $this->host  = $host;
  4571.         $this->user  = $user;
  4572.         $this->pwd   = $pwd;
  4573.         $this->db    = $db;
  4574.         $this->table = $table;
  4575.         $this->storageType = "database";
  4576.  
  4577.         $this->comments->loadFromDb($this->host, $this->user, $this->pwd, $this->db, $this->table, $this->id);
  4578.     }
  4579.  
  4580.     /**
  4581.      * Save the comments to a database
  4582.      * 
  4583.      * @param string $host  The dbname
  4584.      * @param string $user  The db user name
  4585.      * @param string $pwd   The db user password
  4586.      * @param string $db    The db name
  4587.      * @param string $table The db table
  4588.      * 
  4589.      * @return boolean
  4590.      */
  4591.     function saveDb($host = "", $user = "", $pwd = "", $db = "", $table = "")
  4592.     {
  4593.         if ($this->comments == null)
  4594.             return false;
  4595.  
  4596.         $host  = $host != "" ? $host : $this->host;
  4597.         $user  = $user != "" ? $user : $this->user;
  4598.         $pwd   = $pwd != "" ? $pwd : $this->pwd;
  4599.         $db    = $db != "" ? $db : $this->db;
  4600.         $table = $table != "" ? $table : $this->table;
  4601.         return $this->comments->saveToDb($host, $user, $pwd, $db, $table, $this->id);
  4602.     }
  4603.  
  4604.  
  4605.     /**
  4606.      * Checks the $_POST array for new messages
  4607.      * 
  4608.      * @param boolean $moderate    TRUE to show only approved comments
  4609.      * @param string  $email       The email to notify the new comment
  4610.      * @param string  $type        The topic type (guestbook|blog)
  4611.      * @param string  $moderateurl The url where the user can moderate the comments
  4612.      * 
  4613.      * @return booelan
  4614.      */
  4615.     function checkNewMessages($moderate = true, $email = "", $type = "guestbook", $moderateurl = "")
  4616.     {
  4617.         global $ImMailer;
  4618.         global $imSettings;
  4619.  
  4620.         /*
  4621.         |-------------------------------------------
  4622.         |    Check for new messages
  4623.         |-------------------------------------------
  4624.          */
  4625.  
  4626.         if (!isset($_POST['x5topicid']) || $_POST['x5topicid'] != $this->id)
  4627.             return false;
  4628.         if (!checkJsAndSpam())
  4629.             return false;
  4630.  
  4631.         $comment = array(
  4632.             "email"     => $_POST['email'],
  4633.             "name"      => $_POST['name'],
  4634.             "url"       => $_POST['url'],
  4635.             "body"      => $_POST['body'],
  4636.             "ip"        => $_SERVER['REMOTE_ADDR'],
  4637.             "timestamp" => date("Y-m-d H:i:s"),
  4638.             "abuse"     => "0",
  4639.             "approved"  => $moderate ? "0" : "1"
  4640.         );
  4641.         if (isset($_POST['rating']))
  4642.             $comment['rating'] = $_POST['rating'];
  4643.         $this->comments->add($comment);
  4644.         $saved = ($this->storageType == "xml" ? $this->saveXML() : $this->saveDb());
  4645.         if (!$saved) {
  4646.             echo "<script type=\"text/javascript\">window.top.location.href='" . $this->posturl . $this->id . "error';</script>";
  4647.             return false;
  4648.         }
  4649.         // Send the notification email
  4650.         if ($email != "") {
  4651.             if ($type == "guestbook")
  4652.                 $html = str_replace(array("Blog", "blog"), array("Guestbook", "guestbook"), l10n('blog_new_comment_text')) . " \"" . $this->title . "\":<br /><br />\n\n";
  4653.             else
  4654.                 $html = l10n('blog_new_comment_text') . ":<br /><br />\n\n";
  4655.             $html .= "<b>" . l10n('blog_name') . "</b> " . stripslashes($_POST['name']) . "<br />\n";
  4656.             $html .= "<b>" . l10n('blog_email') . "</b> " . $_POST['email'] . "<br />\n";
  4657.             $html .= "<b>" . l10n('blog_website') . "</b> " . $_POST['url'] . "<br />\n";
  4658.             if (isset($_POST['rating']))
  4659.                 $html .= "<b>" . l10n('blog_rating', "Vote:") . "</b> " . $_POST['rating'] . "/5<br />\n";
  4660.             $html .= "<b>" . l10n('blog_message') . "</b> " . stripslashes($_POST['body']) . "<br /><br />\n\n";
  4661.             // Set the proper link
  4662.             if ($moderateurl != "") {
  4663.                 $html .= ($moderate ? l10n('blog_unapprove_link') : l10n('blog_approve_link')) . ":<br />\n";
  4664.                 $html .= "<a href=\"" . $moderateurl . "\">" . $moderateurl . "</a>";
  4665.             }
  4666.             if ($type == "guestbook")
  4667.                 $subject = str_replace(array("Blog", "blog"), array("Guestbook", "guestbook"), l10n('blog_new_comment_object'));
  4668.             else
  4669.                 $subject = l10n('blog_new_comment_object');
  4670.             $ImMailer->send(strlen($comment['email']) ? $comment['email'] : $email, $email, $subject, strip_tags($html), $html);
  4671.         }
  4672.  
  4673.         // Redirect
  4674.         echo "<script type=\"text/javascript\">window.top.location.href='" . $this->posturl . ($moderate ? $this->id . "success" : "") . "';</script>";
  4675.         return true;
  4676.     }
  4677.  
  4678.     /**
  4679.      * Check for new abuses
  4680.      * 
  4681.      * @return void
  4682.      */
  4683.     function checkNewAbuses()
  4684.     {
  4685.         if (isset($_GET['x5topicid']) && $_GET['x5topicid'] == $this->id) {
  4686.             if (isset($_GET['abuse'])) {
  4687.                 $n = (int)$_GET['abuse'];
  4688.                 $c = $this->comments->get($n);
  4689.                 $c['abuse'] = "1";
  4690.                 $this->comments->edit($n, $c);
  4691.                 $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4692.                 echo "<script type=\"text/javascript\">window.top.location.href='" . $this->posturl . "';</script>";
  4693.             }
  4694.         }
  4695.     }
  4696.  
  4697.     /**
  4698.      * Show the comments form
  4699.      * 
  4700.      * @param boolean $rating      true to show the rating
  4701.      * @param boolean $captcha     true to enable captcha
  4702.      * @param boolean $moderate    true to enable the moderation
  4703.      * @param string  $email       the email address to notificate
  4704.      * @param string  $type        guestbook or blog
  4705.      * @param string  $moderateurl The url at wich is possible to moderate the new comments
  4706.      * 
  4707.      * @return void
  4708.      */
  4709.     function showForm($rating = true, $captcha = true, $moderate = true, $email = "", $type = "guestbook", $moderateurl = "")
  4710.     {
  4711.         global $imSettings;
  4712.         $id = $this->id . "-topic-form";
  4713.  
  4714.         $this->checkNewMessages($moderate, $email, $type, $moderateurl);
  4715.         $this->checkNewAbuses();
  4716.  
  4717.         /*
  4718.         |-------------------------------------------
  4719.         |    Show the form
  4720.         |-------------------------------------------
  4721.          */
  4722.         
  4723.         if (isset($_GET[$this->id . 'success'])) {
  4724.             echo "<div class=\"alert alert-green\">" . l10n('blog_send_confirmation') . "</div>";
  4725.         } else if (isset($_GET[$this->id . 'error'])) {
  4726.             echo "<div class=\"alert alert-red\">" . l10n('blog_send_error') . "</div>";
  4727.         }
  4728.  
  4729.         echo "<div class=\"topic-form\">
  4730.               <form id=\"" . $id ."\" action=\"" . $this->posturl . "\" method=\"post\" onsubmit=\"return x5engine.imForm.validate(this, {type: 'tip', showAll: true})\">
  4731.                 <input type=\"hidden\" name=\"post_id\" value=\"" . $this->id . "\"/>
  4732.                 <div class=\"topic-form-row\">
  4733.                     <label for=\"" . $id . "-name\" style=\"float: left; width: 100px;\">" . l10n('blog_name') . "*</label> <input type=\"text\" id=\"" . $id . "-name\" name=\"name\" class=\"imfield mandatory\" />
  4734.                 </div>
  4735.                 <div class=\"topic-form-row\">
  4736.                     <label for=\"" . $id . "-email\" style=\"float: left; width: 100px;\">" . l10n('blog_email') . "*</label> <input type=\"text\" id=\"" . $id . "-email\" name=\"email\" class=\"imfield mandatory valEmail\"/>
  4737.                 </div>
  4738.                 <div class=\"topic-form-row\">
  4739.                     <label for=\"" . $id . "-url\" style=\"float: left; width: 100px;\">" . l10n('blog_website') . "</label> <input type=\"text\" id=\"" . $id . "-url\" name=\"url\" />
  4740.                 </div>";
  4741.         if ($rating) {
  4742.             echo "<div class=\"topic-form-row\">
  4743.                 <label style=\"float: left; width: 100px;vertical-align: middle;\">" . l10n('blog_rating', "Vote") . "</label>
  4744.                 <span class=\"topic-star-container-big variable-star-rating\">
  4745.                     <span class=\"topic-star-fixer-big\" style=\"width: 0;\"></span>
  4746.                 </span>
  4747.                 </div>";
  4748.         }
  4749.                 echo "<div class=\"topic-form-row\">
  4750.                     <br /><label for=\"" . $id . "-body\" style=\"clear: both; width: 100px;\">" . l10n('blog_message') . "*</label><textarea id=\"" . $id . "-body\" name=\"body\" class=\"imfield mandatory\" style=\"width: 95%; height: 100px;\"></textarea>
  4751.                 </div>";
  4752.         if ($captcha) {
  4753.             echo "<div class=\"topic-form-row\" style=\"text-align: center\">
  4754.                     <label for=\"" . $id . "_imCpt\" style=\"float: left;\">" . l10n('form_captcha_title') . "</label> <input type=\"text\" id=\"" . $id . "_imCpt\" name=\"imCpt\" maxlength=\"5\" class=\"imfield imCpt[5" . ($type == "blog" ? ", ../" : "") . "]\" size=\"5\" style=\"width: 120px; margin: 0 auto;\" />
  4755.                 </div>";
  4756.         }
  4757.         echo "<input type=\"hidden\" value=\"" . $this->id . "\" name=\"x5topicid\">";
  4758.         echo "<input type=\"text\" value=\"\" name=\"prt\" class=\"prt_field\">";
  4759.         echo "<div class=\"topic-form-row\" style=\"text-align: center\">
  4760.                     <input type=\"submit\" value=\"" . l10n('blog_send') . "\" />
  4761.                     <input type=\"reset\" value=\"" . l10n('form_reset') . "\" />
  4762.                 </div>
  4763.                 </form>
  4764.                 <script type=\"text/javascript\">x5engine.boot.push( function () { x5engine.imForm.initForm('#" . $id . "', false, { showAll: true }); });</script>
  4765.             </div>\n";
  4766.     }
  4767.  
  4768.     /**
  4769.      * Show the topic summary
  4770.      * 
  4771.      * @param boolean $rating      TRUE to show the ratings
  4772.      * @param boolean $admin       TRUE to show approved and unapproved comments
  4773.      * @param boolean $hideifempty true to hide the summary if there are no comments
  4774.      * 
  4775.      * @return void
  4776.      */
  4777.     function showSummary($rating = true, $admin = false, $hideifempty = true)
  4778.     {
  4779.         $c = $this->comments->getAll();
  4780.         $comments = array();
  4781.         $votes = 0;
  4782.         $votescount = 0;
  4783.         foreach ($c as $comment) {
  4784.             if ($comment['approved'] == "1" || $admin) {
  4785.                 if (isset($comment['body'])) {
  4786.                     $comments[] = $comment;
  4787.                 }
  4788.                 if (isset($comment['rating'])) {
  4789.                     $votes += $comment['rating'];
  4790.                     $votescount++;
  4791.                 }
  4792.             }
  4793.         }
  4794.         $count = count($comments);
  4795.         $vote = $votescount > 0 ? $votes/$votescount : 0;
  4796.  
  4797.         if ($count == 0 && $hideifempty)
  4798.             return;
  4799.  
  4800.         echo "<div class=\"topic-summary\">\n";
  4801.         echo "<div>" . ($count > 0 ? $count . " " . ($count > 1 ? l10n('blog_comments') : l10n('blog_comment')) : l10n('blog_no_comment')) . "</div>";
  4802.         if ($rating) {
  4803.             echo "<div style=\"margin-bottom: 5px;\">" . l10n("blog_average_rating", "Average Vote") . ": " . number_format($vote, 1) . "/5</div>";
  4804.             echo "<span class=\"topic-star-container-big\" title=\"" . number_format($vote, 1) . "/5\">
  4805.                     <span class=\"topic-star-fixer-big\" style=\"width: " . round($vote/5 * 100) . "%;\"></span>
  4806.             </span>\n";
  4807.         }
  4808.         echo "</div>\n";
  4809.     }
  4810.  
  4811.     /**
  4812.      * Show the comments list
  4813.      * 
  4814.      * @param boolean $rating      true to show the ratings
  4815.      * @param string  $order       desc or asc
  4816.      * @param boolean $showabuse   true to show the "Abuse" button
  4817.      * @param boolean $hideifempty true to hide the summary if there are no comments
  4818.      * 
  4819.      * @return void
  4820.      */
  4821.     function showComments($rating = true, $order = "desc", $showabuse = true, $hideifempty = false)
  4822.     {
  4823.         
  4824.         global $imSettings;
  4825.  
  4826.         $c = $this->comments->getAll("timestamp", $order);
  4827.  
  4828.         if (count($c) == 0 && $hideifempty)
  4829.             return;
  4830.  
  4831.         echo "<div class=\"topic-comments\">\n";
  4832.         if (count($c) > 0) {
  4833.             // Check aproved comments count
  4834.             $ca = array();
  4835.             foreach($c as $comment)
  4836.                 if($comment['approved'] == "1")
  4837.                     $ca[] = $comment;
  4838.  
  4839.             // Show the comments
  4840.             $i = 0;
  4841.             foreach ($ca as $comment) {
  4842.                 if (isset($comment['body']) && $comment['approved'] == "1") {
  4843.                     echo "<div class=\"topic-comment\">\n";
  4844.                     echo "<div class=\"topic-comments-user\">" . (stristr($comment['url'], "http") ? "<a href=\"" . $comment['url'] . "\" target=\"_blank\" " . (strpos($comment['url'], $imSettings['general']['url']) === false ? 'rel="nofollow"' : '') . ">" . $comment['name'] . "</a>" : $comment['name']);
  4845.                     if ($rating && isset($comment['rating']) && $comment['rating'] > 0) {
  4846.                         echo "<span class=\"topic-star-container-small\" title=\"" . $comment['rating'] . "/5\" style=\"margin-left: 5px; vertical-align: middle;\">
  4847.                                     <span class=\"topic-star-fixer-small\" style=\"width: " . round($comment['rating']/5 * 100) . "%;\"></span>
  4848.                             </span>\n";
  4849.                     }
  4850.                     echo "</div>\n";
  4851.                     echo "<div class=\"topic-comments-date imBreadcrumb\">" . $comment['timestamp'] . "</div>\n";
  4852.                     echo "<div class=\"topic-comments-body\">" . $comment['body'] . "</div>\n";
  4853.                     if ($showabuse) {
  4854.                         echo "<div class=\"topic-comments-abuse\"><a href=\"" . $this->posturl . "x5topicid=" . $this->id . "&abuse=" . $i++ . "\">" . l10n('blog_abuse') . "<img src=\"" . $this->basepath . "res/exclamation.png\" alt=\"" . l10n('blog_abuse') . "\" title=\"" . l10n('blog_abuse') . "\" /></a></div>\n";
  4855.                     }
  4856.                     echo "</div>\n";
  4857.                 }
  4858.                 $i++;
  4859.             }
  4860.         } else {
  4861.             echo "<div>" . l10n('blog_no_comment') . "</div>\n";
  4862.         }
  4863.         echo "</div>\n";        
  4864.     }
  4865.  
  4866.     /**
  4867.      * Show the comments list in a administration section
  4868.      * 
  4869.      * @param boolean $rating true to show the ratings
  4870.      * @param string  $order  desc or asc
  4871.      * 
  4872.      * @return void
  4873.      */
  4874.     function showAdminComments($rating = true, $order = "desc")
  4875.     {
  4876.         
  4877.         global $imSettings;
  4878.         $this->comments->sort("ts", $order);
  4879.  
  4880.         if (isset($_GET['disable'])) {
  4881.             $n = (int)$_GET['disable'];
  4882.             $c = $this->comments->get($n);
  4883.             if (count($c) != 0) {
  4884.                 $c['approved'] = "0";
  4885.                 $this->comments->edit($n, $c);
  4886.                 $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4887.             }
  4888.         }
  4889.  
  4890.         if (isset($_GET['enable'])) {
  4891.             $n = (int)$_GET['enable'];
  4892.             $c = $this->comments->get($n);
  4893.             if (count($c) != 0) {
  4894.                 $c['approved'] = "1";
  4895.                 $this->comments->edit($n, $c);
  4896.                 $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4897.             }
  4898.         }
  4899.  
  4900.         if (isset($_GET['delete'])) {
  4901.             $this->comments->delete((int)$_GET['delete']);
  4902.             $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4903.         }
  4904.  
  4905.         if (isset($_GET['unabuse'])) {
  4906.             $n = (int)$_GET['unabuse'];
  4907.             $c = $this->comments->get($n);
  4908.             if (count($c)) {
  4909.                 $c['abuse'] = "0";
  4910.                 $this->comments->edit($n, $c);
  4911.                 $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4912.             }
  4913.         }
  4914.  
  4915.         if (isset($_GET['disable']) || isset($_GET['enable']) || isset($_GET['delete']) || isset($_GET['unabuse'])) {
  4916.             echo "<script type=\"text/javascript\">window.top.location.href='" . $this->posturl . "';</script>\n";
  4917.             exit();
  4918.         }
  4919.  
  4920.         echo "<div class=\"topic-comments\">\n";
  4921.         $c = $this->comments->getAll();
  4922.         if (count($c) > 0) {
  4923.             // Show the comments
  4924.             for ($i = 0; $i < count($c); $i++) {
  4925.                 $comment = $c[$i];
  4926.                 if (isset($comment['body'])) {
  4927.                     echo "<div class=\"topic-comment " . ($comment['approved'] == "1" ? "enabled" : "disabled") . ($comment['abuse'] == "1" ? " abused" : "") . "\">\n";
  4928.                     echo "\t<div class=\"topic-comments-user\">";
  4929.                     if ($comment['abuse'] == "1") {
  4930.                         echo "<img src=\"" . $this->basepath . "res/exclamation.png\" alt=\"Abuse\" title=\"" . l10n('admin_comment_abuse') . "\" style=\"vertical-align: middle;\">\n";
  4931.                     }
  4932.                     echo (stristr($comment['url'], "http") ? "<a href=\"" . $comment['url'] . "\" target=\"_blank\" " . (strpos($comment['url'], $imSettings['general']['url']) === false ? 'rel="nofollow"' : '') . ">" . $comment['name'] . "</a>" : $comment['name']);
  4933.                     if ($rating && isset($comment['rating']) && $comment['rating'] > 0) {
  4934.                         echo "\t<span class=\"topic-star-container-small\" title=\"" . $comment['rating'] . "/5\" style=\"margin-left: 5px; vertical-align: middle;\">
  4935.                                     <span class=\"topic-star-fixer-small\" style=\"width: " . round($comment['rating']/5 * 100) . "%;\"></span>
  4936.                             </span>\n";
  4937.                     }
  4938.                     echo "\t</div>\n";
  4939.                     echo "\t<div class=\"topic-comments-date imBreadcrumb\">" . $comment['timestamp'] . "</div>\n";
  4940.                     echo "\t<div class=\"topic-comments-body\">" . $comment['body'] . "</div>\n";
  4941.                     echo "\t<div class=\"topic-comments-controls\">\n";
  4942.                     echo "\t\t<span style=\"float: left;\">IP: " . $comment['ip'] . "</span>\n";
  4943.                     if ($comment['abuse'] == "1")
  4944.                         echo "\t\t<a href=\"" . $this->posturl . "unabuse=" . $i . "\">" . l10n("blog_abuse_remove", "Remove abuse") . "</a> |\n";
  4945.                     if ($comment['approved'] == "1")
  4946.                         echo "\t\t<a onclick=\"return confirm('" . str_replace("'", "\\'", l10n('blog_unapprove_question')) . "')\" href=\"" . $this->posturl . "disable=" . $i . "\">" . l10n('blog_unapprove') . "</a> |\n";
  4947.                     else
  4948.                         echo "\t\t<a onclick=\"return confirm('" . str_replace("'", "\\'", l10n('blog_approve_question')) . "')\" href=\"" . $this->posturl . "enable=" . $i . "\">" . l10n('blog_approve') . "</a> |\n";
  4949.                     echo "\t\t<a onclick=\"return confirm('" . str_replace("'", "\\'", l10n('blog_delete_question')) . "')\" href=\"" . $this->posturl . "delete=" . $i . "\">" . l10n('blog_delete') . "</a>\n";
  4950.                     echo "</div>\n";
  4951.                     echo "</div>\n";
  4952.                 }
  4953.             }
  4954.         } else {
  4955.             echo "<div style=\"text-align: center; margin: 15px; 0\">" . l10n('blog_no_comment') . "</div>\n";
  4956.         }
  4957.         echo "</div>\n";        
  4958.     }
  4959.  
  4960.     /**
  4961.      * Show a single rating form
  4962.      * 
  4963.      * @return void
  4964.      */
  4965.     function showRating()
  4966.     {
  4967.         
  4968.         global $imSettings;
  4969.  
  4970.         if (isset($_POST['x5topicid']) && $_POST['x5topicid'] == $this->id && !isset($_COOKIE['vtd' . $this->id]) && isset($_POST['imJsCheck']) && $_POST['imJsCheck'] == 'jsactive') {
  4971.             $this->comments->add(
  4972.                 array(
  4973.                     "rating" => $_POST['rating'],
  4974.                     "approved" => "1"
  4975.                 )
  4976.             );
  4977.             $this->storageType == "xml" ? $this->saveXML() : $this->saveDb();
  4978.         }
  4979.  
  4980.         $c = $this->comments->getAll();
  4981.         $count = 0;
  4982.         $votes = 0;
  4983.         $vote = 0;
  4984.         if (count($c) > 0) {
  4985.             // Check aproved comments count
  4986.             $ca = array();
  4987.             foreach ($c as $comment) {
  4988.                 if ($comment['approved'] == "1" && isset($comment['rating'])) {
  4989.                     $count++;
  4990.                     $votes += $comment['rating'];
  4991.                 }
  4992.             }
  4993.             $vote = ($count > 0 ? $votes/$count : 0);
  4994.         }
  4995.         echo "
  4996.             <div style=\"text-align: center\">
  4997.                 <div style=\"margin-bottom: 5px;\">" . l10n("blog_rating", "Vote:") . " " . number_format($vote, 1) . "/5</div>
  4998.                 <div class=\"topic-star-container-big" . (!isset($_COOKIE['vtd' . $this->id]) ? " variable-star-rating" : "") . "\" data-url=\"" . $this->posturl . "\" data-id=\"" . $this->id . "\">
  4999.                     <span class=\"topic-star-fixer-big\" style=\"width: " . round($vote/5 * 100) . "%;\"></span>
  5000.                 </div>
  5001.             </div>\n";
  5002.     }
  5003. }
  5004.  
  5005.  
  5006.  
  5007. /**
  5008.  * XML Handling class
  5009.  * @access public
  5010.  */
  5011. class imXML 
  5012. {
  5013.     var $tree = array();
  5014.     var $force_to_array = array();
  5015.     var $error = null;
  5016.     var $parser;
  5017.     var $inside = false;
  5018.  
  5019.     // PHP 5
  5020.     function __construct($encoding = 'UTF-8')
  5021.     {
  5022.         $this->setUp($encoding);
  5023.     }
  5024.  
  5025.     // PHP 4
  5026.     function imXML($encoding = 'UTF-8')
  5027.     {
  5028.         $this->setUp($encoding);   
  5029.     }
  5030.  
  5031.     function setUp($encoding = 'UTF-8')
  5032.     {
  5033.         $this->parser = xml_parser_create($encoding);
  5034.         xml_set_object($this->parser, $this); // $this was passed as reference &$this
  5035.         xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
  5036.         xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1);
  5037.         xml_set_element_handler($this->parser, "startEl", "stopEl");
  5038.         xml_set_character_data_handler($this->parser, "charData");
  5039.         xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8');
  5040.     }
  5041.  
  5042.     function parse_file($file)
  5043.     {
  5044.         $fp = @fopen($file, "r");
  5045.         if (!$fp)
  5046.             return false;
  5047.         while ($data = fread($fp, 4096)) {
  5048.             if (!xml_parse($this->parser, $data, feof($fp))) {
  5049.                 return false;
  5050.             }
  5051.         }
  5052.         fclose($fp);
  5053.         return $this->tree[0]["content"];
  5054.     }
  5055.  
  5056.     function parse_string($str)
  5057.     {
  5058.         if (!xml_parse($this->parser, $str))
  5059.             return false;
  5060.         if (isset($this->tree[0]["content"]))
  5061.             return $this->tree[0]["content"];
  5062.         return false;
  5063.     }
  5064.  
  5065.     function startEl($parser, $name, $attrs)
  5066.     {
  5067.         array_unshift($this->tree, array("name" => $name));
  5068.         $this->inside = false;
  5069.     }
  5070.  
  5071.     function stopEl($parser, $name)
  5072.     {
  5073.         if ($name != $this->tree[0]["name"])
  5074.             return false;
  5075.         if (count($this->tree) > 1) {
  5076.             $elem = array_shift($this->tree);
  5077.             if (isset($this->tree[0]["content"][$elem["name"]])) {
  5078.                 if (is_array($this->tree[0]["content"][$elem["name"]]) && isset($this->tree[0]["content"][$elem["name"]][0])) {
  5079.                     array_push($this->tree[0]["content"][$elem["name"]], $elem["content"]);
  5080.                 } else {
  5081.                     $this->tree[0]["content"][$elem["name"]] = array($this->tree[0]["content"][$elem["name"]],$elem["content"]);
  5082.                 }
  5083.             } else {
  5084.                 if (in_array($elem["name"], $this->force_to_array)) {
  5085.                     $this->tree[0]["content"][$elem["name"]] = array($elem["content"]);
  5086.                 } else {
  5087.                     if (!isset($elem["content"])) $elem["content"] = "";
  5088.                     $this->tree[0]["content"][$elem["name"]] = $elem["content"];
  5089.                 }
  5090.             }
  5091.         }
  5092.         $this->inside = false;
  5093.     }
  5094.  
  5095.     function charData($parser, $data)
  5096.     {
  5097.         if (!preg_match("/\\S/", $data))
  5098.                 return false;
  5099.         if ($this->inside) {
  5100.             $this->tree[0]["content"] .= $data;
  5101.         } else {
  5102.             $this->tree[0]["content"] = $data;
  5103.         }
  5104.         $this->inside_data = true; 
  5105.     }
  5106. }
  5107.  
  5108.  
  5109. /**
  5110.  * Some useful functions
  5111.  *
  5112.  * @category X5engine
  5113.  * @package  X5engine
  5114.  * @license  Copyright by Incomedia http://incomedia.eu
  5115.  * @link     http://websitex5.com
  5116.  */
  5117.  
  5118. /**
  5119.  * Prints an error about not active JS
  5120.  *
  5121.  * @param $docType True to use the meta redirect with a complete document. False to use a javascript code.
  5122.  * 
  5123.  * @return void
  5124.  */
  5125. function imPrintJsError($docType = true)
  5126. {
  5127.     if ($docType) {
  5128.         $html = "<DOCTYPE><html><head><meta http-equiv=\"Refresh\" content=\"5;URL=" . $_SERVER['HTTP_REFERER'] . "\"></head><body>";
  5129.         $html .= l10n('form_js_error');
  5130.         $html .= "</body></html>";
  5131.     } else {
  5132.         $html = "<meta http-equiv=\"Refresh\" content=\"5;URL=" . $_SERVER['HTTP_REFERER'] . "\">";
  5133.         $html .= l10n('form_js_error');
  5134.     }
  5135.     return $html;
  5136. }
  5137.  
  5138. /**
  5139.  * Check the user's access to $page
  5140.  * 
  5141.  * @param string $page The page to check
  5142.  * 
  5143.  * @return void
  5144.  */
  5145. function imCheckAccess($page)
  5146. {
  5147.     $pa = new imPrivateArea();
  5148.     $stat = $pa->checkAccess($page);
  5149.     if ($stat !== 0) {
  5150.         $pa->savePage();
  5151.         header("Location: imlogin.php?loginstatus=" . $stat );
  5152.         exit;
  5153.     }
  5154. }
  5155.  
  5156.  
  5157. /**
  5158.  * Show the guestbook
  5159.  * This function is provided as compatibility for v9 guestbook widget
  5160.  * 
  5161.  * @param string  $id              The guestbook id
  5162.  * @param string  $filepath        The folder where the comments must be stored
  5163.  * @param string  $email           The email to notify the new comments
  5164.  * @param boolean $captcha         true to show the captcha
  5165.  * @param boolean $direct_approval true to directly approve comments
  5166.  * 
  5167.  * @return void
  5168.  */
  5169. function showGuestBook($id, $filepath, $email, $captcha = true, $direct_approval = true)
  5170. {
  5171.     global $imSettings;
  5172.  
  5173.     $gb = new ImTopic("gb" . $id);
  5174.     $gb->loadXML($filepath);
  5175.     $gb->showSummary(false);
  5176.     $gb->showForm(false, $captcha, !$direct_approval, $email, "guestbook", $imSettings['general']['url'] . "/admin/guestbook.php?id=" . $id);
  5177.     $gb->showComments(false);
  5178. }
  5179.  
  5180. /**
  5181.  * Provide the database connection data of given id
  5182.  * @param  string $dbid The database id
  5183.  * @return array        an array like array('description' => '', 'host' => '', 'database' => '', 'user' => '', 'password' => '')
  5184.  */
  5185. function getDbData($dbid) {
  5186.     global $imSettings;
  5187.     if (!isset($imSettings['databases'][$dbid]))
  5188.         return false;
  5189.     return $imSettings['databases'][$dbid];
  5190. }
  5191.  
  5192.  
  5193. /**
  5194.  * Shuffle an associate array
  5195.  * 
  5196.  * @param array $list The array to shuffle
  5197.  * 
  5198.  * @return array       The shuffled array
  5199.  */
  5200. function shuffleAssoc($list)
  5201. {
  5202.     if (!is_array($list))
  5203.         return $list;
  5204.     $keys = array_keys($list);
  5205.     shuffle($keys);
  5206.     $random = array();
  5207.     foreach ($keys as $key)
  5208.         $random[$key] = $list[$key];
  5209.     return $random;
  5210. }
  5211.  
  5212. /**
  5213.  * Provide a fallback for the PHP5 stripos function
  5214.  * 
  5215.  * @param string  $haystack Where to search
  5216.  * @param string  $needle   What to replace
  5217.  * @param integer $offset   Start searching from here
  5218.  * 
  5219.  * @return integer          The position of the searched string
  5220.  */
  5221. function imstripos($haystack, $needle , $offset = 0)
  5222. {
  5223.     if (function_exists('stripos')) // Is PHP5+
  5224.         return stripos($haystack, $needle, $offset);
  5225.  
  5226.     // PHP4 fallback
  5227.     return strpos(strtolower($haystack), strtolower($needle), $offset);
  5228. }
  5229.  
  5230. /**
  5231.  * Provide a localization helper
  5232.  * 
  5233.  * @param string $id      The localization key
  5234.  * @param string $default The default string
  5235.  * 
  5236.  * @return string          The localization
  5237.  */
  5238. function l10n($id, $default = "")
  5239. {
  5240.     global $l10n;
  5241.  
  5242.     if (!isset($l10n[$id]))
  5243.         return $default;
  5244.  
  5245.     return $l10n[$id];
  5246. }
  5247.  
  5248. /**
  5249.  * Combine paths
  5250.  * 
  5251.  * @param  array  $paths
  5252.  * 
  5253.  * @return string
  5254.  */
  5255. function pathCombine($paths = array())
  5256. {
  5257.     $s = array();
  5258.     foreach ($paths as $path) {
  5259.         if (strlen($path))
  5260.             $s[] = trim($path, "/\\ ");
  5261.     }
  5262.     return implode("/", $s);
  5263. }
  5264.  
  5265. /**
  5266.  * Try to convert a string to lowercase using multibyte encoding
  5267.  * 
  5268.  * @param  string $str
  5269.  * 
  5270.  * @return string
  5271.  */
  5272. function imstrtolower($str)
  5273. {
  5274.     return (function_exists("mb_convert_case") ? mb_convert_case($str, MB_CASE_LOWER, "UTF-8") : strtolower($str));
  5275. }
  5276.  
  5277. if (!function_exists('htmlspecialchars_decode')) {
  5278.     /**
  5279.      * Fallback for htmlspecialchars_decode in PHP4
  5280.      * @param  string  $text
  5281.      * @param  integer $quote_style
  5282.      * @return string
  5283.      */
  5284.     function htmlspecialchars_decode($text, $quote_style = ENT_COMPAT)
  5285.     {
  5286.         return strtr($text, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
  5287.     }
  5288. }
  5289.  
  5290. /**
  5291.  * Fallback for json_encode before PHP 5.2
  5292.  */
  5293. if (!function_exists('json_encode')) {
  5294.     function json_encode($data)
  5295.     {
  5296.         switch ($type = gettype($data)) {
  5297.             case 'NULL':
  5298.                 return 'null';
  5299.             case 'boolean':
  5300.                 return ($data ? 'true' : 'false');
  5301.             case 'integer':
  5302.             case 'double':
  5303.             case 'float':
  5304.                 return $data;
  5305.             case 'string':
  5306.                 return '"' . addslashes($data) . '"';
  5307.             case 'object':
  5308.                 $data = get_object_vars($data);
  5309.             case 'array':
  5310.                 $output_index_count = 0;
  5311.                 $output_indexed = array();
  5312.                 $output_associative = array();
  5313.                 foreach ($data as $key => $value) {
  5314.                     $output_indexed[] = json_encode($value);
  5315.                     $output_associative[] = json_encode($key) . ':' . json_encode($value);
  5316.                     if ($output_index_count !== NULL && $output_index_count++ !== $key) {
  5317.                         $output_index_count = NULL;
  5318.                     }
  5319.                 }
  5320.                 if ($output_index_count !== NULL) {
  5321.                     return '[' . implode(',', $output_indexed) . ']';
  5322.                 } else {
  5323.                     return '{' . implode(',', $output_associative) . '}';
  5324.                 }
  5325.             default:
  5326.                 return ''; // Not supported
  5327.         }
  5328.     }
  5329. }
  5330.  
  5331. /**
  5332.  * Check for the valid data about spam and js
  5333.  * 
  5334.  * @param  string $prt The spam post field name
  5335.  * @param  string $js  The js post file name
  5336.  * 
  5337.  * @return bool
  5338.  */
  5339. function checkJsAndSpam($prt = 'prt', $js = 'imJsCheck')
  5340. {
  5341.     // Spam!
  5342.     if ($_POST[$prt] != "") {
  5343.         return false;
  5344.     }
  5345.  
  5346.     // Javascript disabled
  5347.     if (!isset($_POST[$js]) || $_POST[$js] != 'jsactive') {
  5348.         echo imPrintJsError(false);
  5349.         return false;
  5350.     }
  5351.  
  5352.     return true;
  5353. }
  5354.  
  5355. /**
  5356.  * Search if at least one element of $needle is in $haystack.
  5357.  * @param  Array   $needle   Non-associative array
  5358.  * @param  Array   $haystack Non-associative array
  5359.  * @param  boolean $all      Set to true to ensure that all the elements in $needle are in $haystack
  5360.  * @return boolean
  5361.  */
  5362. function in_array_field($needle, $haystack, $all = false)
  5363. {
  5364.     if ($all) {
  5365.         foreach ($needle as $key)
  5366.             if (!in_array($key, $haystack))
  5367.                 return false;
  5368.         return true;
  5369.     } else {
  5370.         foreach ($needle as $key)
  5371.             if (in_array($key, $haystack))
  5372.                 return true;
  5373.         return false;
  5374.     }
  5375. }
  5376.  
  5377. /**
  5378.  * Filter the var from unwanted input chars.
  5379.  * Basically remove the quotes added by magic_quotes
  5380.  * @param  mixed $var The var to filter
  5381.  * @return mixed      The filtered var
  5382.  */
  5383. function imFilterInput($var) {
  5384.     // Remove the magic quotes
  5385.     if (get_magic_quotes_gpc()) {        
  5386.         // String
  5387.         if (is_string($var))
  5388.             $var = stripslashes($var);
  5389.         // Array
  5390.         else if (is_array($var)) {
  5391.             for ($i = 0; $i < count($var); $i++)
  5392.                 $var[$i] = imFilterInput($var[$i]);
  5393.         }
  5394.     }
  5395.     return $var;
  5396. }
  5397.  
  5398. /**
  5399.  * Provide a fallback function to get the headers array on PHP 4.3.0 and less.
  5400.  * 
  5401.  * @return array or FALSE on failure
  5402.  */
  5403. function imRequestHeaders()
  5404. {
  5405.     $headers = array();
  5406.     // If apache supports apache_request_headers, use it!
  5407.     if (function_exists('apache_request_headers')) {
  5408.         $headers = apache_request_headers();
  5409.         if (!is_array($headers))
  5410.             return false;
  5411.     } else {
  5412.         // Build the array manually
  5413.         foreach ($_SERVER as $key => $val) {
  5414.             if (strncmp($key, 'HTTP_', 5) === 0) {
  5415.                 $headers[substr($key, 5)] = $_SERVER[$key];
  5416.             }
  5417.         }
  5418.         if (count($headers) === 0)
  5419.             return false;
  5420.         $headers['Content-Type'] = (isset($_SERVER['CONTENT_TYPE'])) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
  5421.     }
  5422.  
  5423.     // Format the headers name correctly. For example, turn CONTENT_TYPE into Content-Type.
  5424.     foreach ($headers as $key => $val) {
  5425.         $key = str_replace('_', ' ', strtolower($key));
  5426.         $key = str_replace(' ', '-', ucwords($key));
  5427.         $headers[$key] = $val;
  5428.     }
  5429.     
  5430.     return $headers;
  5431. }
  5432.  
  5433. // End of file