Esempio n. 1
0
 public function display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber, $totalPages)
 {
     global $config, $page;
     $theme_name = $config->get_string('theme');
     $data_href = $config->get_string('base_href');
     $base_href = $config->get_string('base_href');
     $html = "";
     $n = 0;
     $html = "<table id='postList' class='zebra'>" . "<thead><tr>" . "<th>User</th>" . "<th>Message</th>" . "</tr></thead>";
     foreach ($posts as $post) {
         $message = $post["message"];
         $tfe = new TextFormattingEvent($message);
         send_event($tfe);
         $message = $tfe->formatted;
         $message = str_replace('\\n\\r', '<br>', $message);
         $message = str_replace('\\r\\n', '<br>', $message);
         $message = str_replace('\\n', '<br>', $message);
         $message = str_replace('\\r', '<br>', $message);
         $message = stripslashes($message);
         $user = "******" . make_link("user/" . $post["user_name"] . "") . "'>" . $post["user_name"] . "</a>";
         $poster = User::by_name($post["user_name"]);
         $gravatar = $poster->get_avatar_html();
         $oe = $n++ % 2 == 0 ? "even" : "odd";
         if ($post["user_admin"] == "Y") {
             $rank = "<sup>admin</sup>";
         } else {
             $rank = "<sup>user</sup>";
         }
         $postID = $post['id'];
         //if($user->is_admin()){
         //$delete_link = "<a href=".make_link("forum/delete/".$threadID."/".$postID).">Delete</a>";
         //} else {
         //$delete_link = "";
         //}
         if ($showAdminOptions) {
             $delete_link = "<a href=" . make_link("forum/delete/" . $threadID . "/" . $postID) . ">Delete</a>";
         } else {
             $delete_link = "";
         }
         $html .= "<tr class='{$oe}'>" . "<td class='forum_user'>" . $user . "<br>" . $rank . "<br>" . $gravatar . "</td>" . "<td class='forum_message'>" . $message . "</td>" . "</tr>\n\t\t\t\t<tr class='{$oe}'>\n\t\t\t\t\t<td class='forum_subuser'><small>" . autodate($post["date"]) . "</small></td>\n\t\t\t\t\t<td class='forum_submessage'>" . $delete_link . "</td>\n\t\t\t\t</tr>";
     }
     $html .= "</tbody></table>";
     $this->display_paginator($page, "forum/view/" . $threadID, null, $pageNumber, $totalPages);
     $page->set_title(html_escape($threadTitle));
     $page->set_heading(html_escape($threadTitle));
     $page->add_block(new Block("Thread", $html, "main", 20));
 }
Esempio n. 2
0
 public function display_thread($posts, $showAdminOptions, $threadTitle, $threadID, $pageNumber, $totalPages)
 {
     global $config, $page;
     $posts_per_page = $config->get_int('forumPostsPerPage');
     $current_post = 0;
     $html = "<div id=returnLink>[<a href=" . make_link("forum/index/") . ">Return</a>]</div><br><br>" . "<table id='threadPosts' class='zebra'>" . "<thead><tr>" . "<th id=threadHeadUser>User</th>" . "<th>Message</th>" . "</tr></thead>";
     foreach ($posts as $post) {
         $current_post++;
         $message = $post["message"];
         $tfe = new TextFormattingEvent($message);
         send_event($tfe);
         $message = $tfe->formatted;
         $message = str_replace('\\n\\r', '<br>', $message);
         $message = str_replace('\\r\\n', '<br>', $message);
         $message = str_replace('\\n', '<br>', $message);
         $message = str_replace('\\r', '<br>', $message);
         $message = stripslashes($message);
         $user = "******" . make_link("user/" . $post["user_name"] . "") . "'>" . $post["user_name"] . "</a>";
         $poster = User::by_name($post["user_name"]);
         $gravatar = $poster->get_avatar_html();
         $rank = "<sup class='user_rank'>{$post["user_class"]}</sup>";
         $postID = $post['id'];
         //if($user->is_admin()){
         //$delete_link = "<a href=".make_link("forum/delete/".$threadID."/".$postID).">Delete</a>";
         //} else {
         //$delete_link = "";
         //}
         if ($showAdminOptions) {
             $delete_link = "<a href=" . make_link("forum/delete/" . $threadID . "/" . $postID) . ">Delete</a>";
         } else {
             $delete_link = "";
         }
         $post_number = ($pageNumber - 1) * $posts_per_page + $current_post;
         $html .= "<tr >\n\t\t\t<tr class='postHead'>\n\t\t\t\t<td class='forumSupuser'></td>\n\t\t\t\t<td class='forumSupmessage'><div class=deleteLink>" . $delete_link . "</div></td>\n\t\t\t</tr>\n\t\t\t<tr class='posBody'>\n\t\t\t\t<td class='forumUser'>" . $user . "<br>" . $rank . "<br>" . $gravatar . "<br></td>\n\t\t\t\t<td class='forumMessage'>\n\t\t\t\t\t<div class=postDate><small>" . autodate($post['date']) . "</small></div>\n\t\t\t\t\t<div class=postNumber> #" . $post_number . "</div>\n\t\t\t\t\t<br>\n\t\t\t\t\t<div class=postMessage>" . $message . "</td>\n\t\t\t</tr>\n\t\t\t<tr class='postFoot'>\n\t\t\t\t<td class='forumSubuser'></td>\n\t\t\t\t<td class='forumSubmessage'></td>\n\t\t\t</tr>";
     }
     $html .= "</tbody></table>";
     $this->display_paginator($page, "forum/view/" . $threadID, null, $pageNumber, $totalPages);
     $page->set_title(html_escape($threadTitle));
     $page->set_heading(html_escape($threadTitle));
     $page->add_block(new Block($threadTitle, $html, "main", 20));
 }
Esempio n. 3
0
 /**
  * @param string $name
  * @param string $pass
  */
 private function set_login_cookie($name, $pass)
 {
     global $config;
     $addr = get_session_ip($config);
     $hash = User::by_name($name)->passhash;
     set_prefixed_cookie("user", $name, time() + 60 * 60 * 24 * 365, '/');
     set_prefixed_cookie("session", md5($hash . $addr), time() + 60 * 60 * 24 * $config->get_int('login_memory'), '/');
 }
Esempio n. 4
0
 public function onSearchTermParse($event)
 {
     $matches = array();
     if (preg_match("/comments(<|>|<=|>=|=)(\\d+)/", $event->term, $matches)) {
         $cmp = $matches[1];
         $comments = $matches[2];
         $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) {$cmp} {$comments})"));
     } else {
         if (preg_match("/commented_by=(.*)/i", $event->term, $matches)) {
             global $database;
             $user = User::by_name($matches[1]);
             if (!is_null($user)) {
                 $user_id = $user->id;
             } else {
                 $user_id = -1;
             }
             $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = {$user_id})"));
         } else {
             if (preg_match("/commented_by_userid=([0-9]+)/i", $event->term, $matches)) {
                 $user_id = int_escape($matches[1]);
                 $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = {$user_id})"));
             }
         }
     }
 }
Esempio n. 5
0
 public function onImageInfoSet(ImageInfoSetEvent $event)
 {
     global $user;
     if ($user->can("edit_image_owner")) {
         $owner = User::by_name($_POST['tag_edit__owner']);
         if ($owner instanceof User) {
             send_event(new OwnerSetEvent($event->image, $owner));
         } else {
             throw new NullUserException("Error: No user with that name was found.");
         }
     }
     if ($this->can_tag($event->image) && isset($_POST['tag_edit__tags'])) {
         send_event(new TagSetEvent($event->image, $_POST['tag_edit__tags']));
     }
     if ($this->can_source($event->image) && isset($_POST['tag_edit__source'])) {
         if (isset($_POST['tag_edit__tags']) ? !preg_match('/source[=|:]/', $_POST["tag_edit__tags"]) : TRUE) {
             send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source']));
         }
     }
     if ($user->can("edit_image_lock")) {
         $locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked'] == "on";
         send_event(new LockSetEvent($event->image, $locked));
     }
 }
Esempio n. 6
0
 public function onSearchTermParse(SearchTermParseEvent $event)
 {
     $matches = array();
     if (preg_match("/^note[=|:](.*)\$/i", $event->term, $matches)) {
         $notes = int_escape($matches[1]);
         $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = {$notes})"));
     } else {
         if (preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\\d+)%/i", $event->term, $matches)) {
             $cmp = ltrim($matches[1], ":") ?: "=";
             $notes = $matches[2];
             $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes {$cmp} {$notes})"));
         } else {
             if (preg_match("/^notes_by[=|:](.*)\$/i", $event->term, $matches)) {
                 $user = User::by_name($matches[1]);
                 if (!is_null($user)) {
                     $user_id = $user->id;
                 } else {
                     $user_id = -1;
                 }
                 $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = {$user_id})"));
             } else {
                 if (preg_match("/^notes_by_userno[=|:](\\d+)\$/i", $event->term, $matches)) {
                     $user_id = int_escape($matches[1]);
                     $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE user_id = {$user_id})"));
                 }
             }
         }
     }
 }
Esempio n. 7
0
 /**
  * @param string $name
  * @throws Exception
  */
 public function set_name($name)
 {
     global $database;
     if (User::by_name($name)) {
         throw new Exception("Desired username is already in use");
     }
     $old_name = $this->name;
     $this->name = $name;
     $database->Execute("UPDATE users SET name=:name WHERE id=:id", array("name" => $this->name, "id" => $this->id));
     log_info("core-user", "Changed username for {$old_name} to {$this->name}");
 }
Esempio n. 8
0
    /**
     * This function attempts to revert all changes by a given IP within an (optional) timeframe.
     *
     * @param string $name
     * @param string $ip
     * @param string $date
     */
    public function process_revert_all_changes($name, $ip, $date)
    {
        global $database;
        $select_code = array();
        $select_args = array();
        if (!is_null($name)) {
            $duser = User::by_name($name);
            if (is_null($duser)) {
                $this->theme->add_status($name, "user not found");
                return;
            } else {
                $select_code[] = 'user_id = ?';
                $select_args[] = $duser->id;
            }
        }
        if (!is_null($date)) {
            $select_code[] = 'date_set >= ?';
            $select_args[] = $date;
        }
        if (!is_null($ip)) {
            $select_code[] = 'user_ip = ?';
            $select_args[] = $ip;
        }
        if (count($select_code) == 0) {
            log_error("source_history", "Tried to mass revert without any conditions");
            return;
        }
        log_info("source_history", 'Attempting to revert edits where ' . implode(" and ", $select_code) . " (" . implode(" / ", $select_args) . ")");
        // Get all the images that the given IP has changed source on (within the timeframe) that were last editied by the given IP
        $result = $database->get_col('
				SELECT t1.image_id
				FROM source_histories t1
				LEFT JOIN source_histories t2 ON (t1.image_id = t2.image_id AND t1.date_set < t2.date_set)
				WHERE t2.image_id IS NULL
				AND t1.image_id IN ( select image_id from source_histories where ' . implode(" AND ", $select_code) . ') 
				ORDER BY t1.image_id
		', $select_args);
        foreach ($result as $image_id) {
            // Get the first source history that was done before the given IP edit
            $row = $database->get_row('
				SELECT id, source
				FROM source_histories
				WHERE image_id=' . $image_id . '
				AND NOT (' . implode(" AND ", $select_code) . ')
				ORDER BY date_set DESC LIMIT 1
			', $select_args);
            if (empty($row)) {
                // we can not revert this image based on the date restriction.
                // Output a message perhaps?
            } else {
                $revert_id = $row['id'];
                $result = $this->get_source_history_from_revert($revert_id);
                if (empty($result)) {
                    // there is no history entry with that id so either the image was deleted
                    // while the user was viewing the history,  or something messed up
                    /* calling die() is probably not a good idea, we should throw an Exception */
                    die('Error: No source history with specified id (' . $revert_id . ') was found in the database.' . "\n\n" . 'Perhaps the image was deleted while processing this request.');
                }
                // lets get the values out of the result
                $stored_result_id = $result['id'];
                $stored_image_id = $result['image_id'];
                $stored_source = $result['source'];
                log_debug("source_history", 'Reverting source of Image #' . $stored_image_id . ' to [' . $stored_source . ']');
                $image = Image::by_id($stored_image_id);
                if (is_null($image)) {
                    die('Error: No image with the id (' . $stored_image_id . ') was found. Perhaps the image was deleted while processing this request.');
                }
                // all should be ok so we can revert by firing the SetSources event.
                send_event(new SourceSetEvent($image, $stored_source));
                $this->theme->add_status('Reverted Change', 'Reverted Image #' . $image_id . ' to Source History #' . $stored_result_id . ' (' . $row['source'] . ')');
            }
        }
        log_info("source_history", 'Reverted ' . count($result) . ' edits.');
    }
Esempio n. 9
0
 public function onSearchTermParse(SearchTermParseEvent $event)
 {
     $matches = array();
     if (preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\\d+)\$/i", $event->term, $matches)) {
         $cmp = ltrim($matches[1], ":") ?: "=";
         $comments = $matches[2];
         $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) {$cmp} {$comments})"));
     } else {
         if (preg_match("/^commented_by[=|:](.*)\$/i", $event->term, $matches)) {
             $user = User::by_name($matches[1]);
             if (!is_null($user)) {
                 $user_id = $user->id;
             } else {
                 $user_id = -1;
             }
             $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = {$user_id})"));
         } else {
             if (preg_match("/^commented_by_userno[=|:]([0-9]+)\$/i", $event->term, $matches)) {
                 $user_id = int_escape($matches[1]);
                 $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM comments WHERE owner_id = {$user_id})"));
             }
         }
     }
 }
Esempio n. 10
0
 /**
  * Construct a User by name and password.
  * @param string $name
  * @param string $pass
  * @return null|User
  */
 public static function by_name_and_pass($name, $pass)
 {
     assert(is_string($name));
     assert(is_string($pass));
     $user = User::by_name($name);
     if ($user) {
         if ($user->passhash == md5(strtolower($name) . $pass)) {
             $user->set_password($pass);
         }
         if (password_verify($pass, $user->passhash)) {
             return $user;
         }
     }
 }
Esempio n. 11
0
 public function onSearchTermParse(SearchTermParseEvent $event)
 {
     $matches = array();
     if (preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\\d+)\$/i", $event->term, $matches)) {
         $cmp = ltrim($matches[1], ":") ?: "=";
         $score = $matches[2];
         $event->add_querylet(new Querylet("numeric_score {$cmp} {$score}"));
     } else {
         if (preg_match("/^upvoted_by[=|:](.*)\$/i", $event->term, $matches)) {
             $duser = User::by_name($matches[1]);
             if (is_null($duser)) {
                 throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
             }
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", array("ns_user_id" => $duser->id)));
         } else {
             if (preg_match("/^downvoted_by[=|:](.*)\$/i", $event->term, $matches)) {
                 $duser = User::by_name($matches[1]);
                 if (is_null($duser)) {
                     throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
                 }
                 $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", array("ns_user_id" => $duser->id)));
             } else {
                 if (preg_match("/^upvoted_by_id[=|:](\\d+)\$/i", $event->term, $matches)) {
                     $iid = int_escape($matches[1]);
                     $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", array("ns_user_id" => $iid)));
                 } else {
                     if (preg_match("/^downvoted_by_id[=|:](\\d+)\$/i", $event->term, $matches)) {
                         $iid = int_escape($matches[1]);
                         $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", array("ns_user_id" => $iid)));
                     } else {
                         if (preg_match("/^order[=|:](numeric_)?(score)[_]?(desc|asc)?\$/i", $event->term, $matches)) {
                             $default_order_for_column = "DESC";
                             $sort = isset($matches[3]) ? strtoupper($matches[3]) : $default_order_for_column;
                             Image::$order_sql = "images.numeric_score {$sort}";
                             $event->add_querylet(new Querylet("1=1"));
                             //small hack to avoid metatag being treated as normal tag
                         }
                     }
                 }
             }
         }
     }
 }
Esempio n. 12
0
function build_backend_subactions()
{
    global $backend_subactions, $pluginpages_handlers;
    $backend_subactions = url_action_subactions(array("_index" => url_action_alias(array("login")), "index" => url_action_alias(array("login")), "_prelude" => function (&$data, $url_now, &$url_next) {
        global $ratatoeskr_settings, $admin_grp, $ste, $languages;
        if ($admin_grp === NULL) {
            $admin_grp = Group::by_name("admins");
        }
        $ste->vars["all_languages"] = array();
        $ste->vars["all_langcodes"] = array();
        foreach ($languages as $code => $data) {
            $ste->vars["all_languages"][$code] = $data["language"];
            $ste->vars["all_langcodes"][] = $code;
        }
        ksort($ste->vars["all_languages"]);
        sort($ste->vars["all_langcodes"]);
        /* Check authentification */
        if (isset($_SESSION["ratatoeskr_uid"])) {
            try {
                $user = User::by_id($_SESSION["ratatoeskr_uid"]);
                if ($user->pwhash == $_SESSION["ratatoeskr_pwhash"] and $user->member_of($admin_grp)) {
                    if (empty($user->language)) {
                        $user->language = $ratatoeskr_settings["default_language"];
                        $user->save();
                    }
                    load_language($user->language);
                    if ($url_next[0] == "login") {
                        $url_next = array("content", "write");
                    }
                    $data["user"] = $user;
                    $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language);
                    return;
                    /* Authentification successful, continue  */
                } else {
                    unset($_SESSION["ratatoeskr_uid"]);
                }
            } catch (DoesNotExistError $e) {
                unset($_SESSION["ratatoeskr_uid"]);
            }
        }
        load_language();
        /* If we are here, user is not logged in... */
        $url_next = array("login");
    }, "login" => url_action_simple(function ($data) {
        global $ste, $admin_grp;
        if (!empty($_POST["user"])) {
            try {
                $user = User::by_name($_POST["user"]);
                if (!PasswordHash::validate($_POST["password"], $user->pwhash)) {
                    throw new Exception();
                }
                if (!$user->member_of($admin_grp)) {
                    throw new Exception();
                }
                /* Login successful. */
                $_SESSION["ratatoeskr_uid"] = $user->get_id();
                $_SESSION["ratatoeskr_pwhash"] = $user->pwhash;
                load_language($user->language);
                $data["user"] = $user;
                $ste->vars["user"] = array("id" => $user->get_id(), "name" => $user->username, "lang" => $user->language);
            } catch (Exception $e) {
                $ste->vars["login_failed"] = True;
            }
            if (isset($data["user"])) {
                throw new Redirect(array("content", "write"));
            }
        }
        echo $ste->exectemplate("/systemtemplates/backend_login.html");
    }), "logout" => url_action_simple(function ($data) {
        unset($_SESSION["ratatoeskr_uid"]);
        unset($_SESSION["ratatoeskr_pwhash"]);
        load_language();
        throw new Redirect(array("login"));
    }), "content" => url_action_subactions(array("write" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $textprocessors, $ratatoeskr_settings, $languages, $articleeditor_plugins;
        list($article, $editlang) = array_slice($url_next, 0);
        if (!isset($editlang)) {
            $editlang = $data["user"]->language;
        }
        if (isset($article)) {
            $ste->vars["article_editurl"] = urlencode($article) . "/" . urlencode($editlang);
        } else {
            $ste->vars["article_editurl"] = "";
        }
        $url_next = array();
        $default_section = Section::by_id($ratatoeskr_settings["default_section"]);
        $ste->vars["section"] = "content";
        $ste->vars["submenu"] = isset($article) ? "articles" : "newarticle";
        $ste->vars["textprocessors"] = array();
        foreach ($textprocessors as $txtproc => $properties) {
            if ($properties[1]) {
                $ste->vars["textprocessors"][] = $txtproc;
            }
        }
        $ste->vars["sections"] = array();
        foreach (Section::all() as $section) {
            $ste->vars["sections"][] = $section->name;
        }
        $ste->vars["article_section"] = $default_section->name;
        /* Check Form */
        $fail_reasons = array();
        if (isset($_POST["save_article"])) {
            if (!Article::test_urlname($_POST["urlname"])) {
                $fail_reasons[] = $translation["invalid_urlname"];
            } else {
                $inputs["urlname"] = $_POST["urlname"];
            }
            if (!Article::test_status(@$_POST["article_status"])) {
                $fail_reasons[] = $translation["invalid_article_status"];
            } else {
                $inputs["article_status"] = (int) $_POST["article_status"];
            }
            if (!isset($textprocessors[@$_POST["content_txtproc"]])) {
                $fail_reasons[] = $translation["unknown_txtproc"];
            } else {
                $inputs["content_txtproc"] = $_POST["content_txtproc"];
            }
            if (!isset($textprocessors[@$_POST["excerpt_txtproc"]])) {
                $fail_reasons[] = $translation["unknown_txtproc"];
            } else {
                $inputs["excerpt_txtproc"] = $_POST["excerpt_txtproc"];
            }
            if (!empty($_POST["date"])) {
                if (($time_tmp = @DateTime::createFromFormat("Y-m-d H:i:s", @$_POST["date"])) === False) {
                    $fail_reasons[] = $translation["invalid_date"];
                } else {
                    $inputs["date"] = @$time_tmp->getTimestamp();
                }
            } else {
                $inputs["date"] = time();
            }
            $inputs["allow_comments"] = !(empty($_POST["allow_comments"]) or $_POST["allow_comments"] != "yes");
            try {
                $inputs["article_section"] = Section::by_name($_POST["section"]);
            } catch (DoesNotExistError $e) {
                $fail_reasons[] = $translation["unknown_section"];
            }
            $inputs["title"] = $_POST["title"];
            $inputs["content"] = $_POST["content"];
            $inputs["excerpt"] = $_POST["excerpt"];
            $inputs["tags"] = array_filter(array_map("trim", explode(",", $_POST["tags"])), function ($t) {
                return !empty($t);
            });
            if (isset($_POST["saveaslang"])) {
                $editlang = $_POST["saveaslang"];
            }
        } else {
            /* Call articleeditor plugins */
            $article = empty($article) ? NULL : Article::by_urlname($article);
            foreach ($articleeditor_plugins as $plugin) {
                call_user_func($plugin["fx"], $article, False);
            }
        }
        function fill_article(&$article, $inputs, $editlang)
        {
            $article->urlname = $inputs["urlname"];
            $article->status = $inputs["article_status"];
            $article->timestamp = $inputs["date"];
            $article->title[$editlang] = new Translation($inputs["title"], "");
            $article->text[$editlang] = new Translation($inputs["content"], $inputs["content_txtproc"]);
            $article->excerpt[$editlang] = new Translation($inputs["excerpt"], $inputs["excerpt_txtproc"]);
            $article->set_tags(maketags($inputs["tags"], $editlang));
            $article->set_section($inputs["article_section"]);
            $article->allow_comments = $inputs["allow_comments"];
        }
        if (empty($article)) {
            /* New Article */
            $ste->vars["pagetitle"] = $translation["new_article"];
            if (empty($fail_reasons) and isset($_POST["save_article"])) {
                $article = Article::create($inputs["urlname"]);
                fill_article($article, $inputs, $editlang);
                /* Calling articleeditor plugins */
                $call_after_save = array();
                foreach ($articleeditor_plugins as $plugin) {
                    $result = call_user_func($plugin["fx"], $article, True);
                    if (is_string($result)) {
                        $fail_reasons[] = $result;
                    } elseif ($result !== NULL) {
                        $call_after_save[] = $result;
                    }
                }
                if (empty($fail_reasons)) {
                    try {
                        $article->save();
                        foreach ($call_after_save as $cb) {
                            call_user_func($cb, $article);
                        }
                        $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang);
                        $ste->vars["success"] = htmlesc($translation["article_save_success"]);
                    } catch (AlreadyExistsError $e) {
                        $fail_reasons[] = $translation["article_name_already_in_use"];
                    }
                }
            }
        } else {
            try {
                if (!$article instanceof Article) {
                    $article = Article::by_urlname($article);
                }
            } catch (DoesNotExistError $e) {
                throw new NotFoundError();
            }
            if (empty($fail_reasons) and isset($_POST["save_article"])) {
                fill_article($article, $inputs, $editlang);
                /* Calling articleeditor plugins */
                $call_after_save = array();
                foreach ($articleeditor_plugins as $plugin) {
                    $result = call_user_func($plugin["fx"], $article, True);
                    if (is_string($result)) {
                        $fail_reasons[] = $result;
                    } elseif ($result !== NULL) {
                        $call_after_save[] = $result;
                    }
                }
                if (empty($fail_reasons)) {
                    try {
                        $article->save();
                        foreach ($call_after_save as $cb) {
                            call_user_func($cb, $article);
                        }
                        $ste->vars["article_editurl"] = urlencode($article->urlname) . "/" . urlencode($editlang);
                        $ste->vars["success"] = htmlesc($translation["article_save_success"]);
                    } catch (AlreadyExistsError $e) {
                        $fail_reasons[] = $translation["article_name_already_in_use"];
                    }
                }
            }
            if (!isset($article->title[$editlang])) {
                $langs_available = array();
                foreach ($article->title as $lang => $_) {
                    $langs_available[] = $lang;
                }
                $editlang = $langs_available[0];
            }
            foreach (array("urlname" => "urlname", "status" => "article_status", "timestamp" => "date", "allow_comments" => "allow_comments") as $prop => $k_out) {
                if (!isset($inputs[$k_out])) {
                    $inputs[$k_out] = $article->{$prop};
                }
            }
            if (!isset($inputs["title"])) {
                $inputs["title"] = $article->title[$editlang]->text;
            }
            if (!isset($inputs["content"])) {
                $translation_obj = $article->text[$editlang];
                $inputs["content"] = $translation_obj->text;
                $inputs["content_txtproc"] = $translation_obj->texttype;
            }
            if (!isset($inputs["excerpt"])) {
                $translation_obj = $article->excerpt[$editlang];
                $inputs["excerpt"] = $translation_obj->text;
                $inputs["excerpt_txtproc"] = $translation_obj->texttype;
            }
            if (!isset($inputs["article_section"])) {
                $inputs["article_section"] = $article->get_section();
            }
            if (!isset($inputs["tags"])) {
                $inputs["tags"] = array_map(function ($tag) use($editlang) {
                    return $tag->name;
                }, $article->get_tags());
            }
            $ste->vars["morelangs"] = array();
            $ste->vars["pagetitle"] = $article->title[$editlang]->text;
            foreach ($article->title as $lang => $_) {
                if ($lang != $editlang) {
                    $ste->vars["morelangs"][] = array("url" => urlencode($article->urlname) . "/{$lang}", "full" => "({$lang}) " . $languages[$lang]["language"]);
                }
            }
        }
        if (!isset($inputs["date"])) {
            $inputs["date"] = time();
        }
        if (!isset($inputs["article_status"])) {
            $inputs["article_status"] = ARTICLE_STATUS_LIVE;
        }
        /* Push data back to template */
        if (isset($inputs["tags"])) {
            $ste->vars["tags"] = implode(", ", $inputs["tags"]);
        }
        if (isset($inputs["article_section"])) {
            $ste->vars["article_section"] = $inputs["article_section"]->name;
        }
        $ste->vars["editlang"] = $editlang;
        foreach (array("urlname" => "urlname", "article_status" => "article_status", "title" => "title", "content_txtproc" => "content_txtproc", "content" => "content", "excerpt_txtproc" => "excerpt_txtproc", "excerpt" => "excerpt", "date" => "date", "allow_comments" => "allow_comments") as $k_in => $k_out) {
            if (isset($inputs[$k_in])) {
                $ste->vars[$k_out] = $inputs[$k_in];
            }
        }
        /* Displaying article editor plugins */
        $ste->vars["displayed_plugins"] = array_map(function ($x) {
            return array("label" => $x["label"], "template" => $x["template"]);
        }, array_filter($articleeditor_plugins, function ($x) {
            return $x["display"];
        }));
        if (!empty($fail_reasons)) {
            $ste->vars["failed"] = $fail_reasons;
        }
        echo $ste->exectemplate("/systemtemplates/content_write.html");
    }, "tags" => function (&$data, $url_now, &$url_next) {
        global $translation, $languages, $ste, $rel_path_to_root;
        $url_next = array();
        $ste->vars["section"] = "content";
        $ste->vars["submenu"] = "tags";
        $ste->vars["pagetitle"] = $translation["tags_overview"];
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["tag_multiselect"] as $tagid) {
                try {
                    $tag = Tag::by_id($tagid);
                    $tag->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["tags_successfully_deleted"];
        }
        if (isset($_POST["save_changes"])) {
            $newlang = !empty($_POST["new_language"]) ? $_POST["new_language"] : NULL;
            $newtag = NULL;
            if (!empty($_POST["newtagname"])) {
                if (!Tag::test_name(@$_POST["newtagname"])) {
                    $ste->vars["error"] = $translation["invalid_tag_name"];
                } else {
                    $newtag = $_POST["newtagname"];
                }
            }
            if ($newlang !== NULL and !isset($languages[$newlang])) {
                $newlang = NULL;
            }
            if ($newtag !== NULL) {
                try {
                    $newtag = Tag::create($newtag);
                } catch (AlreadyExistsError $e) {
                    $newtag = NULL;
                }
            }
            $translations = array();
            foreach ($_POST as $k => $v) {
                if (preg_match('/tagtrans_(NEW|[a-z]{2})_(.*)/', $k, $matches) == 1) {
                    $lang = $matches[1] == "NEW" ? $newlang : $matches[1];
                    $tag = $matches[2];
                    if ($lang === NULL) {
                        continue;
                    }
                    $translations[$tag][$lang] = $v;
                }
            }
            foreach ($translations as $tag => $langmap) {
                if ($tag == "NEW") {
                    if ($newtag === NULL) {
                        continue;
                    }
                    $tag = $newtag;
                } else {
                    try {
                        $tag = Tag::by_id($tag);
                    } catch (DoesNotExistError $e) {
                        continue;
                    }
                }
                foreach ($langmap as $l => $text) {
                    if (empty($text)) {
                        unset($tag->title[$l]);
                    } else {
                        $tag->title[$l] = new Translation($text, "");
                    }
                }
                $tag->save();
            }
            $ste->vars["success"] = $translation["tags_successfully_edited"];
        }
        $ste->vars["alltags"] = array();
        $taglangs = array();
        $alltags = Tag::all();
        foreach ($alltags as $tag) {
            $transls = array();
            foreach ($tag->title as $l => $t) {
                if (!in_array($l, $taglangs)) {
                    $taglangs[] = $l;
                }
                $transls[$l] = $t->text;
            }
            $ste->vars["alltags"][] = array("id" => $tag->get_id(), "name" => $tag->name, "translations" => $transls);
        }
        $unused_langs = array_diff(array_keys($languages), $taglangs);
        $ste->vars["all_tag_langs"] = array();
        foreach ($taglangs as $l) {
            $ste->vars["all_tag_langs"][$l] = $languages[$l]["language"];
        }
        $ste->vars["unused_languages"] = array();
        foreach ($unused_langs as $l) {
            $ste->vars["unused_languages"][$l] = $languages[$l]["language"];
        }
        echo $ste->exectemplate("/systemtemplates/tags_overview.html");
    }, "articles" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        $url_next = array();
        $ste->vars["section"] = "content";
        $ste->vars["submenu"] = "articles";
        $ste->vars["pagetitle"] = $translation["menu_articles"];
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["article_multiselect"] as $article_urlname) {
                try {
                    $article = Article::by_urlname($article_urlname);
                    $article->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["articles_deleted"];
        }
        $articles = Article::all();
        /* Filtering */
        $filterquery = array();
        if (!empty($_GET["filter_urlname"])) {
            $searchfor = strtolower($_GET["filter_urlname"]);
            $articles = array_filter($articles, function ($a) use($searchfor) {
                return strpos(strtolower($a->urlname), $searchfor) !== False;
            });
            $filterquery[] = "filter_urlname=" . urlencode($_GET["filter_urlname"]);
            $ste->vars["filter_urlname"] = $_GET["filter_urlname"];
        }
        if (!empty($_GET["filter_tag"])) {
            $searchfor = $_GET["filter_tag"];
            $articles = array_filter($articles, function ($a) use($searchfor) {
                foreach ($a->get_tags() as $t) {
                    if ($t->name == $searchfor) {
                        return True;
                    }
                }
                return False;
            });
            $filterquery[] = "filter_tag=" . urlencode($searchfor);
            $ste->vars["filter_tag"] = $searchfor;
        }
        if (!empty($_GET["filter_section"])) {
            $searchfor = $_GET["filter_section"];
            $articles = array_filter($articles, function ($a) use($searchfor) {
                return $a->get_section()->name == $searchfor;
            });
            $filterquery[] = "filter_section=" . urlencode($searchfor);
            $ste->vars["filter_section"] = $searchfor;
        }
        $ste->vars["filterquery"] = implode("&", $filterquery);
        /* Sorting */
        if (isset($_GET["sort_asc"])) {
            switch ($_GET["sort_asc"]) {
                case "date":
                    $ste->vars["sortquery"] = "sort_asc=date";
                    $ste->vars["sort_asc_date"] = True;
                    $ste->vars["sorting"] = array("dir" => "asc", "by" => "date");
                    usort($articles, function ($a, $b) {
                        return intcmp($a->timestamp, $b->timestamp);
                    });
                    break;
                case "section":
                    $ste->vars["sortquery"] = "sort_asc=section";
                    $ste->vars["sort_asc_section"] = True;
                    $ste->vars["sorting"] = array("dir" => "asc", "by" => "section");
                    usort($articles, function ($a, $b) {
                        return strcmp($a->get_section()->name, $b->get_section()->name);
                    });
                    break;
                case "urlname":
                    $ste->vars["sortquery"] = "sort_asc=urlname";
                default:
                    $ste->vars["sort_asc_urlname"] = True;
                    $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname");
                    usort($articles, function ($a, $b) {
                        return strcmp($a->urlname, $b->urlname);
                    });
                    break;
            }
        } elseif (isset($_GET["sort_desc"])) {
            switch ($_GET["sort_desc"]) {
                case "date":
                    $ste->vars["sortquery"] = "sort_desc=date";
                    $ste->vars["sort_desc_date"] = True;
                    $ste->vars["sorting"] = array("dir" => "desc", "by" => "date");
                    usort($articles, function ($a, $b) {
                        return intcmp($b->timestamp, $a->timestamp);
                    });
                    break;
                case "section":
                    $ste->vars["sortquery"] = "sort_desc=section";
                    $ste->vars["sort_desc_section"] = True;
                    $ste->vars["sorting"] = array("dir" => "desc", "by" => "section");
                    usort($articles, function ($a, $b) {
                        return strcmp($b->get_section()->name, $a->get_section()->name);
                    });
                    break;
                case "urlname":
                    $ste->vars["sortquery"] = "sort_desc=urlname";
                    $ste->vars["sort_desc_urlname"] = True;
                    $ste->vars["sorting"] = array("dir" => "desc", "by" => "urlname");
                    usort($articles, function ($a, $b) {
                        return strcmp($b->urlname, $a->urlname);
                    });
                    break;
                default:
                    $ste->vars["sort_asc_urlname"] = True;
                    $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname");
                    usort($articles, function ($a, $b) {
                        return strcmp($a->urlname, $b->urlname);
                    });
                    break;
            }
        } else {
            $ste->vars["sort_asc_urlname"] = True;
            $ste->vars["sorting"] = array("dir" => "asc", "by" => "urlname");
            usort($articles, function ($a, $b) {
                return strcmp($a->urlname, $b->urlname);
            });
        }
        $ste->vars["articles"] = array_map(function ($article) {
            $avail_langs = array();
            foreach ($article->title as $lang => $_) {
                $avail_langs[] = $lang;
            }
            sort($avail_langs);
            $a_section = $article->get_section();
            return array("urlname" => $article->urlname, "languages" => $avail_langs, "date" => $article->timestamp, "tags" => array_map(function ($tag) {
                return $tag->name;
            }, $article->get_tags()), "section" => array("id" => $a_section->get_id(), "name" => $a_section->name));
        }, $articles);
        echo $ste->exectemplate("/systemtemplates/articles.html");
    }, "images" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        list($imgid, $imageaction) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "content";
        $ste->vars["submenu"] = "images";
        $ste->vars["pagetitle"] = $translation["menu_images"];
        if (!empty($imgid) and is_numeric($imgid)) {
            try {
                $image = Image::by_id($imgid);
            } catch (DoesNotExistError $e) {
                throw new NotFoundError();
            }
            if (empty($imageaction)) {
                throw new NotFoundError();
            } else {
                if ($imageaction == "markdown" or $imageaction == "html" or $imageaction == "ste") {
                    $ste->vars["pagetitle"] = $translation["generate_embed_code"];
                    $ste->vars["image_id"] = $image->get_id();
                    $ste->vars["markup_variant"] = $imageaction;
                    if (isset($_POST["img_alt"])) {
                        if ($imageaction == "markdown") {
                            $ste->vars["embed_code"] = "![" . str_replace("]", "\\]", $_POST["img_alt"]) . "](%root%/images/" . str_replace(")", "\\)", urlencode($image->get_filename())) . ")";
                        } elseif ($imageaction == "html") {
                            $ste->vars["embed_code"] = "<img src=\"%root%/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />";
                        } elseif ($imageaction == "ste") {
                            $ste->vars["embed_code"] = "<img src=\"\$rel_path_to_root/images/" . htmlesc(urlencode($image->get_filename())) . "\" alt=\"" . htmlesc($_POST["img_alt"]) . "\" />";
                        }
                    }
                    echo $ste->exectemplate("/systemtemplates/image_embed.html");
                } else {
                    throw new NotFoundError();
                }
            }
            return;
        }
        /* Upload Form */
        if (isset($_POST["upload"])) {
            try {
                $image = Image::create(!empty($_POST["upload_name"]) ? $_POST["upload_name"] : $_FILES["upload_img"]["name"], $_FILES["upload_img"]["tmp_name"]);
                $image->save();
                $ste->vars["success"] = $translation["upload_success"];
            } catch (IOError $e) {
                $ste->vars["error"] = $translation["upload_failed"];
            } catch (UnknownFileFormat $e) {
                $ste->vars["error"] = $translation["unknown_file_format"];
            }
        }
        /* Mass delete */
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["image_multiselect"] as $image_id) {
                try {
                    $image = Image::by_id($image_id);
                    $image->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["images_deleted"];
        }
        $images = Image::all();
        $ste->vars["images"] = array_map(function ($img) {
            return array("id" => $img->get_id(), "name" => $img->name, "file" => $img->get_filename());
        }, $images);
        echo $ste->exectemplate("/systemtemplates/image_list.html");
    }, "comments" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        list($comment_id) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "content";
        $ste->vars["submenu"] = "comments";
        $ste->vars["pagetitle"] = $translation["menu_comments"];
        /* Single comment? */
        if (!empty($comment_id)) {
            try {
                $comment = Comment::by_id($comment_id);
            } catch (DoesNotExistError $e) {
                throw new NotFoundError();
            }
            if (!$comment->read_by_admin) {
                $comment->read_by_admin = True;
                $comment->save();
            }
            if (isset($_POST["action_on_comment"])) {
                switch ($_POST["action_on_comment"]) {
                    case "delete":
                        $comment->delete();
                        $ste->vars["success"] = $translation["comment_successfully_deleted"];
                        goto backend_content_comments_overview;
                        break;
                    case "make_visible":
                        $comment->visible = True;
                        $comment->save();
                        $ste->vars["success"] = $translation["comment_successfully_made_visible"];
                        break;
                    case "make_invisible":
                        $comment->visible = False;
                        $comment->save();
                        $ste->vars["success"] = $translation["comment_successfully_made_invisible"];
                        break;
                }
            }
            $ste->vars["id"] = $comment->get_id();
            $ste->vars["visible"] = $comment->visible;
            $ste->vars["article"] = $comment->get_article()->urlname;
            $ste->vars["language"] = $comment->get_language();
            $ste->vars["date"] = $comment->get_timestamp();
            $ste->vars["author"] = "\"{$comment->author_name}\" <{$comment->author_mail}>";
            $ste->vars["comment_text"] = $comment->create_html();
            $ste->vars["comment_raw"] = $comment->text;
            echo $ste->exectemplate("/systemtemplates/single_comment.html");
            return;
        }
        backend_content_comments_overview:
        /* Perform an action on all selected comments */
        if (!empty($_POST["action_on_comments"])) {
            switch ($_POST["action_on_comments"]) {
                case "delete":
                    $commentaction = function ($c) {
                        $c->delete();
                    };
                    $ste->vars["success"] = $translation["comments_successfully_deleted"];
                    break;
                case "mark_read":
                    $commentaction = function ($c) {
                        $c->read_by_admin = True;
                        $c->save();
                    };
                    $ste->vars["success"] = $translation["comments_successfully_marked_read"];
                    break;
                case "mark_unread":
                    $commentaction = function ($c) {
                        $c->read_by_admin = False;
                        $c->save();
                    };
                    $ste->vars["success"] = $translation["comments_successfully_marked_unread"];
                    break;
                case "make_visible":
                    $commentaction = function ($c) {
                        $c->visible = True;
                        $c->save();
                    };
                    $ste->vars["success"] = $translation["comments_successfully_made_visible"];
                    break;
                case "make_invisible":
                    $commentaction = function ($c) {
                        $c->visible = False;
                        $c->save();
                    };
                    $ste->vars["success"] = $translation["comments_successfully_made_invisible"];
                    break;
                default:
                    $ste->vars["error"] = $translation["unknown_action"];
                    break;
            }
            if (isset($commentaction)) {
                foreach ($_POST["comment_multiselect"] as $c_id) {
                    try {
                        $comment = Comment::by_id($c_id);
                        $commentaction($comment);
                    } catch (DoesNotExistError $e) {
                        continue;
                    }
                }
            }
        }
        $comments = Comment::all();
        /* Filtering */
        $filterquery = array();
        if (!empty($_GET["filter_article"])) {
            $searchfor = strtolower($_GET["filter_article"]);
            $comments = array_filter($comments, function ($c) use($searchfor) {
                return strpos(strtolower($c->get_article()->urlname), $searchfor) !== False;
            });
            $filterquery[] = "filter_article=" . urlencode($_GET["filter_article"]);
            $ste->vars["filter_article"] = $_GET["filter_article"];
        }
        $ste->vars["filterquery"] = implode("&", $filterquery);
        /* Sorting */
        if (isset($_GET["sort_asc"])) {
            $sort_dir = 1;
            $sort_by = $_GET["sort_asc"];
        } elseif (isset($_GET["sort_desc"])) {
            $sort_dir = -1;
            $sort_by = $_GET["sort_desc"];
        } else {
            $sort_dir = 1;
            $sort_by = "was_read";
        }
        switch ($sort_by) {
            case "language":
                usort($comments, function ($a, $b) use($sort_dir) {
                    return strcmp($a->get_language(), $b->get_language()) * $sort_dir;
                });
                break;
            case "date":
                usort($comments, function ($a, $b) use($sort_dir) {
                    return intcmp($a->get_timestamp(), $b->get_timestamp()) * $sort_dir;
                });
                break;
            case "was_read":
            default:
                usort($comments, function ($a, $b) use($sort_dir) {
                    return intcmp((int) $a->read_by_admin, (int) $b->read_by_admin) * $sort_dir;
                });
                $sort_by = "was_read";
                break;
        }
        $ste->vars["sortquery"] = "sort_" . ($sort_dir == 1 ? "asc" : "desc") . "={$sort_by}";
        $ste->vars["sorting"] = array("dir" => $sort_dir == 1 ? "asc" : "desc", "by" => $sort_by);
        $ste->vars["sort_" . ($sort_dir == 1 ? "asc" : "desc") . "_{$sort_by}"] = True;
        $ste->vars["comments"] = array_map(function ($c) {
            return array("id" => $c->get_id(), "visible" => $c->visible, "read_by_admin" => $c->read_by_admin, "article" => $c->get_article()->urlname, "excerpt" => substr(str_replace(array("\r\n", "\n", "\r"), " ", $c->text), 0, 50), "language" => $c->get_language(), "date" => $c->get_timestamp(), "author" => "\"{$c->author_name}\" <{$c->author_mail}>");
        }, $comments);
        echo $ste->exectemplate("/systemtemplates/comments_list.html");
    })), "design" => url_action_subactions(array("templates" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        list($template) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "design";
        $ste->vars["submenu"] = "templates";
        $ste->vars["pagetitle"] = $translation["menu_templates"];
        if (isset($template)) {
            if (preg_match("/^[a-zA-Z0-9\\-_\\.]+\$/", $template) == 0) {
                /* Prevent a possible LFI attack. */
                throw new NotFoundError();
            }
            if (!is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$template}")) {
                throw new NotFoundError();
            }
            $ste->vars["template_name"] = $template;
            $ste->vars["template_code"] = file_get_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$template}");
        }
        /* Was there a delete request? */
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["templates_multiselect"] as $tplname) {
                if (preg_match("/^[a-zA-Z0-9\\-_\\.]+\$/", $tplname) == 0) {
                    /* Prevent a possible LFI attack. */
                    continue;
                }
                if (is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$tplname}")) {
                    @unlink(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$tplname}");
                }
            }
            $ste->vars["success"] = $translation["templates_successfully_deleted"];
        }
        /* A write request? */
        if (isset($_POST["save_template"])) {
            if (preg_match("/^[a-zA-Z0-9\\-_\\.]+\$/", $_POST["template_name"]) == 1) {
                $ste->vars["template_name"] = $_POST["template_name"];
                $ste->vars["template_code"] = $_POST["template_code"];
                try {
                    \ste\transcompile(\ste\parse(\ste\precompile($_POST["template_code"]), $_POST["template_name"]));
                    file_put_contents(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/" . $_POST["template_name"], $_POST["template_code"]);
                    $ste->vars["success"] = $translation["template_successfully_saved"];
                } catch (\ste\ParseCompileError $e) {
                    $e->rewrite($_POST["template_code"]);
                    $ste->vars["error"] = $translation["could_not_compile_template"] . $e->getMessage();
                }
            } else {
                $ste->vars["error"] = $translation["invalid_template_name"];
            }
        }
        /* Get all templates */
        $ste->vars["templates"] = array();
        $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates");
        foreach ($tpldir as $fo) {
            if ($fo->isFile()) {
                $ste->vars["templates"][] = $fo->getFilename();
            }
        }
        sort($ste->vars["templates"]);
        echo $ste->exectemplate("/systemtemplates/templates.html");
    }, "styles" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        list($style) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "design";
        $ste->vars["submenu"] = "styles";
        $ste->vars["pagetitle"] = $translation["menu_styles"];
        if (isset($style)) {
            try {
                $style = Style::by_name($style);
                $ste->vars["style_name"] = $style->name;
                $ste->vars["style_code"] = $style->code;
            } catch (DoesNotExistError $e) {
                throw new NotFoundError();
            }
        }
        /* Was there a delete request? */
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["styles_multiselect"] as $stylename) {
                try {
                    $style = Style::by_name($stylename);
                    $style->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["styles_successfully_deleted"];
        }
        /* A write request? */
        if (isset($_POST["save_style"])) {
            if (Style::test_name($_POST["style_name"])) {
                $ste->vars["style_name"] = $_POST["style_name"];
                $ste->vars["style_code"] = $_POST["style_code"];
                try {
                    $style = Style::by_name($_POST["style_name"]);
                } catch (DoesNotExistError $e) {
                    $style = Style::create($_POST["style_name"]);
                }
                $style->code = $_POST["style_code"];
                $style->save();
                $ste->vars["success"] = $translation["style_successfully_saved"];
            } else {
                $ste->vars["error"] = $translation["invalid_style_name"];
            }
        }
        /* Get all styles */
        $ste->vars["styles"] = array_map(function ($s) {
            return $s->name;
        }, Style::all());
        sort($ste->vars["styles"]);
        echo $ste->exectemplate("/systemtemplates/styles.html");
    }, "sections" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings;
        list($style) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "design";
        $ste->vars["submenu"] = "sections";
        $ste->vars["pagetitle"] = $translation["menu_pagesections"];
        /* New section? */
        if (isset($_POST["new_section"])) {
            try {
                Section::by_name($_POST["section_name"]);
                $ste->vars["error"] = $translation["section_already_exists"];
            } catch (DoesNotExistError $e) {
                if (preg_match("/^[a-zA-Z0-9\\-_\\.]+\$/", $_POST["template"]) == 0 or !is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['template']}")) {
                    $ste->vars["error"] = $translation["unknown_template"];
                } else {
                    if (!Section::test_name($_POST["section_name"])) {
                        $ste->vars["error"] = $translation["invalid_section_name"];
                    } else {
                        $section = Section::create($_POST["section_name"]);
                        $section->template = $_POST["template"];
                        $section->title[$data["user"]->language] = new Translation($_POST["section_name"], "");
                        $section->save();
                        $ste->vars["success"] = $translation["section_created_successfully"];
                    }
                }
            }
        }
        /* Remove a style? */
        if (isset($_GET["rmstyle"]) and isset($_GET["rmfrom"])) {
            try {
                $section = Section::by_name($_GET["rmfrom"]);
                $style = Style::by_name($_GET["rmstyle"]);
                $section->remove_style($style);
                $section->save();
                $ste->vars["success"] = $translation["style_removed"];
            } catch (DoesNotExistError $e) {
            }
        }
        /* Delete a section? */
        if (isset($_POST["delete"]) and @$_POST["really_delete"] == "yes" and isset($_POST["section_select"])) {
            try {
                $section = Section::by_name($_POST["section_select"]);
                if ($section->get_id() == $ratatoeskr_settings["default_section"]) {
                    $ste->vars["error"] = $translation["cannot_delete_default_section"];
                } else {
                    $default_section = Section::by_id($ratatoeskr_settings["default_section"]);
                    foreach ($section->get_articles() as $article) {
                        $article->set_section($default_section);
                        $article->save();
                    }
                    $section->delete();
                    $ste->vars["success"] = $translation["section_successfully_deleted"];
                }
            } catch (DoesNotExistError $e) {
            }
        }
        /* Make section default? */
        if (isset($_POST["make_default"]) and isset($_POST["section_select"])) {
            try {
                $section = Section::by_name($_POST["section_select"]);
                $ratatoeskr_settings["default_section"] = $section->get_id();
                $ste->vars["success"] = $translation["default_section_changed_successfully"];
            } catch (DoesNotExistError $e) {
            }
        }
        /* Set template? */
        if (isset($_POST["set_template"]) and isset($_POST["section_select"])) {
            try {
                $section = Section::by_name($_POST["section_select"]);
                if (preg_match("/^[a-zA-Z0-9\\-_\\.]+\$/", $_POST["set_template_to"]) == 0 or !is_file(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates/{$_POST['set_template_to']}")) {
                    $ste->vars["error"] = $translation["unknown_template"];
                } else {
                    $section->template = $_POST["set_template_to"];
                    $section->save();
                    $ste->vars["success"] = $translation["successfully_set_template"];
                }
            } catch (DoesNotExistError $e) {
            }
        }
        /* Adding a style? */
        if (isset($_POST["add_style"]) and isset($_POST["section_select"])) {
            try {
                $section = Section::by_name($_POST["section_select"]);
                $style = Style::by_name($_POST["style_to_add"]);
                $section->add_style($style);
                $ste->vars["success"] = $translation["successfully_added_style"];
            } catch (DoesNotExistError $e) {
            }
        }
        /* Set/unset title? */
        if (isset($_POST["set_title"]) and isset($_POST["section_select"])) {
            if (!isset($languages[$_POST["set_title_lang"]])) {
                $ste->vars["error"] = $translation["language_unknown"];
            } else {
                try {
                    $section = Section::by_name($_POST["section_select"]);
                    if (!empty($_POST["set_title_text"])) {
                        $section->title[$_POST["set_title_lang"]] = new Translation($_POST["set_title_text"], "");
                    } else {
                        if (isset($section->title[$_POST["set_title_lang"]])) {
                            unset($section->title[$_POST["set_title_lang"]]);
                        }
                    }
                    $section->save();
                    $ste->vars["success"] = $translation["successfully_set_section_title"];
                } catch (DoesNotExistError $e) {
                }
            }
        }
        /* Get all templates */
        $ste->vars["templates"] = array();
        $tpldir = new DirectoryIterator(SITE_BASE_PATH . "/ratatoeskr/templates/src/usertemplates");
        foreach ($tpldir as $fo) {
            if ($fo->isFile()) {
                $ste->vars["templates"][] = $fo->getFilename();
            }
        }
        sort($ste->vars["templates"]);
        /* Get all styles */
        $ste->vars["styles"] = array_map(function ($s) {
            return $s->name;
        }, Style::all());
        sort($ste->vars["styles"]);
        /* Get all sections */
        $sections = Section::all();
        $ste->vars["sections"] = array_map(function ($section) use($ratatoeskr_settings) {
            $titles = array();
            foreach ($section->title as $l => $t) {
                $titles[$l] = $t->text;
            }
            return array("name" => $section->name, "title" => $titles, "template" => $section->template, "styles" => array_map(function ($style) {
                return $style->name;
            }, $section->get_styles()), "default" => $section->get_id() == $ratatoeskr_settings["default_section"]);
        }, $sections);
        echo $ste->exectemplate("/systemtemplates/sections.html");
    })), "admin" => url_action_subactions(array("settings" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors;
        $url_next = array();
        $ste->vars["section"] = "admin";
        $ste->vars["submenu"] = "settings";
        $ste->vars["pagetitle"] = $translation["menu_settings"];
        $ste->vars["textprocessors"] = array();
        foreach ($textprocessors as $txtproc => $properties) {
            if ($properties[1]) {
                $ste->vars["textprocessors"][] = $txtproc;
            }
        }
        /* Toggle debugmode value? */
        if (isset($_POST["toggle_debugmode"])) {
            if (isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]) {
                $ratatoeskr_settings["debugmode"] = False;
                $ste->vars["success"] = $translation["debugmode_now_disabled"];
            } else {
                $ratatoeskr_settings["debugmode"] = True;
                $ste->vars["success"] = $translation["debugmode_now_enabled"];
            }
        }
        /* Save comment settings? */
        if (isset($_POST["save_comment_settings"])) {
            if (!in_array(@$_POST["comment_textprocessor"], $ste->vars["textprocessors"])) {
                $ste->vars["error"] = $translation["unknown_txtproc"];
            } else {
                $ratatoeskr_settings["comment_textprocessor"] = $_POST["comment_textprocessor"];
                $ratatoeskr_settings["comment_visible_default"] = (isset($_POST["comment_auto_visible"]) and $_POST["comment_auto_visible"] == "yes");
                $ste->vars["success"] = $translation["comment_settings_successfully_saved"];
            }
        }
        /* Delete language? */
        if (isset($_POST["delete"]) and $_POST["really_delete"] == "yes" and isset($_POST["language_select"])) {
            if ($ratatoeskr_settings["default_language"] == $_POST["language_select"]) {
                $ste->vars["error"] = $translation["cannot_delete_default_language"];
            } else {
                $ratatoeskr_settings["languages"] = array_filter($ratatoeskr_settings["languages"], function ($l) {
                    return $l != $_POST["language_select"];
                });
                $ste->vars["success"] = $translation["language_successfully_deleted"];
            }
        }
        /* Set default language */
        if (isset($_POST["make_default"]) and isset($_POST["language_select"])) {
            if (in_array($_POST["language_select"], $ratatoeskr_settings["languages"])) {
                $ratatoeskr_settings["default_language"] = $_POST["language_select"];
                $ste->vars["success"] = $translation["successfully_set_default_language"];
            }
        }
        /* Add a language */
        if (isset($_POST["add_language"])) {
            if (!isset($languages[$_POST["language_to_add"]])) {
                $ste->vars["error"] = $translation["language_unknown"];
            } else {
                if (!in_array($_POST["language_to_add"], $ratatoeskr_settings["languages"])) {
                    $ls = $ratatoeskr_settings["languages"];
                    $ls[] = $_POST["language_to_add"];
                    $ratatoeskr_settings["languages"] = $ls;
                }
                $ste->vars["success"] = $translation["language_successfully_added"];
            }
        }
        $ste->vars["debugmode_enabled"] = (isset($ratatoeskr_settings["debugmode"]) and $ratatoeskr_settings["debugmode"]);
        $ste->vars["comment_auto_visible"] = $ratatoeskr_settings["comment_visible_default"];
        $ste->vars["comment_textprocessor"] = $ratatoeskr_settings["comment_textprocessor"];
        $ste->vars["used_langs"] = array_map(function ($l) use($ratatoeskr_settings, $languages) {
            return array("code" => $l, "name" => $languages[$l]["language"], "default" => $l == $ratatoeskr_settings["default_language"]);
        }, $ratatoeskr_settings["languages"]);
        echo $ste->exectemplate("/systemtemplates/settings.html");
    }, "users" => url_action_subactions(array("_index" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $ratatoeskr_settings, $textprocessors;
        $url_next = array();
        $ste->vars["section"] = "admin";
        $ste->vars["submenu"] = "users";
        $ste->vars["pagetitle"] = $translation["menu_users_groups"];
        /* Add a new group? */
        if (isset($_POST["new_group"])) {
            if (empty($_POST["group_name"])) {
                $ste->vars["error"] = $translation["empty_group_name"];
            } else {
                try {
                    Group::by_name($_POST["group_name"]);
                    $ste->vars["error"] = $translation["group_already_exists"];
                } catch (DoesNotExistError $e) {
                    $group = Group::create($_POST["group_name"]);
                    $ste->vars["success"] = $translation["successfully_created_group"];
                }
            }
        }
        /* Add a new user? */
        if (isset($_POST["new_user"])) {
            if (empty($_POST["username"])) {
                $ste->vars["error"] = $translation["empty_username"];
            } else {
                try {
                    User::by_name($_POST["username"]);
                    $ste->vars["error"] = $translation["user_already_exists"];
                } catch (DoesNotExistError $e) {
                    $group = User::create($_POST["username"], PasswordHash::create($_POST["initial_password"]));
                    $ste->vars["success"] = $translation["successfully_created_user"];
                }
            }
        }
        /* Delete groups? */
        if (isset($_POST["delete_groups"]) and $_POST["really_delete"] == "yes" and !empty($_POST["groups_multiselect"])) {
            $deleted = 0;
            foreach ($_POST["groups_multiselect"] as $gid) {
                try {
                    $group = Group::by_id($gid);
                    if ($group->name == "admins") {
                        $ste->vars["error"] = $translation["cannot_delete_admin_group"];
                    } else {
                        $group->delete();
                        ++$deleted;
                    }
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            if ($deleted > 0) {
                $ste->vars["success"] = $translation["successfully_deleted_groups"];
            }
        }
        /* Delete users? */
        if (isset($_POST["delete_users"]) and $_POST["really_delete"] == "yes" and !empty($_POST["users_multiselect"])) {
            $deleted = 0;
            foreach ($_POST["users_multiselect"] as $uid) {
                if ($uid == $data["user"]->get_id()) {
                    $ste->vars["error"] = $translation["cannot_delete_yourself"];
                } else {
                    try {
                        $user = User::by_id($uid);
                        $user->delete();
                        ++$deleted;
                    } catch (DoesNotExistError $e) {
                        continue;
                    }
                }
            }
            if ($deleted > 0) {
                $ste->vars["success"] = $translation["successfully_deleted_users"];
            }
        }
        /* Get all groups */
        $ste->vars["groups"] = array_map(function ($g) {
            return array("id" => $g->get_id(), "name" => $g->name);
        }, Group::all());
        /* Get all users */
        $ste->vars["users"] = array_map(function ($u) {
            return array("id" => $u->get_id(), "name" => $u->username, "memberof" => array_map(function ($g) {
                return $g->name;
            }, $u->get_groups()), "fullname" => $u->fullname, "mail" => $u->mail);
        }, User::all());
        echo $ste->exectemplate("/systemtemplates/users.html");
    }, "u" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $admin_grp;
        try {
            $user = User::by_id($url_next[0]);
        } catch (DoesNotExistError $e) {
            throw new NotFoundError();
        }
        $url_next = array();
        $ste->vars["section"] = "admin";
        $ste->vars["submenu"] = "users";
        $ste->vars["pagetitle"] = $user->username;
        /* Modify data? */
        if (isset($_POST["change_data"])) {
            $user->fullname = $_POST["fullname"];
            $user->mail = $_POST["mail"];
            $user->language = $_POST["lang"];
            $current_groups = array_map(function ($g) {
                return $g->get_id();
            }, $user->get_groups());
            $new_groups = empty($_POST[groups_multiselect]) ? array() : $_POST["groups_multiselect"];
            $groups_exclude = array_diff($current_groups, $new_groups);
            $groups_include = array_diff($new_groups, $current_groups);
            foreach ($groups_exclude as $gid) {
                try {
                    $g = Group::by_id($gid);
                    $g->exclude_user($user);
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            foreach ($groups_include as $gid) {
                try {
                    $g = Group::by_id($gid);
                    $g->include_user($user);
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $user->save();
            $ste->vars["success"] = $translation["successfully_modified_user"];
        }
        /* New Password? */
        if (isset($_POST["new_password"])) {
            $pwhash = PasswordHash::create($_POST["password"]);
            $user->pwhash = $pwhash;
            if ($user->get_id() == $data["user"]->get_id()) {
                $_SESSION["ratatoeskr_pwhash"] = $pwhash;
            }
            $user->save();
            $ste->vars["success"] = $translation["successfully_set_new_password"];
        }
        /* Put data to STE */
        $ste->vars["u"] = array("id" => $user->get_id(), "name" => $user->username, "fullname" => $user->fullname, "mail" => $user->mail, "lang" => $user->language);
        $ste->vars["groups"] = array_map(function ($g) use($user) {
            return array("id" => $g->get_id(), "name" => $g->name, "member" => $user->member_of($g));
        }, Group::all());
        echo $ste->exectemplate("/systemtemplates/user.html");
    })), "repos" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        $url_next = array();
        $ste->vars["section"] = "admin";
        $ste->vars["submenu"] = "repos";
        $ste->vars["pagetitle"] = $translation["menu_plugin_repos"];
        /* Add a repo? */
        if (isset($_POST["add_repo"])) {
            try {
                $repo = Repository::create($_POST["repo_baseurl"]);
                $ste->vars["success"] = $translation["successfully_added_repo"];
            } catch (RepositoryUnreachableOrInvalid $e) {
                $ste->vars["error"] = $translation["repository_unreachable_or_invalid"];
            }
        }
        /* Delete repos? */
        if (isset($_POST["delete_repos"]) and $_POST["really_delete"] == "yes") {
            foreach ($_POST["repos_multiselect"] as $repo_id) {
                try {
                    $repo = Repository::by_id($repo_id);
                    $repo->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["repos_deleted"];
        }
        /* Force refresh? */
        if (isset($_POST["force_repo_refresh"])) {
            $failed = array();
            foreach ($_POST["repos_multiselect"] as $repo_id) {
                try {
                    $repo = Repository::by_id($repo_id);
                    $repo->refresh(True);
                } catch (DoesNotExistError $e) {
                    continue;
                } catch (RepositoryUnreachableOrInvalid $e) {
                    $failed[] = $repo->get_name();
                }
            }
            $ste->vars["success"] = $translation["successfully_refreshed_repos"];
            if (!empty($failed)) {
                $ste->vars["error"] = str_replace("[[REPOS]]", implode(", ", $failed), $translation["repo_refresh_failed_on"]);
            }
        }
        /* Fill data */
        $all_repos = Repository::all();
        $ste->vars["repos"] = array_map(function ($r) {
            try {
                $r->refresh();
            } catch (RepositoryUnreachableOrInvalid $e) {
            }
            return array("id" => $r->get_id(), "name" => $r->get_name(), "description" => $r->get_description(), "baseurl" => $r->get_baseurl());
        }, $all_repos);
        echo $ste->exectemplate("/systemtemplates/repos.html");
    })), "plugin" => url_action_subactions(array("list" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $plugin_objs, $api_compat;
        $url_next = array();
        $ste->vars["section"] = "plugins";
        $ste->vars["submenu"] = "pluginlist";
        $ste->vars["pagetitle"] = $translation["menu_pluginlist"];
        /* Delete plugins? */
        if (isset($_POST["delete"]) and ($_POST["really_delete"] == "yes" or $_POST["really_delete"] == "force") and !empty($_POST["plugins_multiselect"])) {
            foreach ($_POST["plugins_multiselect"] as $pid) {
                try {
                    $plugin = Plugin::by_id($pid);
                    if ($_POST["really_delete"] != "force") {
                        if (!isset($plugin_objs[$pid])) {
                            eval($plugin->code);
                            $plugin_objs[$pid] = new $plugin->classname($pid);
                        }
                        $plugin_objs[$pid]->uninstall();
                    }
                    $plugin->delete();
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation["successfully_deleted_plugins"];
        }
        /* Activate or deactivate plugins? */
        if ((isset($_POST["activate"]) or isset($_POST["deactivate"])) and !empty($_POST["plugins_multiselect"])) {
            $api_incompat = array();
            $newstatus = isset($_POST["activate"]);
            foreach ($_POST["plugins_multiselect"] as $pid) {
                try {
                    $plugin = Plugin::by_id($pid);
                    if (!$plugin->installed) {
                        continue;
                    }
                    if ($newstatus and !in_array($plugin->api, $api_compat)) {
                        $api_incompat[] = $plugin->name . ("(ID: " . $plugin->get_id() . ")");
                        continue;
                    }
                    $plugin->active = $newstatus;
                    $plugin->save();
                    if ($newstatus and !isset($plugin_objs[$pid])) {
                        eval($plugin->code);
                        $plugin_objs[$pid] = new $plugin->classname($pid);
                        $plugin_objs[$pid]->init();
                    }
                } catch (DoesNotExistError $e) {
                    continue;
                }
            }
            $ste->vars["success"] = $translation[$newstatus ? "plugins_activated" : "plugins_deactivated"];
            if (!empty($api_incompat)) {
                $ste->vars["error"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["could_not_activate_plugin_api_incompat"]));
            }
        }
        $stream_ctx = stream_context_create(array("http" => array("timeout" => 5)));
        /* Update plugins? */
        if (isset($_POST["update"]) and !empty($_POST["plugins_multiselect"])) {
            $updated = array();
            foreach ($_POST["plugins_multiselect"] as $pid) {
                try {
                    $plugin = Plugin::by_id($pid);
                    if (!empty($plugin->updatepath)) {
                        $update_info = @unserialize(@file_get_contents($plugin->updatepath, False, $stream_ctx));
                        if (is_array($update_info) and $update_info["current-version"] + 0 > $plugin->versioncount + 0) {
                            $pkg = PluginPackage::load(@file_get_contents($update_info["dl-path"], False, $stream_ctx));
                            $plugin->fill_from_pluginpackage($pkg);
                            $plugin->update = True;
                            $plugin->save();
                            $updated[] = $plugin->name;
                        }
                    }
                } catch (DoesNotExistError $e) {
                    continue;
                } catch (InvalidPackage $e) {
                    continue;
                }
            }
            if (empty($updated)) {
                $ste->vars["success"] = $translation["nothing_to_update"];
            } else {
                $ste->vars["success"] = str_replace("[[PLUGINS]]", implode(", ", $updated), $translation["successfully_updated_plugins"]);
            }
        }
        /* Load plugin data */
        $all_plugins = Plugin::all();
        $ste->vars["plugins"] = array();
        $api_incompat = array();
        foreach ($all_plugins as $p) {
            if (!$p->installed) {
                continue;
            }
            if (!in_array($p->api, $api_compat)) {
                $api_incompat[] = $p->name . ("(ID: " . $p->get_id() . ")");
            }
            $ste->vars["plugins"][] = array("id" => $p->get_id(), "name" => $p->name, "versiontext" => $p->versiontext, "active" => $p->active, "description" => $p->short_description, "web" => $p->web, "author" => $p->author, "help" => !empty($p->help));
        }
        if (!empty($api_incompat)) {
            $ste->vars["notice"] = htmlesc(str_replace("[[PLUGINS]]", implode(", ", $api_incompat), $translation["plugins_incompat"]));
        }
        echo $ste->exectemplate("/systemtemplates/pluginlist.html");
    }, "help" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        try {
            $plugin = Plugin::by_id($url_next[0]);
            if (empty($plugin->help)) {
                throw new NotFoundError();
            }
        } catch (DoesNotExistError $e) {
            throw new NotFoundError();
        }
        $url_next = array();
        $ste->vars["section"] = "plugins";
        $ste->vars["submenu"] = "";
        $ste->vars["pagetitle"] = $plugin->name;
        $ste->vars["help"] = $plugin->help;
        echo $ste->exectemplate("/systemtemplates/pluginhelp.html");
    }, "install" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root, $api_compat;
        $url_next = array();
        $ste->vars["section"] = "plugins";
        $ste->vars["submenu"] = "installplugins";
        $ste->vars["pagetitle"] = $translation["menu_plugininstall"];
        $all_repos = Repository::all();
        foreach ($all_repos as $repo) {
            try {
                $repo->refresh();
            } catch (RepositoryUnreachableOrInvalid $e) {
                continue;
            }
        }
        if (isset($_POST["installpackage"])) {
            if (is_uploaded_file($_FILES["pluginpackage"]["tmp_name"])) {
                try {
                    $package = PluginPackage::load(file_get_contents($_FILES["pluginpackage"]["tmp_name"]));
                    unlink($_FILES["pluginpackage"]["tmp_name"]);
                    if (in_array($package->api, $api_compat)) {
                        $plugin = Plugin::create();
                        $plugin->fill_from_pluginpackage($package);
                        $plugin->installed = False;
                        $plugin->active = False;
                        $plugin->save();
                        $url_next = array("confirminstall", (string) $plugin->get_id());
                        return;
                    } else {
                        $ste->vars["error"] = str_replace("[[API]]", $package->api, $translation["incompatible_plugin"]);
                    }
                } catch (InvalidPackage $e) {
                    $ste->vars["error"] = $translation["invalid_package"];
                    unlink($_FILES["pluginpackage"]["tmp_name"]);
                }
            } else {
                $ste->vars["error"] = $translation["upload_failed"];
            }
        }
        if (isset($_POST["search_in_repos"])) {
            $ste->vars["searchresults"] = array();
            $repos_to_scan = $_POST["searchin"] == "*" ? $all_repos : Repository::by_id($_POST["searchin"]);
            $searchfor = strtolower($_POST["searchfor"]);
            foreach ($repos_to_scan as $repo) {
                foreach ($repo->packages as $pkg) {
                    if (empty($searchfor) or strpos(strtolower($pkg[0]), $searchfor) !== False or strpos(strtolower($pkg[2]), $searchfor) !== False) {
                        $ste->vars["searchresults"][] = array("name" => $pkg[0], "description" => $pkg[2], "reponame" => $repo->get_name(), "repoid" => $repo->get_id());
                    }
                }
            }
        }
        $ste->vars["repos"] = array_map(function ($r) {
            return array("id" => $r->get_id(), "name" => $r->get_name());
        }, $all_repos);
        echo $ste->exectemplate("/systemtemplates/plugininstall.html");
    }, "repoinstall" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $rel_path_to_root;
        $stream_ctx = stream_context_create(array("http" => array("timeout" => 5)));
        try {
            $repo = Repository::by_id($_GET["repo"]);
            $pkg = $repo->download_package($_GET["pkg"]);
            $plugin = Plugin::create();
            $plugin->fill_from_pluginpackage($pkg);
            $plugin->installed = False;
            $plugin->active = False;
            $plugin->save();
            $url_next = array("confirminstall", (string) $plugin->get_id());
        } catch (DoesNotExistError $e) {
            $ste->vars["error"] = $translation["package_or_repo_not_found"];
            $url_next = array("install");
        } catch (InvalidPackage $e) {
            $ste->vars["error"] = $translation["invalid_package"];
            $url_next = array("install");
        }
    }, "confirminstall" => function (&$data, $url_now, &$url_next) {
        global $ste, $translation, $languages, $rel_path_to_root;
        list($plugin_id) = $url_next;
        $url_next = array();
        $ste->vars["section"] = "plugins";
        $ste->vars["submenu"] = "installplugins";
        $ste->vars["pagetitle"] = $translation["menu_plugininstall"];
        try {
            $plugin = Plugin::by_id($plugin_id);
        } catch (DoesNotExistError $e) {
            throw new NotFoundError();
        }
        if ($plugin->installed) {
            throw new NotFoundError();
        }
        $ste->vars["plugin_id"] = $plugin->get_id();
        $ste->vars["name"] = $plugin->name;
        $ste->vars["description"] = $plugin->short_description;
        $ste->vars["code"] = $plugin->code;
        $ste->vars["license"] = $plugin->license;
        if (isset($_POST["yes"])) {
            $plugin->installed = True;
            $plugin->save();
            eval($plugin->code);
            $plugin_instance = new $plugin->classname($plugin->get_id());
            $plugin_instance->install();
            $ste->vars["success"] = $translation["plugin_installed_successfully"];
            $url_next = array("list");
            return;
        }
        if (isset($_POST["no"])) {
            $plugin->delete();
            $url_next = array("install");
            return;
        }
        echo $ste->exectemplate("/systemtemplates/confirminstall.html");
    })), "pluginpages" => url_action_subactions($pluginpages_handlers)));
}
Esempio n. 13
0
 protected function log_in_as_user()
 {
     global $user;
     $user = User::by_name('test');
     $this->assertNotNull($user);
 }
Esempio n. 14
0
 public function onSearchTermParse(Event $event)
 {
     global $user;
     $matches = array();
     if (preg_match("/^(poster|user)=(.*)\$/i", $event->term, $matches)) {
         $user = User::by_name($matches[2]);
         if (!is_null($user)) {
             $user_id = $user->id;
         } else {
             $user_id = -1;
         }
         $event->add_querylet(new Querylet("images.owner_id = {$user_id}"));
     } else {
         if (preg_match("/^(poster|user)_id=([0-9]+)\$/i", $event->term, $matches)) {
             $user_id = int_escape($matches[2]);
             $event->add_querylet(new Querylet("images.owner_id = {$user_id}"));
         } else {
             if ($user->is_admin() && preg_match("/^(poster|user)_ip=([0-9\\.]+)\$/i", $event->term, $matches)) {
                 $user_ip = $matches[2];
                 // FIXME: ip_escape?
                 $event->add_querylet(new Querylet("images.owner_ip = '{$user_ip}'"));
             }
         }
     }
 }
Esempio n. 15
0
 public function receive_event(Event $event)
 {
     global $config, $database, $page, $user;
     if (is_null($this->theme)) {
         $this->theme = get_theme_object($this);
     }
     if ($event instanceof InitExtEvent) {
         if ($config->get_int("ext_numeric_score_version", 0) < 1) {
             $this->install();
         }
     }
     if ($event instanceof DisplayingImageEvent) {
         if (!$user->is_anonymous()) {
             $html = $this->theme->get_voter_html($event->image);
             $page->add_block(new Block("Image Score", $html, "left", 20));
         }
     }
     if ($event instanceof PageRequestEvent && $event->page_matches("numeric_score_vote")) {
         if (!$user->is_anonymous()) {
             $image_id = int_escape($_POST['image_id']);
             $char = $_POST['vote'];
             $score = 0;
             if ($char == "up") {
                 $score = 1;
             } else {
                 if ($char == "down") {
                     $score = -1;
                 }
             }
             if ($score != 0) {
                 send_event(new NumericScoreSetEvent($image_id, $user, $score));
             }
             $page->set_mode("redirect");
             $page->set_redirect(make_link("post/view/{$image_id}"));
         }
     }
     if ($event instanceof NumericScoreSetEvent) {
         $this->add_vote($event->image_id, $user->id, $event->score);
     }
     if ($event instanceof ImageDeletionEvent) {
         $database->execute("DELETE FROM numeric_score_votes WHERE image_id=?", array($event->image->id));
     }
     if ($event instanceof ParseLinkTemplateEvent) {
         $event->replace('$score', $event->image->numeric_score);
     }
     if ($event instanceof SearchTermParseEvent) {
         $matches = array();
         if (preg_match("/^score(<|<=|=|>=|>)(\\d+)\$/", $event->term, $matches)) {
             $cmp = $matches[1];
             $score = $matches[2];
             $event->add_querylet(new Querylet("numeric_score {$cmp} {$score}"));
         }
         if (preg_match("/^upvoted_by=(.*)\$/", $event->term, $matches)) {
             $duser = User::by_name($matches[1]);
             if (is_null($duser)) {
                 throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
             }
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=1)", array($duser->id)));
         }
         if (preg_match("/^downvoted_by=(.*)\$/", $event->term, $matches)) {
             $duser = User::by_name($matches[1]);
             if (is_null($duser)) {
                 throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
             }
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=-1)", array($duser->id)));
         }
     }
 }
Esempio n. 16
0
 public function receive_event(Event $event)
 {
     global $config, $database, $page, $user;
     if (is_null($this->theme)) {
         $this->theme = get_theme_object($this);
     }
     if ($event instanceof InitExtEvent) {
         if ($config->get_int("ext_numeric_score_version", 0) < 1) {
             $this->install();
         }
     }
     if ($event instanceof DisplayingImageEvent) {
         if (!$user->is_anonymous()) {
             $html = $this->theme->get_voter_html($event->image);
             $page->add_block(new Block("Image Score", $html, "left", 20));
         }
     }
     if ($event instanceof UserPageBuildingEvent) {
         $html = $this->theme->get_nuller_html($event->display_user);
         $page->add_block(new Block("Votes", $html, "main", 60));
     }
     if ($event instanceof PageRequestEvent) {
         if ($event->page_matches("numeric_score_votes")) {
             $image_id = int_escape($event->get_arg(0));
             $x = $database->get_all("SELECT users.name as username, user_id, score \n\t\t\t\t\tFROM numeric_score_votes \n\t\t\t\t\tJOIN users ON numeric_score_votes.user_id=users.id\n\t\t\t\t\tWHERE image_id=?", array($image_id));
             $html = "<table>";
             foreach ($x as $vote) {
                 $html .= "<tr><td>";
                 $html .= "<a href='/user/{$vote['username']}'>{$vote['username']}</a>";
                 $html .= "</td><td>";
                 $html .= $vote['score'];
                 $html .= "</td></tr>";
             }
             die($html);
         }
         if ($event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
             if (!$user->is_anonymous()) {
                 $image_id = int_escape($_POST['image_id']);
                 $char = $_POST['vote'];
                 $score = null;
                 if ($char == "up") {
                     $score = 1;
                 } else {
                     if ($char == "null") {
                         $score = 0;
                     } else {
                         if ($char == "down") {
                             $score = -1;
                         }
                     }
                 }
                 if (!is_null($score) && $image_id > 0) {
                     send_event(new NumericScoreSetEvent($image_id, $user, $score));
                 }
                 $page->set_mode("redirect");
                 $page->set_redirect(make_link("post/view/{$image_id}"));
             }
         }
         if ($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
             if ($user->is_admin()) {
                 $image_id = int_escape($_POST['image_id']);
                 $database->execute("DELETE FROM numeric_score_votes WHERE image_id=?", array($image_id));
                 $database->execute("UPDATE images SET numeric_score=0 WHERE id=?", array($image_id));
                 $page->set_mode("redirect");
                 $page->set_redirect(make_link("post/view/{$image_id}"));
             }
         }
         if ($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
             if ($user->is_admin()) {
                 $user_id = int_escape($_POST['user_id']);
                 $image_ids = $database->get_col("SELECT image_id FROM numeric_score_votes WHERE user_id=?", array($user_id));
                 $database->execute("DELETE FROM numeric_score_votes WHERE user_id=? AND image_id IN ?", array($user_id, $image_ids));
                 $database->execute("UPDATE images SET numeric_score=(SELECT SUM(score) FROM numeric_score_votes WHERE image_id=images.id) WHERE images.id IN ?", array($image_ids));
                 $page->set_mode("redirect");
                 $page->set_redirect(make_link());
             }
         }
     }
     if ($event instanceof NumericScoreSetEvent) {
         log_info("numeric_score", "Rated Image #{$event->image_id} as {$event->score}");
         $this->add_vote($event->image_id, $user->id, $event->score);
     }
     if ($event instanceof ImageDeletionEvent) {
         $database->execute("DELETE FROM numeric_score_votes WHERE image_id=?", array($event->image->id));
     }
     if ($event instanceof ParseLinkTemplateEvent) {
         $event->replace('$score', $event->image->numeric_score);
     }
     if ($event instanceof SearchTermParseEvent) {
         $matches = array();
         if (preg_match("/^score(<|<=|=|>=|>)(\\d+)\$/", $event->term, $matches)) {
             $cmp = $matches[1];
             $score = $matches[2];
             $event->add_querylet(new Querylet("numeric_score {$cmp} {$score}"));
         }
         if (preg_match("/^upvoted_by=(.*)\$/", $event->term, $matches)) {
             $duser = User::by_name($matches[1]);
             if (is_null($duser)) {
                 throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
             }
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=1)", array($duser->id)));
         }
         if (preg_match("/^downvoted_by=(.*)\$/", $event->term, $matches)) {
             $duser = User::by_name($matches[1]);
             if (is_null($duser)) {
                 throw new SearchTermParseException("Can't find the user named " . html_escape($matches[1]));
             }
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=-1)", array($duser->id)));
         }
         if (preg_match("/^upvoted_by_id=(\\d+)\$/", $event->term, $matches)) {
             $iid = int_escape($matches[1]);
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=1)", array($iid)));
         }
         if (preg_match("/^downvoted_by_id=(\\d+)\$/", $event->term, $matches)) {
             $iid = int_escape($matches[1]);
             $event->add_querylet(new Querylet("images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=? AND score=-1)", array($iid)));
         }
     }
 }
Esempio n. 17
0
 public function onSearchTermParse($event)
 {
     $matches = array();
     if (preg_match("/favorites(<|>|<=|>=|=)(\\d+)/", $event->term, $matches)) {
         $cmp = $matches[1];
         $favorites = $matches[2];
         $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites {$cmp} {$favorites})"));
     } else {
         if (preg_match("/favorited_by=(.*)/i", $event->term, $matches)) {
             global $database;
             $user = User::by_name($matches[1]);
             if (!is_null($user)) {
                 $user_id = $user->id;
             } else {
                 $user_id = -1;
             }
             $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = {$user_id})"));
         } else {
             if (preg_match("/favorited_by_userno=([0-9]+)/i", $event->term, $matches)) {
                 $user_id = int_escape($matches[1]);
                 $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM user_favorites WHERE user_id = {$user_id})"));
             }
         }
     }
 }
Esempio n. 18
0
 /**
  * @param string[] $args
  */
 public function __construct($args)
 {
     global $user;
     $opts = array();
     $log_level = SCORE_LOG_WARNING;
     $arg_count = count($args);
     for ($i = 1; $i < $arg_count; $i++) {
         switch ($args[$i]) {
             case '-u':
                 $user = User::by_name($args[++$i]);
                 if (is_null($user)) {
                     die("Unknown user");
                 }
                 break;
             case '-q':
                 $log_level += 10;
                 break;
             case '-v':
                 $log_level -= 10;
                 break;
             default:
                 $opts[] = $args[$i];
                 break;
         }
     }
     define("CLI_LOG_LEVEL", $log_level);
     if (count($opts) > 0) {
         $this->cmd = $opts[0];
         $this->args = array_slice($opts, 1);
     } else {
         print "\n";
         print "Usage: php {$args[0]} [flags] [command]\n";
         print "\n";
         print "Flags:\n";
         print "  -u [username]\n";
         print "    Log in as the specified user\n";
         print "  -q / -v\n";
         print "    Be quieter / more verbose\n";
         print "    Scale is debug - info - warning - error - critical\n";
         print "    Default is to show warnings and above\n";
         print "    \n";
         print "Currently known commands:\n";
     }
 }
Esempio n. 19
0
     $settings["repo_baseurl"] = $_POST["repo_baseurl"];
     if ($_POST["repo_mode"] == "public") {
         $settings["repo_mode"] = "public";
     }
     if ($_POST["repo_mode"] == "private") {
         $settings["repo_mode"] = "private";
     }
     update_repometa();
     $ste->vars["success"] = "Settings saved.";
 }
 if (isset($_POST["new_user"])) {
     if (empty($_POST["username"]) or empty($_POST["password"])) {
         $ste->vars["error"] = "Formular not filled out.";
     } else {
         try {
             $u = User::by_name($_POST["username"]);
             $ste->vars["error"] = "Username already exists.";
         } catch (DoesNotExistError $e) {
             $u = User::create($_POST["username"]);
             $u->isadmin = False;
             $u->pwhash = PasswordHash::create($_POST["password"]);
             $u->save();
             $ste->vars["success"] = "Account successfully created.";
         }
     }
 }
 if (isset($_POST["delete_users"]) and $_POST["really_delete"] == "yes") {
     foreach ($_POST["users_multiselect"] as $uid) {
         try {
             $u = User::by_id($uid);
             $u->delete();