|
- <?php
- /**
- * Class: Admin Controller
- * The logic behind the Admin area.
- */
- class AdminController {
- # Boolean: $displayed
- # Has anything been displayed?
- public $displayed = false;
-
- # Array: $context
- # Contains the context for various admin pages, to be passed to the Twig templates.
- public $context = array();
-
- # String: $selected_bookmarklet
- # Holds the name of the Feather to be selected when they open the bookmarklet.
- public $selected_bookmarklet;
-
- # String: $base
- # The base path for this controller.
- public $base = "admin";
-
- # Boolean: $feed
- # Is the current page a feed?
- public $feed = false;
-
- /**
- * Function: __construct
- * Prepares Twig.
- */
- private function __construct() {
- $this->admin_theme = fallback($_SESSION['admin_theme'], "default");
-
- $this->theme = new Twig_Loader(MAIN_DIR."/admin/themes/".$this->admin_theme,
- (is_writable(INCLUDES_DIR."/caches") and !DEBUG) ?
- INCLUDES_DIR."/caches" :
- null);
-
- $this->default = new Twig_Loader(MAIN_DIR."/admin/themes/default",
- (is_writable(INCLUDES_DIR."/caches") and !DEBUG) ?
- INCLUDES_DIR."/caches" :
- null);
- }
-
- /**
- * Function: parse
- * Determines the action.
- */
- public function parse($route) {
- $visitor = Visitor::current();
-
- # Protect non-responder functions.
- if (in_array($route->action, array("__construct", "parse", "subnav_context", "display", "current")))
- show_404();
-
- if (empty($route->action) or $route->action == "write") {
- # "Write > Post", if they can add posts or drafts.
- if (($visitor->group->can("add_post") or $visitor->group->can("add_draft")) and
- !empty(Config::current()->enabled_feathers))
- return $route->action = "write_post";
-
- # "Write > Page", if they can add pages.
- if ($visitor->group->can("add_page"))
- return $route->action = "write_page";
- }
-
- if (empty($route->action) or $route->action == "manage") {
- # "Manage > Posts", if they can manage any posts.
- if (Post::any_editable() or Post::any_deletable())
- return $route->action = "manage_posts";
-
- # "Manage > Pages", if they can manage pages.
- if ($visitor->group->can("edit_page") or $visitor->group->can("delete_page"))
- return $route->action = "manage_pages";
-
- # "Manage > Users", if they can manage users.
- if ($visitor->group->can("edit_user") or $visitor->group->can("delete_user"))
- return $route->action = "manage_users";
-
- # "Manage > Groups", if they can manage groups.
- if ($visitor->group->can("edit_group") or $visitor->group->can("delete_group"))
- return $route->action = "manage_groups";
- }
-
- if (empty($route->action) or $route->action == "settings") {
- # "General Settings", if they can configure the installation.
- if ($visitor->group->can("change_settings"))
- return $route->action = "general_settings";
- }
-
- if (empty($route->action) or $route->action == "extend") {
- # "Modules", if they can configure the installation.
- if ($visitor->group->can("toggle_extensions"))
- return $route->action = "modules";
- }
-
- Trigger::current()->filter($route->action, "admin_determine_action");
-
- if (!isset($route->action))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to view this area."));
- }
-
- /**
- * Function: write
- * Post writing.
- */
- public function write_post() {
- $visitor = Visitor::current();
-
- if (!$visitor->group->can("add_post", "add_draft"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts."));
-
- $config = Config::current();
-
- if (empty($config->enabled_feathers))
- error(__("No Feathers"), __("Please install a feather or two in order to add a post."));
-
- Trigger::current()->filter($options, array("write_post_options", "post_options"));
-
- fallback($_GET['feather'], reset($config->enabled_feathers));
-
- $this->display("write_post",
- array("groups" => Group::find(array("order" => "id ASC")),
- "options" => $options,
- "feathers" => Feathers::$instances,
- "feather" => Feathers::$instances[$_GET['feather']]));
- }
-
- /**
- * Function: bookmarklet
- * Post writing, from the bookmarklet.
- */
- public function bookmarklet() {
- $visitor = Visitor::current();
- if (!$visitor->group->can("add_post", "add_draft"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts."));
-
- $config = Config::current();
-
- if (empty($config->enabled_feathers))
- error(__("No Feathers"), __("Please install a feather or two in order to add a post."));
-
- if (!isset($this->selected_bookmarklet))
- fallback($feather, $config->enabled_feathers[0]);
- else
- $feather = $this->selected_bookmarklet;
-
- fallback($_GET['url']);
- fallback($_GET['title']);
- fallback($_GET['selection']);
-
- $this->display("bookmarklet",
- array("done" => isset($_GET['done']),
- "feathers" => Feathers::$instances,
- "selected_feather" => Feathers::$instances[$feather],
- "args" => array("url" => stripslashes($_GET['url']),
- "page_url" => stripslashes($_GET['url']),
- "page_link" => '(via <a href="'.stripslashes($_GET['url']).'">'.$_GET['title'].'</a>)',
- "title" => stripslashes($_GET['title']),
- "page_title" => stripslashes($_GET['title']),
- "selection" => stripslashes($_GET['selection']))));
- }
-
- /**
- * Function: add_post
- * Adds a post when the form is submitted.
- */
- public function add_post() {
- $visitor = Visitor::current();
- if (!$visitor->group->can("add_post", "add_draft"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create posts."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- if (!isset($_POST['draft']) and !$visitor->group->can("add_post"))
- $_POST['draft'] = 'true';
-
- $post = Feathers::$instances[$_POST['feather']]->submit();
-
- if (!$post->redirect)
- $post->redirect = "/admin/?action=write_post";
-
- if (!isset($_POST['bookmarklet']))
- Flash::notice(__("Post created!"), $post->redirect);
- else
- redirect($post->redirect);
- }
-
- /**
- * Function: edit_post
- * Post editing.
- */
- public function edit_post() {
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to edit a post."));
-
- $post = new Post($_GET['id'], array("drafts" => true, "filter" => false));
-
- if (!$post->editable())
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post."));
-
- Trigger::current()->filter($options, array("edit_post_options", "post_options"), $post);
-
- $this->display("edit_post",
- array("post" => $post,
- "groups" => Group::find(array("order" => "id ASC")),
- "options" => $options,
- "feather" => Feathers::$instances[$post->feather]));
- }
-
- /**
- * Function: update_post
- * Updates a post when the form is submitted.
- */
- public function update_post() {
- $post = new Post($_POST['id'], array("drafts" => true));
-
- if ($post->no_results)
- Flash::warning(__("Post not found."), "/admin/?action=manage_posts");
-
- if (!$post->editable())
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- Feathers::$instances[$post->feather]->update($post);
-
- if (!isset($_POST['ajax']))
- Flash::notice(_f("Post updated. <a href=\"%s\">View Post →</a>",
- array($post->url())),
- "/admin/?action=manage_posts");
- else
- exit((string) $_POST['id']);
- }
-
- /**
- * Function: delete_post
- * Post deletion (confirm page).
- */
- public function delete_post() {
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to delete a post."));
-
- $post = new Post($_GET['id'], array("drafts" => true));
-
- if (!$post->deletable())
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete this post."));
-
- $this->display("delete_post", array("post" => $post));
- }
-
- /**
- * Function: destroy_post
- * Destroys a post (the real deal).
- */
- public function destroy_post() {
- if (empty($_POST['id']))
- error(__("No ID Specified"), __("An ID is required to delete a post."));
-
- if ($_POST['destroy'] == "bollocks")
- redirect("/admin/?action=manage_posts");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $post = new Post($_POST['id'], array("drafts" => true));
- if (!$post->deletable())
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete this post."));
-
- Post::delete($_POST['id']);
-
- Flash::notice(__("Post deleted."), "/admin/?action=manage_posts");
- }
-
- /**
- * Function: manage_posts
- * Post managing.
- */
- public function manage_posts() {
- if (!Post::any_editable() and !Post::any_deletable())
- show_403(__("Access Denied"), __("You do not have sufficient privileges to manage any posts."));
-
- fallback($_GET['query'], "");
-
- list($where, $params) = keywords($_GET['query'], "post_attributes.value LIKE :query OR url LIKE :query", "post_attributes");
-
- if (!empty($_GET['month']))
- $where["created_at like"] = $_GET['month']."-%";
-
- $visitor = Visitor::current();
- if (!$visitor->group->can("view_draft", "edit_draft", "edit_post", "delete_draft", "delete_post"))
- $where["user_id"] = $visitor->id;
-
- $results = Post::find(array("placeholders" => true,
- "drafts" => true,
- "where" => $where,
- "params" => $params));
-
- $ids = array();
- foreach ($results[0] as $result)
- $ids[] = $result["id"];
-
- if (!empty($ids))
- $posts = new Paginator(Post::find(array("placeholders" => true,
- "drafts" => true,
- "where" => array("id" => $ids))),
- 25);
- else
- $posts = new Paginator(array());
-
- foreach ($posts->paginated as &$post) {
- if (preg_match_all("/\{([0-9]+)\}/", $post->status, $matches)) {
- $groups = array();
- $groupClasses = array();
-
- foreach ($matches[1] as $id) {
- $group = new Group($id);
- $groups[] = "<span class=\"group_prefix\">Group:</span> ".$group->name;
- $groupClasses[] = "group-".$id;
- }
-
- $post->status_name = join(", ", $groups);
- $post->status_class = join(" ", $groupClasses);
- } else {
- $post->status_name = camelize($post->status, true);
- $post->status_class = $post->status;
- }
- }
-
- $this->display("manage_posts", array("posts" => $posts));
- }
-
- /**
- * Function: write_page
- * Page creation.
- */
- public function write_page() {
- if (!Visitor::current()->group->can("add_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create pages."));
-
- $this->display("write_page", array("pages" => Page::find()));
- }
-
- /**
- * Function: add_page
- * Adds a page when the form is submitted.
- */
- public function add_page() {
- if (!Visitor::current()->group->can("add_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create pages."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- if (empty($_POST['title']) and empty($_POST['slug']))
- error(__("Error"), __("Title and slug cannot be blank."));
-
- $page = Page::add($_POST['title'],
- $_POST['body'],
- null,
- $_POST['parent_id'],
- !empty($_POST['show_in_list']),
- 0,
- (!empty($_POST['slug']) ? $_POST['slug'] : sanitize($_POST['title'])));
-
- Flash::notice(__("Page created!"), $page->url());
- }
-
- /**
- * Function: edit_page
- * Page editing.
- */
- public function edit_page() {
- if (!Visitor::current()->group->can("edit_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this page."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to edit a page."));
-
- $this->display("edit_page",
- array("page" => new Page($_GET['id'], array("filter" => false)),
- "pages" => Page::find(array("where" => array("id not" => $_GET['id'])))));
- }
-
- /**
- * Function: update_page
- * Updates a page when the form is submitted.
- */
- public function update_page() {
- if (!Visitor::current()->group->can("edit_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit pages."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- if (empty($_POST['title']) and empty($_POST['slug']))
- error(__("Error"), __("Title and slug cannot be blank."));
-
- $page = new Page($_POST['id']);
-
- if ($page->no_results)
- Flash::warning(__("Page not found."), "/admin/?action=manage_pages");
-
- $page->update($_POST['title'], $_POST['body'], null, $_POST['parent_id'], !empty($_POST['show_in_list']), $page->list_order, null, $_POST['slug']);
-
- if (!isset($_POST['ajax']))
- Flash::notice(_f("Page updated. <a href=\"%s\">View Page →</a>",
- array($page->url())),
- "/admin/?action=manage_pages");
- }
-
- /**
- * Function: reorder_pages
- * Reorders pages.
- */
- public function reorder_pages() {
- foreach ($_POST['list_order'] as $id => $order) {
- $page = new Page($id);
- $page->update($page->title, $page->body, null, $page->parent_id, $page->show_in_list, $order, null, $page->url);
- }
-
- Flash::notice(__("Pages reordered."), "/admin/?action=manage_pages");
- }
-
- /**
- * Function: delete_page
- * Page deletion (confirm page).
- */
- public function delete_page() {
- if (!Visitor::current()->group->can("delete_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete pages."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to delete a page."));
-
- $this->display("delete_page", array("page" => new Page($_GET['id'])));
- }
-
- /**
- * Function: destroy_page
- * Destroys a page.
- */
- public function destroy_page() {
- if (!Visitor::current()->group->can("delete_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete pages."));
-
- if (empty($_POST['id']))
- error(__("No ID Specified"), __("An ID is required to delete a post."));
-
- if ($_POST['destroy'] == "bollocks")
- redirect("/admin/?action=manage_pages");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $page = new Page($_POST['id']);
-
- if (!$page->no_results)
- foreach ($page->children as $child)
- if (isset($_POST['destroy_children']))
- Page::delete($child->id, true);
- else
- $child->update($child->title, $child->body, 0, $child->show_in_list, $child->list_order, $child->url);
-
- Page::delete($_POST['id']);
-
- Flash::notice(__("Page deleted."), "/admin/?action=manage_pages");
- }
-
- /**
- * Function: manage_pages
- * Page managing.
- */
- public function manage_pages() {
- $visitor = Visitor::current();
- if (!$visitor->group->can("edit_page") and !$visitor->group->can("delete_page"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to manage pages."));
-
- fallback($_GET['query'], "");
- list($where, $params) = keywords($_GET['query'], "title LIKE :query OR body LIKE :query", "pages");
-
- $this->display("manage_pages",
- array("pages" => new Paginator(Page::find(array("placeholders" => true,
- "where" => $where,
- "params" => $params)), 25)));
- }
-
- /**
- * Function: new_user
- * User creation.
- */
- public function new_user() {
- if (!Visitor::current()->group->can("add_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to add users."));
-
- $config = Config::current();
-
- $this->display("new_user",
- array("default_group" => new Group($config->default_group),
- "groups" => Group::find(array("where" => array("id not" => array($config->guest_group,
- $config->default_group)),
- "order" => "id DESC"))));
- }
-
- /**
- * Function: add_user
- * Add a user when the form is submitted.
- */
- public function add_user() {
- if (!Visitor::current()->group->can("add_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to add users."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- if (empty($_POST['login']))
- error(__("Error"), __("Please enter a username for your account."));
-
- $check = new User(array("login" => $_POST['login']));
- if (!$check->no_results)
- error(__("Error"), __("That username is already in use."));
-
- if (empty($_POST['password1']) or empty($_POST['password2']))
- error(__("Error"), __("Password cannot be blank."));
- elseif ($_POST['password1'] != $_POST['password2'])
- error(__("Error"), __("Passwords do not match."));
-
- if (empty($_POST['email']))
- error(__("Error"), __("E-mail address cannot be blank."));
- elseif (!preg_match("/^[_A-z0-9-]+((\.|\+)[_A-z0-9-]+)*@[A-z0-9-]+(\.[A-z0-9-]+)*(\.[A-z]{2,4})$/", $_POST['email']))
- error(__("Error"), __("Invalid e-mail address."));
-
- if (!empty($_POST['website']) and strpos($_POST['website'], '://') === false) {
- $_POST['website'] = 'http://' . $_POST['website'];
- }
-
- User::add($_POST['login'],
- $_POST['password1'],
- $_POST['email'],
- $_POST['full_name'],
- $_POST['website'],
- $_POST['group']);
-
- Flash::notice(__("User added."), "/admin/?action=manage_users");
- }
-
- /**
- * Function: edit_user
- * User editing.
- */
- public function edit_user() {
- if (!Visitor::current()->group->can("edit_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this user."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to edit a user."));
-
- $this->display("edit_user",
- array("user" => new User($_GET['id']),
- "groups" => Group::find(array("order" => "id ASC",
- "where" => array("id not" => Config::current()->guest_group)))));
- }
-
- /**
- * Function: update_user
- * Updates a user when the form is submitted.
- */
- public function update_user() {
- if (empty($_POST['id']))
- error(__("No ID Specified"), __("An ID is required to edit a user."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $visitor = Visitor::current();
-
- if (!$visitor->group->can("edit_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit users."));
-
- $check_name = new User(null, array("where" => array("login" => $_POST['login'],
- "id not" => $_POST['id'])));
-
- if (!$check_name->no_results)
- Flash::notice(_f("Login “%s” is already in use.", array($_POST['login'])),
- "/admin/?action=edit_user&id=".$_POST['id']);
-
- $user = new User($_POST['id']);
-
- if ($user->no_results)
- Flash::warning(__("User not found."), "/admin/?action=manage_user");
-
- $password = (!empty($_POST['new_password1']) and $_POST['new_password1'] == $_POST['new_password2']) ?
- User::hashPassword($_POST['new_password1']) :
- $user->password ;
-
- $website = (!empty($_POST['website']) and strpos($_POST['website'], '://') === false) ?
- $_POST['website'] = 'http://' . $_POST['website'] :
- $_POST['website'] ;
-
- $user->update($_POST['login'], $password, $_POST['email'], $_POST['full_name'], $website, $_POST['group']);
-
- if ($_POST['id'] == $visitor->id)
- $_SESSION['password'] = $password;
-
- Flash::notice(__("User updated."), "/admin/?action=manage_users");
- }
-
- /**
- * Function: delete_user
- * User deletion.
- */
- public function delete_user() {
- if (!Visitor::current()->group->can("delete_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete users."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to delete a user."));
-
- $this->display("delete_user",
- array("user" => new User($_GET['id']),
- "users" => User::find(array("where" => array("id not" => $_GET['id'])))));
- }
-
- /**
- * Function: destroy_user
- * Destroys a user.
- */
- public function destroy_user() {
- if (!Visitor::current()->group->can("delete_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete users."));
-
- if (empty($_POST['id']))
- error(__("No ID Specified"), __("An ID is required to delete a user."));
-
- if ($_POST['destroy'] == "bollocks")
- redirect("/admin/?action=manage_users");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $sql = SQL::current();
- $user = new User($_POST['id']);
-
- if (isset($_POST['posts'])) {
- if ($_POST['posts'] == "delete")
- foreach ($user->post as $post)
- Post::delete($post->id);
- elseif ($_POST['posts'] == "move")
- $sql->update("posts",
- array("user_id" => $user->id),
- array("user_id" => $_POST['move_posts']));
- }
-
- if (isset($_POST['pages'])) {
- if ($_POST['pages'] == "delete")
- foreach ($user->page as $page)
- Page::delete($page->id);
- elseif ($_POST['pages'] == "move")
- $sql->update("pages",
- array("user_id" => $user->id),
- array("user_id" => $_POST['move_pages']));
- }
-
- User::delete($_POST['id']);
-
- Flash::notice(__("User deleted."), "/admin/?action=manage_users");
- }
-
- /**
- * Function: manage_users
- * User managing.
- */
- public function manage_users() {
- $visitor = Visitor::current();
- if (!$visitor->group->can("edit_user") and !$visitor->group->can("delete_user") and !$visitor->group->can("add_user"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to manage users."));
-
- fallback($_GET['query'], "");
- list($where, $params) = keywords($_GET['query'], "login LIKE :query OR full_name LIKE :query OR email LIKE :query OR website LIKE :query", "users");
-
- $this->display("manage_users",
- array("users" => new Paginator(User::find(array("placeholders" => true,
- "where" => $where,
- "params" => $params)),
- 25)));
- }
-
- /**
- * Function: new_group
- * Group creation.
- */
- public function new_group() {
- if (!Visitor::current()->group->can("add_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create groups."));
-
- $this->display("new_group",
- array("permissions" => SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll()));
- }
-
- /**
- * Function: add_group
- * Adds a group when the form is submitted.
- */
- public function add_group() {
- if (!Visitor::current()->group->can("add_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to create groups."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- Group::add($_POST['name'], array_keys($_POST['permissions']));
-
- Flash::notice(__("Group added."), "/admin/?action=manage_groups");
- }
-
- /**
- * Function: edit_group
- * Group editing.
- */
- public function edit_group() {
- if (!Visitor::current()->group->can("edit_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit groups."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to edit a group."));
-
- $this->display("edit_group",
- array("group" => new Group($_GET['id']),
- "permissions" => SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll()));
- }
-
- /**
- * Function: update_group
- * Updates a group when the form is submitted.
- */
- public function update_group() {
- if (!Visitor::current()->group->can("edit_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to edit groups."));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $permissions = array_keys($_POST['permissions']);
-
- $check_name = new Group(null, array("where" => array("name" => $_POST['name'],
- "id not" => $_POST['id'])));
-
- if (!$check_name->no_results)
- Flash::notice(_f("Group name “%s” is already in use.", array($_POST['name'])),
- "/admin/?action=edit_group&id=".$_POST['id']);
-
- $group = new Group($_POST['id']);
-
- if ($group->no_results)
- Flash::warning(__("Group not found."), "/admin/?action=manage_groups");
-
- $group->update($_POST['name'], $permissions);
-
- Flash::notice(__("Group updated."), "/admin/?action=manage_groups");
- }
-
- /**
- * Function: delete_group
- * Group deletion (confirm page).
- */
- public function delete_group() {
- if (!Visitor::current()->group->can("delete_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete groups."));
-
- if (empty($_GET['id']))
- error(__("No ID Specified"), __("An ID is required to delete a group."));
-
- $this->display("delete_group",
- array("group" => new Group($_GET['id']),
- "groups" => Group::find(array("where" => array("id not" => $_GET['id']),
- "order" => "id ASC"))));
- }
-
- /**
- * Function: destroy_group
- * Destroys a group.
- */
- public function destroy_group() {
- if (!Visitor::current()->group->can("delete_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to delete groups."));
-
- if (!isset($_POST['id']))
- error(__("No ID Specified"), __("An ID is required to delete a group."));
-
- if ($_POST['destroy'] == "bollocks")
- redirect("/admin/?action=manage_groups");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $group = new Group($_POST['id']);
- foreach ($group->users as $user)
- $user->update($user->login, $user->password, $user->email, $user->full_name, $user->website, $_POST['move_group']);
-
- $config = Config::current();
- if (!empty($_POST['default_group']))
- $config->set("default_group", $_POST['default_group']);
- if (!empty($_POST['guest_group']))
- $config->set("guest_group", $_POST['guest_group']);
-
- Group::delete($_POST['id']);
-
- Flash::notice(__("Group deleted."), "/admin/?action=manage_groups");
- }
-
- /**
- * Function: manage_groups
- * Group managing.
- */
- public function manage_groups() {
- $visitor = Visitor::current();
- if (!$visitor->group->can("edit_group") and !$visitor->group->can("delete_group") and !$visitor->group->can("add_group"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to manage groups."));
-
- if (!empty($_GET['search'])) {
- $user = new User(array("login" => $_GET['search']));
- if (!$user->no_results)
- $groups = new Paginator(array($user->group), 10);
- else
- $groups = new Paginator(array(), 10);
- } else
- $groups = new Paginator(Group::find(array("placeholders" => true, "order" => "id ASC")), 10);
-
- $this->display("manage_groups",
- array("groups" => $groups));
- }
-
- /**
- * Function: export
- * Export posts, pages, etc.
- */
- public function export() {
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to export content."));
-
- if (empty($_POST))
- return $this->display("export");
-
- $config = Config::current();
- $trigger = Trigger::current();
- $route = Route::current();
- $exports = array();
-
- if (isset($_POST['posts'])) {
- list($where, $params) = keywords($_POST['filter_posts'], "post_attributes.value LIKE :query OR url LIKE :query", "post_attributes");
-
- if (!empty($_GET['month']))
- $where["created_at like"] = $_GET['month']."-%";
-
- $visitor = Visitor::current();
- if (!$visitor->group->can("view_draft", "edit_draft", "edit_post", "delete_draft", "delete_post"))
- $where["user_id"] = $visitor->id;
-
- $results = Post::find(array("placeholders" => true,
- "drafts" => true,
- "where" => $where,
- "params" => $params));
-
- $ids = array();
- foreach ($results[0] as $result)
- $ids[] = $result["id"];
-
- if (!empty($ids))
- $posts = Post::find(array("drafts" => true,
- "where" => array("id" => $ids),
- "order" => "id ASC"),
- array("filter" => false));
- else
- $posts = new Paginator(array());
-
- $latest_timestamp = 0;
- foreach ($posts as $post)
- if (strtotime($post->created_at) > $latest_timestamp)
- $latest_timestamp = strtotime($post->created_at);
-
- $id = substr(strstr($config->url, "//"), 2);
- $id = str_replace("#", "/", $id);
- $id = preg_replace("/(".preg_quote(parse_url($config->url, PHP_URL_HOST)).")/", "\\1,".date("Y", $latest_timestamp).":", $id, 1);
-
- $posts_atom = '<?xml version="1.0" encoding="utf-8"?>'."\r";
- $posts_atom.= '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:chyrp="http://chyrp.net/export/1.0/">'."\r";
- $posts_atom.= ' <title>'.fix($config->name).' Posts</title>'."\r";
- $posts_atom.= ' <subtitle>'.fix($config->description).'</subtitle>'."\r";
- $posts_atom.= ' <id>tag:'.parse_url($config->url, PHP_URL_HOST).','.date("Y", $latest_timestamp).':Chyrp</id>'."\r";
- $posts_atom.= ' <updated>'.date("c", $latest_timestamp).'</updated>'."\r";
- $posts_atom.= ' <link href="'.$config->url.'" rel="self" type="application/atom+xml" />'."\r";
- $posts_atom.= ' <generator uri="http://chyrp.net/" version="'.CHYRP_VERSION.'">Chyrp</generator>'."\r";
-
- foreach ($posts as $post) {
- $title = fix($post->title(), false);
- fallback($title, ucfirst($post->feather)." Post #".$post->id);
-
- $updated = ($post->updated) ? $post->updated_at : $post->created_at ;
-
- $tagged = substr(strstr(url("id/".$post->id), "//"), 2);
- $tagged = str_replace("#", "/", $tagged);
- $tagged = preg_replace("/(".preg_quote(parse_url($post->url(), PHP_URL_HOST)).")/", "\\1,".when("Y-m-d", $updated).":", $tagged, 1);
-
- $url = $post->url();
- $posts_atom.= ' <entry xml:base="'.fix($url).'">'."\r";
- $posts_atom.= ' <title type="html">'.$title.'</title>'."\r";
- $posts_atom.= ' <id>tag:'.$tagged.'</id>'."\r";
- $posts_atom.= ' <updated>'.when("c", $updated).'</updated>'."\r";
- $posts_atom.= ' <published>'.when("c", $post->created_at).'</published>'."\r";
- $posts_atom.= ' <link href="'.fix($trigger->filter($url, "post_export_url", $post)).'" />'."\r";
- $posts_atom.= ' <author chyrp:user_id="'.$post->user_id.'">'."\r";
- $posts_atom.= ' <name>'.fix(oneof($post->user->full_name, $post->user->login)).'</name>'."\r";
-
- if (!empty($post->user->website))
- $posts_atom.= ' <uri>'.fix($post->user->website).'</uri>'."\r";
-
- $posts_atom.= ' <chyrp:login>'.fix($post->user->login).'</chyrp:login>'."\r";
- $posts_atom.= ' </author>'."\r";
- $posts_atom.= ' <content>'."\r";
-
- foreach ($post->attributes as $key => $val)
- $posts_atom.= ' <'.$key.'>'.fix($val).'</'.$key.'>'."\r";
-
- $posts_atom.= ' </content>'."\r";
-
- foreach (array("feather", "clean", "url", "pinned", "status") as $attr)
- $posts_atom.= ' <chyrp:'.$attr.'>'.fix($post->$attr).'</chyrp:'.$attr.'>'."\r";
-
- $trigger->filter($posts_atom, "posts_export", $post);
-
- $posts_atom.= ' </entry>'."\r";
-
- }
- $posts_atom.= '</feed>'."\r";
-
- $exports["posts.atom"] = $posts_atom;
- }
-
- if (isset($_POST['pages'])) {
- list($where, $params) = keywords($_POST['filter_pages'], "title LIKE :query OR body LIKE :query", "pages");
-
- $pages = Page::find(array("where" => $where, "params" => $params, "order" => "id ASC"),
- array("filter" => false));
-
- $latest_timestamp = 0;
- foreach ($pages as $page)
- if (strtotime($page->created_at) > $latest_timestamp)
- $latest_timestamp = strtotime($page->created_at);
-
- $pages_atom = '<?xml version="1.0" encoding="utf-8"?>'."\r";
- $pages_atom.= '<feed xmlns="http://www.w3.org/2005/Atom" xmlns:chyrp="http://chyrp.net/export/1.0/">'."\r";
- $pages_atom.= ' <title>'.fix($config->name).' Pages</title>'."\r";
- $pages_atom.= ' <subtitle>'.fix($config->description).'</subtitle>'."\r";
- $pages_atom.= ' <id>tag:'.parse_url($config->url, PHP_URL_HOST).','.date("Y", $latest_timestamp).':Chyrp</id>'."\r";
- $pages_atom.= ' <updated>'.date("c", $latest_timestamp).'</updated>'."\r";
- $pages_atom.= ' <link href="'.$config->url.'" rel="self" type="application/atom+xml" />'."\r";
- $pages_atom.= ' <generator uri="http://chyrp.net/" version="'.CHYRP_VERSION.'">Chyrp</generator>'."\r";
-
- foreach ($pages as $page) {
- $updated = ($page->updated) ? $page->updated_at : $page->created_at ;
-
- $tagged = substr(strstr($page->url(), "//"), 2);
- $tagged = str_replace("#", "/", $tagged);
- $tagged = preg_replace("/(".preg_quote(parse_url($page->url(), PHP_URL_HOST)).")/", "\\1,".when("Y-m-d", $updated).":", $tagged, 1);
-
- $url = $page->url();
- $pages_atom.= ' <entry xml:base="'.fix($url).'" chyrp:parent_id="'.$page->parent_id.'">'."\r";
- $pages_atom.= ' <title type="html">'.fix($page->title).'</title>'."\r";
- $pages_atom.= ' <id>tag:'.$tagged.'</id>'."\r";
- $pages_atom.= ' <updated>'.when("c", $updated).'</updated>'."\r";
- $pages_atom.= ' <published>'.when("c", $page->created_at).'</published>'."\r";
- $pages_atom.= ' <link href="'.fix($trigger->filter($url, "page_export_url", $page)).'" />'."\r";
- $pages_atom.= ' <author chyrp:user_id="'.fix($page->user_id).'">'."\r";
- $pages_atom.= ' <name>'.fix(oneof($page->user->full_name, $page->user->login)).'</name>'."\r";
-
- if (!empty($page->user->website))
- $pages_atom.= ' <uri>'.fix($page->user->website).'</uri>'."\r";
-
- $pages_atom.= ' <chyrp:login>'.fix($page->user->login).'</chyrp:login>'."\r";
- $pages_atom.= ' </author>'."\r";
- $pages_atom.= ' <content type="html">'.fix($page->body).'</content>'."\r";
-
- foreach (array("show_in_list", "list_order", "clean", "url") as $attr)
- $pages_atom.= ' <chyrp:'.$attr.'>'.fix($page->$attr).'</chyrp:'.$attr.'>'."\r";
-
-
- $trigger->filter($pages_atom, "pages_export", $page);
-
- $pages_atom.= ' </entry>'."\r";
- }
- $pages_atom.= '</feed>'."\r";
-
- $exports["pages.atom"] = $pages_atom;
- }
-
- if (isset($_POST['groups'])) {
- list($where, $params) = keywords($_POST['filter_groups'], "name LIKE :query", "groups");
-
- $groups = Group::find(array("where" => $where, "params" => $params, "order" => "id ASC"));
-
- $groups_yaml = array("groups" => array(),
- "permissions" => array());
-
- foreach (SQL::current()->select("permissions", "*", array("group_id" => 0))->fetchAll() as $permission)
- $groups_yaml["permissions"][$permission["id"]] = $permission["name"];
-
- foreach ($groups as $index => $group)
- $groups_yaml["groups"][$group->name] = $group->permissions;
-
- $exports["groups.yaml"] = YAML::dump($groups_yaml);
- }
-
- if (isset($_POST['users'])) {
- list($where, $params) = keywords($_POST['filter_users'], "login LIKE :query OR full_name LIKE :query OR email LIKE :query OR website LIKE :query", "users");
-
- $users = User::find(array("where" => $where, "params" => $params, "order" => "id ASC"));
-
- $users_yaml = array();
- foreach ($users as $user) {
- $users_yaml[$user->login] = array();
-
- foreach ($user as $name => $attr)
- if (!in_array($name, array("no_results", "group_id", "group", "id", "login", "belongs_to", "has_many", "has_one", "queryString")))
- $users_yaml[$user->login][$name] = $attr;
- elseif ($name == "group_id")
- $users_yaml[$user->login]["group"] = $user->group->name;
- }
-
- $exports["users.yaml"] = YAML::dump($users_yaml);
- }
-
- $trigger->filter($exports, "export");
-
- require INCLUDES_DIR."/lib/zip.php";
-
- $zip = new ZipFile();
- foreach ($exports as $filename => $content)
- $zip->addFile($content, $filename);
-
- $zip_contents = $zip->file();
-
- $filename = sanitize(camelize($config->name), false, true)."_Export_".date("Y-m-d");
- header("Content-type: application/octet-stream");
- header("Content-Disposition: attachment; filename=\"".$filename.".zip\"");
- header("Content-length: ".strlen($zip_contents)."\n\n");
-
- echo $zip_contents;
- }
-
- /**
- * Function: import
- * Importing content from other systems.
- */
- public function import() {
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- $this->display("import");
- }
-
- /**
- * Function: import_chyrp
- * Chyrp importing.
- */
- public function import_chyrp() {
- if (empty($_POST))
- redirect("/admin/?action=import");
-
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- if (isset($_FILES['posts_file']) and $_FILES['posts_file']['error'] == 0)
- if (!$posts = simplexml_load_file($_FILES['posts_file']['tmp_name']) or $posts->generator != "Chyrp")
- Flash::warning(__("Chyrp Posts export file is invalid."), "/admin/?action=import");
-
- if (isset($_FILES['pages_file']) and $_FILES['pages_file']['error'] == 0)
- if (!$pages = simplexml_load_file($_FILES['pages_file']['tmp_name']) or $pages->generator != "Chyrp")
- Flash::warning(__("Chyrp Pages export file is invalid."), "/admin/?action=import");
-
- if (ini_get("memory_limit") < 20)
- ini_set("memory_limit", "20M");
-
- $trigger = Trigger::current();
- $visitor = Visitor::current();
- $sql = SQL::current();
-
- function media_url_scan(&$value) {
- $config = Config::current();
-
- $regexp_url = preg_quote($_POST['media_url'], "/");
- if (preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/", $value, $media))
- foreach ($media[0] as $matched_url) {
- $filename = upload_from_url($matched_url);
- $value = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $value);
- }
- }
-
- if (isset($_FILES['groups_file']) and $_FILES['groups_file']['error'] == 0) {
- $import = YAML::load($_FILES['groups_file']['tmp_name']);
-
- foreach ($import["groups"] as $name => $permissions)
- if (!$sql->count("groups", array("name" => $name)))
- $trigger->call("import_chyrp_group", Group::add($name, (array) $permissions));
-
- foreach ($import["permissions"] as $id => $name)
- if (!$sql->count("permissions", array("id" => $id)))
- $sql->insert("permissions", array("id" => $id, "name" => $name));
- }
-
- if (isset($_FILES['users_file']) and $_FILES['users_file']['error'] == 0) {
- $users = YAML::load($_FILES['users_file']['tmp_name']);
-
- foreach ($users as $login => $user) {
- $group_id = $sql->select("groups", "id", array("name" => $user["group"]), "id DESC")->fetchColumn();
-
- $group = ($group_id) ? $group_id : $config->default_group ;
-
- if (!$sql->count("users", array("login" => $login)))
- $user = User::add($login,
- $user["password"],
- $user["email"],
- $user["full_name"],
- $user["website"],
- $group,
- $user["joined_at"]);
-
- $trigger->call("import_chyrp_user", $user);
- }
- }
-
- if (isset($_FILES['posts_file']) and $_FILES['posts_file']['error'] == 0)
- foreach ($posts->entry as $entry) {
- $chyrp = $entry->children("http://chyrp.net/export/1.0/");
-
- $login = $entry->author->children("http://chyrp.net/export/1.0/")->login;
- $user_id = $sql->select("users", "id", array("login" => $login), "id DESC")->fetchColumn();
-
- $data = xml2arr($entry->content);
- $data["imported_from"] = "chyrp";
-
- if (!empty($_POST['media_url']))
- array_walk_recursive($data, "media_url_scan");
-
- $post = Post::add($data,
- $chyrp->clean,
- Post::check_url($chyrp->url),
- $chyrp->feather,
- ($user_id ? $user_id : $visitor->id),
- (bool) (int) $chyrp->pinned,
- $chyrp->status,
- datetime($entry->published),
- ($entry->updated == $entry->published) ?
- null :
- datetime($entry->updated),
- "",
- false);
-
- $trigger->call("import_chyrp_post", $entry, $post);
- }
-
- if (isset($_FILES['pages_file']) and $_FILES['pages_file']['error'] == 0)
- foreach ($pages->entry as $entry) {
- $chyrp = $entry->children("http://chyrp.net/export/1.0/");
- $attr = $entry->attributes("http://chyrp.net/export/1.0/");
-
- $login = $entry->author->children("http://chyrp.net/export/1.0/")->login;
- $user_id = $sql->select("users", "id", array("login" => $login), "id DESC")->fetchColumn();
-
- $page = Page::add($entry->title,
- $entry->content,
- ($user_id ? $user_id : $visitor->id),
- $attr->parent_id,
- (bool) (int) $chyrp->show_in_list,
- $chyrp->list_order,
- $chyrp->clean,
- Page::check_url($chyrp->url),
- datetime($entry->published),
- ($entry->updated == $entry->published) ? null : datetime($entry->updated));
-
- $trigger->call("import_chyrp_page", $entry, $page);
- }
-
- Flash::notice(__("Chyrp content successfully imported!"), "/admin/?action=import");
- }
-
- /**
- * Function: import_wordpress
- * WordPress importing.
- */
- public function import_wordpress() {
- if (empty($_POST))
- redirect("/admin/?action=import");
-
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- $config = Config::current();
-
- if (!in_array("text", $config->enabled_feathers))
- error(__("Missing Feather"), __("Importing from WordPress requires the Text feather to be installed and enabled."));
-
- if (ini_get("memory_limit") < 20)
- ini_set("memory_limit", "20M");
-
- $trigger = Trigger::current();
-
- $stupid_xml = file_get_contents($_FILES['xml_file']['tmp_name']);
- $sane_xml = preg_replace(array("/<wp:comment_content>/", "/<\/wp:comment_content>/"),
- array("<wp:comment_content><![CDATA[", "]]></wp:comment_content>"),
- $stupid_xml);
-
- $sane_xml = str_replace(array("<![CDATA[<![CDATA[", "]]>]]>"),
- array("<![CDATA[", "]]>"),
- $sane_xml);
-
- if (!substr_count($sane_xml, "xmlns:excerpt"))
- $sane_xml = preg_replace("/xmlns:content=\"([^\"]+)\"(\s+)/m",
- "xmlns:content=\"\\1\"\\2xmlns:excerpt=\"http://wordpress.org/excerpt/1.0/\"\\2",
- $sane_xml);
-
- $fix_amps_count = 1;
- while ($fix_amps_count)
- $sane_xml = preg_replace("/<wp:meta_value>(.+)&(?!amp;)(.+)<\/wp:meta_value>/m",
- "<wp:meta_value>\\1&\\2</wp:meta_value>",
- $sane_xml, -1, $fix_amps_count);
-
- # Remove null (x00) characters
- $sane_xml = str_replace("", "", $sane_xml);
-
- $xml = simplexml_load_string($sane_xml, "SimpleXMLElement", LIBXML_NOCDATA);
-
- if (!$xml or !substr_count($xml->channel->generator, "wordpress.org"))
- Flash::warning(__("File does not seem to be a valid WordPress export file, or could not be parsed. Please check your PHP error log."),
- "/admin/?action=import");
-
- foreach ($xml->channel->item as $item) {
- $wordpress = $item->children("http://wordpress.org/export/1.0/");
- $content = $item->children("http://purl.org/rss/1.0/modules/content/");
- if ($wordpress->status == "attachment" or $item->title == "zz_placeholder")
- continue;
-
- $regexp_url = preg_quote($_POST['media_url'], "/");
- if (!empty($_POST['media_url']) and
- preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/",
- $content->encoded,
- $media))
- foreach ($media[0] as $matched_url) {
- $filename = upload_from_url($matched_url);
- $content->encoded = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $content->encoded);
- }
-
- $clean = (isset($wordpress->post_name)) ? $wordpress->post_name : sanitize($item->title) ;
-
- $pinned = (isset($wordpress->is_sticky)) ? $wordpress->is_sticky : 0 ;
-
- if (empty($wordpress->post_type) or $wordpress->post_type == "post") {
- $status_translate = array("publish" => "public",
- "draft" => "draft",
- "private" => "private",
- "static" => "public",
- "object" => "public",
- "inherit" => "public",
- "future" => "draft",
- "pending" => "draft");
-
- $data = array("title" => trim($item->title),
- "body" => trim($content->encoded),
- "imported_from" => "wordpress");
-
- $post = Post::add($data,
- $clean,
- Post::check_url($clean),
- "text",
- null,
- $pinned,
- $status_translate[(string) $wordpress->status],
- (string) ($wordpress->post_date == "0000-00-00 00:00:00" ? datetime() : $wordpress->post_date),
- null,
- "",
- false);
-
- $trigger->call("import_wordpress_post", $item, $post);
- } elseif ($wordpress->post_type == "page") {
- $page = Page::add(trim($item->title),
- trim($content->encoded),
- null,
- 0,
- true,
- 0,
- $clean,
- Page::check_url($clean),
- (string) ($wordpress->post_date == "0000-00-00 00:00:00" ? datetime() : $wordpress->post_date));
-
- $trigger->call("import_wordpress_page", $item, $page);
- }
- }
-
- Flash::notice(__("WordPress content successfully imported!"), "/admin/?action=import");
- }
-
- /**
- * Function: import_tumblr
- * Tumblr importing.
- */
- public function import_tumblr() {
- if (empty($_POST))
- redirect("/admin/?action=import");
-
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- $config = Config::current();
- if (!in_array("text", $config->enabled_feathers) or
- !in_array("video", $config->enabled_feathers) or
- !in_array("audio", $config->enabled_feathers) or
- !in_array("chat", $config->enabled_feathers) or
- !in_array("photo", $config->enabled_feathers) or
- !in_array("quote", $config->enabled_feathers) or
- !in_array("link", $config->enabled_feathers))
- error(__("Missing Feather"), __("Importing from Tumblr requires the Text, Video, Audio, Chat, Photo, Quote, and Link feathers to be installed and enabled."));
-
- if (ini_get("memory_limit") < 20)
- ini_set("memory_limit", "20M");
-
- if (!parse_url($_POST['tumblr_url'], PHP_URL_SCHEME))
- $_POST['tumblr_url'] = "http://".$_POST['tumblr_url'];
-
- set_time_limit(3600);
- $url = rtrim($_POST['tumblr_url'], "/")."/api/read?num=50";
- $api = preg_replace("/<(\/?)([a-z]+)\-([a-z]+)/", "<\\1\\2_\\3", get_remote($url));
- $api = preg_replace("/ ([a-z]+)\-([a-z]+)=/", " \\1_\\2=", $api);
- $xml = simplexml_load_string($api);
-
- if (!isset($xml->tumblelog))
- Flash::warning(_f("Content could not be retrieved from the given URL. ". get_remote($url)),
- "/admin/?action=import");
-
- $already_in = $posts = array();
- foreach ($xml->posts->post as $post) {
- $posts[] = $post;
- $already_in[] = $post->attributes()->id;
- }
-
- while ($xml->posts->attributes()->total > count($posts)) {
- set_time_limit(3600);
- $api = preg_replace("/<(\/?)([a-z]+)\-([a-z]+)/", "<\\1\\2_\\3", get_remote($url."&start=".count($posts)));
- $api = preg_replace("/ ([a-z]+)\-([a-z]+)=/", " \\1_\\2=", $api);
- $xml = simplexml_load_string($api, "SimpleXMLElement", LIBXML_NOCDATA);
- foreach ($xml->posts->post as $post)
- if (!in_array($post->attributes()->id, $already_in)) {
- $posts[] = $post;
- $already_in[] = $post->attributes()->id;
- }
- }
-
- function reverse($a, $b) {
- if (empty($a) or empty($b)) return 0;
- return (strtotime($a->attributes()->date) < strtotime($b->attributes()->date)) ? -1 : 1 ;
- }
-
- set_time_limit(3600);
- usort($posts, "reverse");
-
- foreach ($posts as $key => $post) {
- set_time_limit(3600);
- if ($post->attributes()->type == "audio")
- break; # Can't import Audio posts since Tumblr has the files locked in to Amazon.
-
- $translate_types = array("regular" => "text", "conversation" => "chat");
-
- $clean = "";
- switch($post->attributes()->type) {
- case "regular":
- $title = fallback($post->regular_title);
- $values = array("title" => $title,
- "body" => $post->regular_body);
- $clean = sanitize($title);
- break;
- case "video":
- $values = array("embed" => $post->video_player,
- "caption" => fallback($post->video_caption));
- break;
- case "conversation":
- $title = fallback($post->conversation_title);
-
- $lines = array();
- foreach ($post->conversation_line as $line)
- $lines[] = $line->attributes()->label." ".$line;
-
- $values = array("title" => $title,
- "dialogue" => implode("\n", $lines));
- $clean = sanitize($title);
- break;
- case "photo":
- $values = array("filename" => upload_from_url($post->photo_url[0]),
- "caption" => fallback($post->photo_caption));
- break;
- case "quote":
- $values = array("quote" => $post->quote_text,
- "source" => preg_replace("/^— /", "",
- fallback($post->quote_source)));
- break;
- case "link":
- $name = fallback($post->link_text);
- $values = array("name" => $name,
- "source" => $post->link_url,
- "description" => fallback($post->link_description));
- $clean = sanitize($name);
- break;
- }
-
- $values["imported_from"] = "tumblr";
-
- $new_post = Post::add($values,
- $clean,
- Post::check_url($clean),
- fallback($translate_types[(string) $post->attributes()->type], (string) $post->attributes()->type),
- null,
- null,
- "public",
- datetime((int) $post->attributes()->unix_timestamp),
- null,
- "",
- false);
-
- Trigger::current()->call("import_tumble", $post, $new_post);
- }
-
- Flash::notice(__("Tumblr content successfully imported!"), "/admin/?action=import");
- }
-
- /**
- * Function: import_textpattern
- * TextPattern importing.
- */
- public function import_textpattern() {
- if (empty($_POST))
- redirect("/admin/?action=import");
-
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- $config = Config::current();
- $trigger = Trigger::current();
-
- $dbcon = $dbsel = false;
- if ($link = @mysql_connect($_POST['host'], $_POST['username'], $_POST['password'])) {
- $dbcon = true;
- $dbsel = @mysql_select_db($_POST['database'], $link);
- }
-
- if (!$dbcon or !$dbsel)
- Flash::warning(__("Could not connect to the specified TextPattern database."),
- "/admin/?action=import");
-
- mysql_query("SET NAMES 'utf8'");
-
- $get_posts = mysql_query("SELECT * FROM {$_POST['prefix']}textpattern ORDER BY ID ASC", $link) or error(__("Database Error"), mysql_error());
- $posts = array();
- while ($post = mysql_fetch_array($get_posts))
- $posts[$post["ID"]] = $post;
-
- foreach ($posts as $post) {
- $regexp_url = preg_quote($_POST['media_url'], "/");
- if (!empty($_POST['media_url']) and
- preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/",
- $post["Body"],
- $media))
- foreach ($media[0] as $matched_url) {
- $filename = upload_from_url($matched_url);
- $post["Body"] = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $post["Body"]);
- }
-
- $status_translate = array(1 => "draft",
- 2 => "private",
- 3 => "draft",
- 4 => "public",
- 5 => "public");
-
- $clean = fallback($post["url_title"], sanitize($post["Title"]));
-
- $new_post = Post::add(array("title" => $post["Title"],
- "body" => $post["Body"],
- "imported_from" => "textpattern"),
- $clean,
- Post::check_url($clean),
- "text",
- null,
- ($post["Status"] == "5"),
- $status_translate[$post["Status"]],
- $post["Posted"],
- null,
- "",
- false);
-
- $trigger->call("import_textpattern_post", $post, $new_post);
- }
-
- mysql_close($link);
-
- Flash::notice(__("TextPattern content successfully imported!"), "/admin/?action=import");
- }
-
- /**
- * Function: import_movabletype
- * MovableType importing.
- */
- public function import_movabletype() {
- if (empty($_POST))
- redirect("/admin/?action=import");
-
- if (!Visitor::current()->group->can("add_post"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to import content."));
-
- $config = Config::current();
- $trigger = Trigger::current();
-
- $dbcon = $dbsel = false;
- if ($link = @mysql_connect($_POST['host'], $_POST['username'], $_POST['password'])) {
- $dbcon = true;
- $dbsel = @mysql_select_db($_POST['database'], $link);
- }
-
- if (!$dbcon or !$dbsel)
- Flash::warning(__("Could not connect to the specified MovableType database."),
- "/admin/?action=import");
-
- mysql_query("SET NAMES 'utf8'");
-
- $get_authors = mysql_query("SELECT * FROM mt_author ORDER BY author_id ASC", $link) or error(__("Database Error"), mysql_error());
- $users = array();
- while ($author = mysql_fetch_array($get_authors)) {
- # Try to figure out if this author is the same as the person doing the import.
- if ($author["author_name"] == Visitor::current()->login or
- $author["author_nickname"] == Visitor::current()->login or
- $author["author_nickname"] == Visitor::current()->full_name or
- $author["author_url"] == Visitor::current()->website or
- $author["author_email"] == Visitor::current()->email)
- $users[$author["author_id"]] = Visitor::current();
- else
- $users[$author["author_id"]] = User::add($author["author_name"],
- $author["author_password"],
- $author["author_email"],
- ($author["author_nickname"] != $author["author_name"] ?
- $author["author_nickname"] :
- ""),
- $author["author_url"],
- ($author["author_can_create_blog"] == "1" ?
- Visitor::current()->group :
- null),
- $author["author_created_on"],
- false);
- }
-
- $get_posts = mysql_query("SELECT * FROM mt_entry ORDER BY entry_id ASC", $link) or error(__("Database Error"), mysql_error());
- $posts = array();
- while ($post = mysql_fetch_array($get_posts))
- $posts[$post["entry_id"]] = $post;
-
- foreach ($posts as $post) {
- $body = $post["entry_text"];
-
- if (!empty($post["entry_text_more"]))
- $body.= "\n\n<!--more-->\n\n".$post["entry_text_more"];
-
- $regexp_url = preg_quote($_POST['media_url'], "/");
- if (!empty($_POST['media_url']) and
- preg_match_all("/{$regexp_url}([^\.\!,\?;\"\'<>\(\)\[\]\{\}\s\t ]+)\.([a-zA-Z0-9]+)/",
- $body,
- $media))
- foreach ($media[0] as $matched_url) {
- $filename = upload_from_url($matched_url);
- $body = str_replace($matched_url, $config->url.$config->uploads_path.$filename, $body);
- }
-
- $status_translate = array(1 => "draft",
- 2 => "public",
- 3 => "draft",
- 4 => "draft");
-
- $clean = oneof($post["entry_basename"], sanitize($post["entry_title"]));
-
- if (empty($post["entry_class"]) or $post["entry_class"] == "entry") {
- $new_post = Post::add(array("title" => $post["entry_title"],
- "body" => $body,
- "imported_from" => "movabletype"),
- $clean,
- Post::check_url($clean),
- "text",
- @$users[$post["entry_author_id"]],
- false,
- $status_translate[$post["entry_status"]],
- oneof(@$post["entry_authored_on"], @$post["entry_created_on"], datetime()),
- $post["entry_modified_on"],
- "",
- false);
- $trigger->call("import_movabletype_post", $post, $new_post, $link);
- } elseif (@$post["entry_class"] == "page") {
- $new_page = Page::add($post["entry_title"], $body, null, 0, true, 0, $clean, Page::check_url($clean));
- $trigger->call("import_movabletype_page", $post, $new_page, $link);
- }
- }
-
- mysql_close($link);
-
- Flash::notice(__("MovableType content successfully imported!"), "/admin/?action=import");
- }
-
- /**
- * Function: modules
- * Module enabling/disabling.
- */
- public function modules() {
- if (!Visitor::current()->group->can("toggle_extensions"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules."));
-
- $config = Config::current();
-
- $this->context["enabled_modules"] = $this->context["disabled_modules"] = array();
-
- if (!$open = @opendir(MODULES_DIR))
- return Flash::warning(__("Could not read modules directory."));
-
- $classes = array();
-
- while (($folder = readdir($open)) !== false) {
- if (!file_exists(MODULES_DIR."/".$folder."/".$folder.".php") or !file_exists(MODULES_DIR."/".$folder."/info.yaml")) continue;
-
- if (file_exists(MODULES_DIR."/".$folder."/locale/".$config->locale.".mo"))
- load_translator($folder, MODULES_DIR."/".$folder."/locale/".$config->locale.".mo");
-
- if (!isset($classes[$folder]))
- $classes[$folder] = array($folder);
- else
- array_unshift($classes[$folder], $folder);
-
- $info = YAML::load(MODULES_DIR."/".$folder."/info.yaml");
-
- $info["conflicts_true"] = array();
- $info["depends_true"] = array();
-
- if (!empty($info["conflicts"])) {
- $classes[$folder][] = "conflict";
-
- foreach ((array) $info["conflicts"] as $conflict)
- if (file_exists(MODULES_DIR."/".$conflict."/".$conflict.".php"))
- $classes[$folder][] = "conflict_".$conflict;
- }
-
- $dependencies_needed = array();
- if (!empty($info["depends"])) {
- $classes[$folder][] = "depends";
-
- foreach ((array) $info["depends"] as $dependency) {
- if (!module_enabled($dependency)) {
- if (!in_array("missing_dependency", $classes[$folder]))
- $classes[$folder][] = "missing_dependency";
-
- $classes[$folder][] = "needs_".$dependency;
-
- $dependencies_needed[] = $dependency;
- }
-
- $classes[$folder][] = "depends_".$dependency;
-
- fallback($classes[$dependency], array());
- $classes[$dependency][] = "depended_by_".$folder;
- }
- }
-
- fallback($info["name"], $folder);
- fallback($info["version"], "0");
- fallback($info["url"]);
- fallback($info["description"]);
- fallback($info["author"], array("name" => "", "url" => ""));
- fallback($info["help"]);
-
- $info["description"] = __($info["description"], $folder);
- $info["description"] = preg_replace(array("/<code>(.+)<\/code>/se", "/<pre>(.+)<\/pre>/se"),
- array("'<code>'.fix('\\1').'</code>'", "'<pre>'.fix('\\1').'</pre>'"),
- $info["description"]);
-
- $info["author"]["link"] = !empty($info["author"]["url"]) ?
- '<a href="'.fix($info["author"]["url"]).'">'.fix($info["author"]["name"]).'</a>' :
- $info["author"]["name"] ;
-
- $category = (module_enabled($folder)) ? "enabled_modules" : "disabled_modules" ;
- $this->context[$category][$folder] = array("name" => $info["name"],
- "version" => $info["version"],
- "url" => $info["url"],
- "description" => $info["description"],
- "author" => $info["author"],
- "help" => $info["help"],
- "classes" => $classes[$folder],
- "dependencies_needed" => $dependencies_needed);
- }
-
- foreach ($this->context["enabled_modules"] as $module => &$attrs)
- $attrs["classes"] = $classes[$module];
-
- foreach ($this->context["disabled_modules"] as $module => &$attrs)
- $attrs["classes"] = $classes[$module];
-
- $this->display("modules");
- }
-
- /**
- * Function: feathers
- * Feather enabling/disabling.
- */
- public function feathers() {
- if (!Visitor::current()->group->can("toggle_extensions"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers."));
-
- $config = Config::current();
-
- $this->context["enabled_feathers"] = $this->context["disabled_feathers"] = array();
-
- if (!$open = @opendir(FEATHERS_DIR))
- return Flash::warning(__("Could not read feathers directory."));
-
- while (($folder = readdir($open)) !== false) {
- if (!file_exists(FEATHERS_DIR."/".$folder."/".$folder.".php") or !file_exists(FEATHERS_DIR."/".$folder."/info.yaml")) continue;
-
- if (file_exists(FEATHERS_DIR."/".$folder."/locale/".$config->locale.".mo"))
- load_translator($folder, FEATHERS_DIR."/".$folder."/locale/".$config->locale.".mo");
-
- $info = YAML::load(FEATHERS_DIR."/".$folder."/info.yaml");
-
- fallback($info["name"], $folder);
- fallback($info["version"], "0");
- fallback($info["url"]);
- fallback($info["description"]);
- fallback($info["author"], array("name" => "", "url" => ""));
- fallback($info["help"]);
-
- $info["description"] = __($info["description"], $folder);
- $info["description"] = preg_replace("/<code>(.+)<\/code>/se", "'<code>'.fix('\\1').'</code>'", $info["description"]);
- $info["description"] = preg_replace("/<pre>(.+)<\/pre>/se", "'<pre>'.fix('\\1').'</pre>'", $info["description"]);
-
- $info["author"]["link"] = !empty($info["author"]["url"]) ?
- '<a href="'.fix($info["author"]["url"]).'">'.fix($info["author"]["name"]).'</a>' :
- $info["author"]["name"] ;
-
- $category = (feather_enabled($folder)) ? "enabled_feathers" : "disabled_feathers" ;
- $this->context[$category][$folder] = array("name" => $info["name"],
- "version" => $info["version"],
- "url" => $info["url"],
- "description" => $info["description"],
- "author" => $info["author"],
- "help" => $info["help"]);
- }
-
- $this->display("feathers");
- }
-
- /**
- * Function: themes
- * Theme switching/previewing.
- */
- public function themes() {
- $config = Config::current();
-
- $this->context["preview"] = !empty($_SESSION['theme']) ? $_SESSION['theme'] : "" ;
-
- $this->context["themes"] = array();
-
- if (!$open = @opendir(THEMES_DIR))
- return Flash::warning(__("Could not read themes directory."));
-
- while (($folder = readdir($open)) !== false) {
- if (!file_exists(THEMES_DIR."/".$folder."/info.yaml"))
- continue;
-
- if (file_exists(THEMES_DIR."/".$folder."/locale/".$config->locale.".mo"))
- load_translator($folder, THEMES_DIR."/".$folder."/locale/".$config->locale.".mo");
-
- $info = YAML::load(THEMES_DIR."/".$folder."/info.yaml");
-
- fallback($info["name"], $folder);
- fallback($info["version"], "0");
- fallback($info["url"]);
- fallback($info["description"]);
- fallback($info["author"], array("name" => "", "url" => ""));
-
- $info["author"]["link"] = !empty($info["author"]["url"]) ?
- '<a href="'.$info["author"]["url"].'">'.$info["author"]["name"].'</a>' :
- $info["author"]["name"] ;
- $info["description"] = preg_replace("/<code>(.+)<\/code>/se",
- "'<code>'.fix('\\1').'</code>'",
- $info["description"]);
-
- $info["description"] = preg_replace("/<pre>(.+)<\/pre>/se",
- "'<pre>'.fix('\\1').'</pre>'",
- $info["description"]);
-
- $this->context["themes"][] = array("name" => $folder,
- "screenshot" => (file_exists(THEMES_DIR."/".$folder."/screenshot.png") ?
- $config->chyrp_url."/themes/".$folder."/screenshot.png" :
- ""),
- "info" => $info);
- }
-
- if (!$open = @opendir(ADMIN_THEMES_DIR))
- return Flash::warning(__("Could not read themes directory."));
-
- while (($folder = readdir($open)) !== false) {
- if (!file_exists(ADMIN_THEMES_DIR."/".$folder."/info.yaml"))
- continue;
-
- if (file_exists(ADMIN_THEMES_DIR."/".$folder."/locale/".$config->locale.".mo"))
- load_translator($folder, ADMIN_THEMES_DIR."/".$folder."/locale/".$config->locale.".mo");
-
- $info = YAML::load(ADMIN_THEMES_DIR."/".$folder."/info.yaml");
-
- fallback($info["name"], $folder);
- fallback($info["version"], "0");
- fallback($info["url"]);
- fallback($info["description"]);
- fallback($info["author"], array("name" => "", "url" => ""));
-
- $info["author"]["link"] = !empty($info["author"]["url"]) ?
- '<a href="'.$info["author"]["url"].'">'.$info["author"]["name"].'</a>' :
- $info["author"]["name"] ;
- $info["description"] = preg_replace("/<code>(.+)<\/code>/se",
- "'<code>'.fix('\\1').'</code>'",
- $info["description"]);
-
- $info["description"] = preg_replace("/<pre>(.+)<\/pre>/se",
- "'<pre>'.fix('\\1').'</pre>'",
- $info["description"]);
-
- $this->context["admin_themes"][] = array("name" => $folder,
- "screenshot" => (file_exists(ADMIN_THEMES_DIR."/".$folder."/screenshot.png") ?
- $config->chyrp_url."/admin/themes/".$folder."/screenshot.png" :
- ""),
- "info" => $info);
- }
-
- closedir($open);
-
- $this->display("themes");
- }
-
- /**
- * Function: enable
- * Enables a module or feather.
- */
- public function enable() {
- $config = Config::current();
- $visitor = Visitor::current();
-
- $type = (isset($_GET['module'])) ? "module" : "feather" ;
-
- if (!$visitor->group->can("toggle_extensions"))
- if ($type == "module")
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules."));
- else
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers."));
-
- if ($type == "module" and module_enabled($_GET[$type]))
- Flash::warning(__("Module already enabled."), "/admin/?action=modules");
-
- if ($type == "feather" and feather_enabled($_GET[$type]))
- Flash::warning(__("Feather already enabled."), "/admin/?action=feathers");
-
- $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ;
- $folder = ($type == "module") ? MODULES_DIR : FEATHERS_DIR ;
-
- require $folder."/".$_GET[$type]."/".$_GET[$type].".php";
-
- $class_name = camelize($_GET[$type]);
-
- if ($type == "module" and !is_subclass_of($class_name, "Modules"))
- Flash::warning(__("Item is not a module."), "/admin/?action=modules");
-
- if ($type == "feather" and !is_subclass_of($class_name, "Feathers"))
- Flash::warning(__("Item is not a feather."), "/admin/?action=feathers");
-
- if (method_exists($class_name, "__install"))
- call_user_func(array($class_name, "__install"));
-
- $new = $config->$enabled_array;
- array_push($new, $_GET[$type]);
- $config->set($enabled_array, $new);
-
- if (file_exists($folder."/".$_GET[$type]."/locale/".$config->locale.".mo"))
- load_translator($_GET[$type], $folder."/".$_GET[$type]."/locale/".$config->locale.".mo");
-
- $info = YAML::load($folder."/".$_GET[$type]."/info.yaml");
- fallback($info["uploader"], false);
- fallback($info["notifications"], array());
-
- foreach ($info["notifications"] as &$notification)
- $notification = __($notification, $_GET[$type]);
-
- if ($info["uploader"])
- if (!file_exists(MAIN_DIR.$config->uploads_path))
- $info["notifications"][] = _f("Please create the <code>%s</code> directory at your Chyrp install's root and CHMOD it to 777.", array($config->uploads_path));
- elseif (!is_writable(MAIN_DIR.$config->uploads_path))
- $info["notifications"][] = _f("Please CHMOD <code>%s</code> to 777.", array($config->uploads_path));
-
- foreach ($info["notifications"] as $message)
- Flash::message($message);
-
- if ($type == "module")
- Flash::notice(_f("“%s” module enabled.",
- array($info["name"])),
- "/admin/?action=".pluralize($type));
- elseif ($type == "feather")
- Flash::notice(_f("“%s” feather enabled.",
- array($info["name"])),
- "/admin/?action=".pluralize($type));
- }
-
- /**
- * Function: disable
- * Disables a module or feather.
- */
- public function disable() {
- $config = Config::current();
- $visitor = Visitor::current();
-
- $type = (isset($_GET['module'])) ? "module" : "feather" ;
-
- if (!$visitor->group->can("toggle_extensions"))
- if ($type == "module")
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable modules."));
- else
- show_403(__("Access Denied"), __("You do not have sufficient privileges to enable/disable feathers."));
-
- if ($type == "module" and !module_enabled($_GET[$type]))
- Flash::warning(__("Module already disabled."), "/admin/?action=modules");
-
- if ($type == "feather" and !feather_enabled($_GET[$type]))
- Flash::warning(__("Feather already disabled."), "/admin/?action=feathers");
-
- $enabled_array = ($type == "module") ? "enabled_modules" : "enabled_feathers" ;
- $folder = ($type == "module") ? MODULES_DIR : FEATHERS_DIR ;
-
- $class_name = camelize($_GET[$type]);
- if (method_exists($class_name, "__uninstall"))
- call_user_func(array($class_name, "__uninstall"), false);
-
- $config->set(($type == "module" ? "enabled_modules" : "enabled_feathers"),
- array_diff($config->$enabled_array, array($_GET[$type])));
-
- $info = YAML::load($folder."/".$_GET[$type]."/info.yaml");
- if ($type == "module")
- Flash::notice(_f("“%s” module disabled.",
- array($info["name"])),
- "/admin/?action=".pluralize($type));
- elseif ($type == "feather")
- Flash::notice(_f("“%s” feather disabled.",
- array($info["name"])),
- "/admin/?action=".pluralize($type));
- }
-
- /**
- * Function: change_theme
- * Changes the theme.
- */
- public function change_theme() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
- if (empty($_GET['theme']))
- error(__("No Theme Specified"), __("You did not specify a theme to switch to."));
-
- $config = Config::current();
-
- $config->set("theme", $_GET['theme']);
-
- if (file_exists(THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo"))
- load_translator($_GET['theme'], THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo");
-
- $info = YAML::load(THEMES_DIR."/".$_GET['theme']."/info.yaml");
- fallback($info["notifications"], array());
-
- foreach ($info["notifications"] as &$notification)
- $notification = __($notification, $_GET['theme']);
-
- foreach ($info["notifications"] as $message)
- Flash::message($message);
-
- # Clear the caches made by the previous theme.
- foreach ((array) glob(INCLUDES_DIR."/caches/*.cache") as $cache)
- @unlink($cache);
-
- Flash::notice(_f("Theme changed to “%s”.", array($info["name"])), "/admin/?action=themes");
- }
-
- /**
- * Function: theme
- * Changes the admin theme.
- */
- public function change_admin_theme() {
- if (empty($_GET['theme']))
- error(__("No Theme Specified"), __("You did not specify a theme to switch to."));
-
- $config = Config::current();
-
- $_SESSION['admin_theme'] = $_GET['theme'];
-
- if (file_exists(ADMIN_THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo"))
- load_translator($_GET['theme'], ADMIN_THEMES_DIR."/".$_GET['theme']."/locale/".$config->locale.".mo");
-
- $info = YAML::load(ADMIN_THEMES_DIR."/".$_GET['theme']."/info.yaml");
- fallback($info["notifications"], array());
-
- foreach ($info["notifications"] as &$notification)
- $notification = __($notification, $_GET['theme']);
-
- foreach ($info["notifications"] as $message)
- Flash::message($message);
-
- # Clear the caches made by the previous theme.
- foreach (glob(INCLUDES_DIR."/caches/*.cache") as $cache)
- @unlink($cache);
-
- Flash::notice(_f("Admin theme changed to “%s”.", array($info["name"])), "/admin/?action=themes");
- }
-
- /**
- * Function: preview_theme
- * Previews the theme.
- */
- public function preview_theme() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to preview themes."));
- if (empty($_GET['theme']))
- error(__("No Theme Specified"), __("You did not specify a theme to preview."));
-
- $info = YAML::load(THEMES_DIR."/".$_GET['theme']."/info.yaml");
-
- # Clear the caches made by the previous theme.
- foreach (glob(INCLUDES_DIR."/caches/*.cache") as $cache)
- @unlink($cache);
-
- if (!empty($_SESSION['theme'])) {
- unset($_SESSION['theme']);
- Flash::notice(_f("Stopped previewing “%s”.", array($info["name"])), "/admin/?action=themes");
- } else {
- $_SESSION['theme'] = $_GET['theme'];
- Flash::notice(_f("Previewing theme “%s”. Press the theme's “Preview” button again to stop previewing.", array($info["name"])), "/");
- }
- }
-
- /**
- * Function: general_settings
- * General Settings page.
- */
- public function general_settings() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
-
- $locales = array();
-
- if ($open = opendir(INCLUDES_DIR."/locale/")) {
- while (($folder = readdir($open)) !== false) {
- $split = explode(".", $folder);
- if (end($split) == "mo")
- $locales[] = array("code" => $split[0], "name" => lang_code($split[0]));
- }
- closedir($open);
- }
-
- if (empty($_POST))
- return $this->display("general_settings",
- array("locales" => $locales,
- "timezones" => timezones()));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $config = Config::current();
- $set = array($config->set("name", $_POST['name']),
- $config->set("description", $_POST['description']),
- $config->set("chyrp_url", rtrim($_POST['chyrp_url'], "/")),
- $config->set("url", rtrim(oneof($_POST['url'], $_POST['chyrp_url']), "/")),
- $config->set("email", $_POST['email']),
- $config->set("timezone", $_POST['timezone']),
- $config->set("locale", $_POST['locale']));
-
- if (!in_array(false, $set))
- Flash::notice(__("Settings updated."), "/admin/?action=general_settings");
- }
-
- /**
- * Function: user_settings
- * User Settings page.
- */
- public function user_settings() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
-
- if (empty($_POST))
- return $this->display("user_settings", array("groups" => Group::find(array("order" => "id DESC"))));
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $config = Config::current();
- $set = array($config->set("can_register", !empty($_POST['can_register'])),
- $config->set("default_group", $_POST['default_group']),
- $config->set("guest_group", $_POST['guest_group']));
-
- if (!in_array(false, $set))
- Flash::notice(__("Settings updated."), "/admin/?action=user_settings");
- }
-
- /**
- * Function: content_settings
- * Content Settings page.
- */
- public function content_settings() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
-
- if (empty($_POST))
- return $this->display("content_settings");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $config = Config::current();
- $set = array($config->set("posts_per_page", $_POST['posts_per_page']),
- $config->set("feed_items", $_POST['feed_items']),
- $config->set("feed_url", $_POST['feed_url']),
- $config->set("uploads_path", $_POST['uploads_path']),
- $config->set("enable_trackbacking", !empty($_POST['enable_trackbacking'])),
- $config->set("send_pingbacks", !empty($_POST['send_pingbacks'])),
- $config->set("enable_xmlrpc", !empty($_POST['enable_xmlrpc'])),
- $config->set("enable_ajax", !empty($_POST['enable_ajax'])));
-
- if (!in_array(false, $set))
- Flash::notice(__("Settings updated."), "/admin/?action=content_settings");
- }
-
- /**
- * Function: route_settings
- * Route Settings page.
- */
- public function route_settings() {
- if (!Visitor::current()->group->can("change_settings"))
- show_403(__("Access Denied"), __("You do not have sufficient privileges to change settings."));
-
- if (empty($_POST))
- return $this->display("route_settings");
-
- if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
- show_403(__("Access Denied"), __("Invalid security key."));
-
- $config = Config::current();
- $set = array($config->set("clean_urls", !empty($_POST['clean_urls'])),
- $config->set("post_url", $_POST['post_url']));
-
- if (!in_array(false, $set))
- Flash::notice(__("Settings updated."), "/admin/?action=route_settings");
- }
-
- /**
- * Function: help
- * Sets the $title and $body for various help IDs.
- */
- public function help() {
- list($title, $body) = Trigger::current()->call("help_".$_GET['id']);
-
- switch($_GET['id']) {
- case "filtering_results":
- $title = __("Filtering Results");
- $body = "<p>".__("Use this to search for specific items. You can either enter plain text to match the item with, or use keywords:")."</pre>";
- $body.= "<h2>".__("Keywords")."</h2>";
- $body.= "<cite><strong>".__("Usage")."</strong>: <code>attr:val</code></cite>\n".__("Use this syntax to quickly match specific results. Keywords will modify the query to match items where <code>attr</code> is equal to <code>val</code> (case insensitive).");
- break;
- case "slugs":
- $title = __("Post Slugs");
- $body = __("Post slugs are strings to use for the URL of a post. They are directly respondible for the <code>(url)</code> attribute in a post's clean URL, or the <code>/?action=view&url=<strong>foo</strong></code> in a post's dirty URL. A post slug should not contain any special characters other than hyphens.");
- break;
- case "trackbacks":
- $title = __("Trackbacks");
- $body = __("Trackbacks are special urls to posts from other blogs that your post is related to or references. The other blog will be notified of your post, and in some cases a comment will automatically be added to the post in question linking back to your post. It's basically a way to network between blogs via posts.");
- break;
- case "alternate_urls":
- $title = __("Alternate URL");
- $body = "<p>".__("An alternate URL will allow you to keep Chyrp in its own directory, while having your site URLs point to someplace else. For example, you could have Chyrp in a <code>/chyrp</code> directory, and have your site at <code>/</code>. There are two requirements for this to work.")."</p>\n\n";
- $body.= "<ol>\n\t<li>".__("Create an <code>index.php</code> file in your destination directory with the following in it:")."\n\n";
- $body.= "<pre><code><?php
- require \"path/to/chyrp/index.php\";
- ?></code></pre>";
- $body.= "</li>\n\t<li>".__("Move the .htaccess file from the original Chyrp directory, and change the <code>RewriteBase</code> line to reflect the new website location.")."</li>\n</ol>";
- }
-
- require "help.php";
- }
-
- /**
- * Function: subnav_context
- * Generates the context variables for the subnav.
- */
- public function subnav_context($action) {
- $trigger = Trigger::current();
- $visitor = Visitor::current();
-
- $this->context["subnav"] = array();
- $subnav =& $this->context["subnav"];
-
- $subnav["write"] = array();
- $pages = array("manage" => array());
-
- foreach (Config::current()->enabled_feathers as $index => $feather) {
- $info = YAML::load(FEATHERS_DIR."/".$feather."/info.yaml");
- $subnav["write"]["write_post&feather=".$feather] = array("title" => __($info["name"], $feather),
- "show" => $visitor->group->can("add_draft", "add_post"),
- "attributes" => ' id="list_feathers['.$feather.']"',
- "selected" => (isset($_GET['feather']) and $_GET['feather'] == $feather) or
- (!isset($_GET['feather']) and $action == "write_post" and !$index));
- }
-
- # Write navs
- $subnav["write"]["write_page"] = array("title" => __("Page"),
- "show" => $visitor->group->can("add_page"));
- $trigger->filter($subnav["write"], array("admin_write_nav", "write_nav"));
- $pages["write"] = array_merge(array("write_post"), array_keys($subnav["write"]));;
-
- # Manage navs
- $subnav["manage"] = array("manage_posts" => array("title" => __("Posts"),
- "show" => (Post::any_editable() or Post::any_deletable()),
- "selected" => array("edit_post", "delete_post")),
- "manage_pages" => array("title" => __("Pages"),
- "show" => ($visitor->group->can("edit_page", "delete_page")),
- "selected" => array("edit_page", "delete_page")),
- "manage_users" => array("title" => __("Users"),
- "show" => ($visitor->group->can("add_user",
- "edit_user",
- "delete_user")),
- "selected" => array("edit_user", "delete_user", "new_user")),
- "manage_groups" => array("title" => __("Groups"),
- "show" => ($visitor->group->can("add_group",
- "edit_group",
- "delete_group")),
- "selected" => array("edit_group", "delete_group", "new_group")));
- $trigger->filter($subnav["manage"], "manage_nav");
-
- $subnav["manage"]["import"] = array("title" => __("Import"),
- "show" => ($visitor->group->can("add_post")));
- $subnav["manage"]["export"] = array("title" => __("Export"),
- "show" => ($visitor->group->can("add_post")));
-
- $pages["manage"][] = "new_user";
- $pages["manage"][] = "new_group";
- foreach (array_keys($subnav["manage"]) as $manage)
- $pages["manage"] = array_merge($pages["manage"], array($manage,
- preg_replace("/manage_(.+)/e",
- "'edit_'.depluralize('\\1')",
- $manage),
- preg_replace("/manage_(.+)/e",
- "'delete_'.depluralize('\\1')",
- $manage)));
-
- # Settings navs
- $subnav["settings"] = array("general_settings" => array("title" => __("General"),
- "show" => $visitor->group->can("change_settings")),
- "content_settings" => array("title" => __("Content"),
- "show" => $visitor->group->can("change_settings")),
- "user_settings" => array("title" => __("Users"),
- "show" => $visitor->group->can("change_settings")),
- "route_settings" => array("title" => __("Routes"),
- "show" => $visitor->group->can("change_settings")));
- $trigger->filter($subnav["settings"], "settings_nav");
- $pages["settings"] = array_keys($subnav["settings"]);
-
- # Extend navs
- $subnav["extend"] = array("modules" => array("title" => __("Modules"),
- "show" => $visitor->group->can("toggle_extensions")),
- "feathers" => array("title" => __("Feathers"),
- "show" => $visitor->group->can("toggle_extensions")),
- "themes" => array("title" => __("Themes"),
- "show" => $visitor->group->can("toggle_extensions")));
- $trigger->filter($subnav["extend"], "extend_nav");
- $pages["extend"] = array_keys($subnav["extend"]);
-
- foreach (array_keys($subnav) as $main_nav)
- foreach ($trigger->filter($pages[$main_nav], $main_nav."_nav_pages") as $extend)
- $subnav[$extend] =& $subnav[$main_nav];
-
- foreach ($subnav as $main_nav => &$sub_nav)
- foreach ($sub_nav as &$nav)
- $nav["show"] = (!isset($nav["show"]) or $nav["show"]);
-
- $trigger->filter($subnav, "admin_subnav");
- }
-
- /**
- * Function: display
- * Renders the page.
- *
- * Parameters:
- * $action - The template file to display, in (theme dir)/pages.
- * $context - Context for the template.
- * $title - The title for the page. Defaults to a camlelization of the action, e.g. foo_bar -> Foo Bar.
- */
- public function display($action, $context = array(), $title = "") {
- $this->displayed = true;
-
- fallback($title, camelize($action, true));
-
- $this->context = array_merge($context, $this->context);
-
- $trigger = Trigger::current();
-
- $trigger->filter($this->context, array("admin_context", "admin_context_".str_replace("/", "_", $action)));
-
- # Are there any extension-added pages?
- foreach (array("write" => array(),
- "manage" => array("import", "export"),
- "settings" => array(),
- "extend" => array("modules", "feathers", "themes")) as $main_nav => $val) {
- $$main_nav = $val;
- $trigger->filter($$main_nav, $main_nav."_pages");
- }
-
- $visitor = Visitor::current();
- $route = Route::current();
-
- $this->context["theme"] = Theme::current();
- $this->context["flash"] = Flash::current();
- $this->context["trigger"] = $trigger;
- $this->context["title"] = $title;
- $this->context["site"] = Config::current();
- $this->context["visitor"] = $visitor;
- $this->context["logged_in"] = logged_in();
- $this->context["route"] = $route;
- $this->context["hide_admin"] = isset($_SESSION["hide_admin"]);
- $this->context["now"] = time();
- $this->context["version"] = CHYRP_VERSION;
- $this->context["debug"] = DEBUG;
- $this->context["feathers"] = Feathers::$instances;
- $this->context["modules"] = Modules::$instances;
- $this->context["admin_theme"] = $this->admin_theme;
- $this->context["theme_url"] = Config::current()->chyrp_url."/admin/themes/".$this->admin_theme;
- $this->context["POST"] = $_POST;
- $this->context["GET"] = $_GET;
-
- $this->context["navigation"] = array();
-
- $show = array("write" => array($visitor->group->can("add_draft", "add_post", "add_page")),
- "manage" => array($visitor->group->can("view_own_draft",
- "view_draft",
- "edit_own_draft",
- "edit_own_post",
- "edit_post",
- "delete_own_draft",
- "delete_own_post",
- "delete_post",
- "add_page",
- "edit_page",
- "delete_page",
- "add_user",
- "edit_user",
- "delete_user",
- "add_group",
- "edit_group",
- "delete_group")),
- "settings" => array($visitor->group->can("change_settings")),
- "extend" => array($visitor->group->can("toggle_extensions")));
-
- foreach ($show as $name => &$arr)
- $trigger->filter($arr, $name."_nav_show");
-
- $this->context["navigation"]["write"] = array("title" => __("Write"),
- "show" => in_array(true, $show["write"]),
- "selected" => (in_array($action, $write) or
- match("/^write_/", $action)));
-
- $this->context["navigation"]["manage"] = array("title" => __("Manage"),
- "show" => in_array(true, $show["manage"]),
- "selected" => (in_array($action, $manage) or
- match(array("/^manage_/",
- "/^edit_/",
- "/^delete_/",
- "/^new_/"), $action)));
-
- $this->context["navigation"]["settings"] = array("title" => __("Settings"),
- "show" => in_array(true, $show["settings"]),
- "selected" => (in_array($action, $settings) or
- match("/_settings$/", $action)));
-
- $this->context["navigation"]["extend"] = array("title" => __("Extend"),
- "show" => in_array(true, $show["extend"]),
- "selected" => (in_array($action, $extend)));
-
- $this->subnav_context($route->action);
-
- $trigger->filter($this->context["selected"], "nav_selected");
-
- $this->context["sql_debug"] = SQL::current()->debug;
-
- $file = MAIN_DIR."/admin/themes/%s/pages/".$action.".twig";
- $template = file_exists(sprintf($file, $this->admin_theme)) ?
- sprintf($file, $this->admin_theme) :
- sprintf($file, "default");
-
- $config = Config::current();
- if (!file_exists($template)) {
- foreach (array(MODULES_DIR => $config->enabled_modules,
- FEATHERS_DIR => $config->enabled_feathers) as $path => $try)
- foreach ($try as $extension)
- if (file_exists($path."/".$extension."/pages/admin/".$action.".twig"))
- $template = $path."/".$extension."/pages/admin/".$action.".twig";
-
- if (!file_exists($template))
- error(__("Template Missing"), _f("Couldn't load template: <code>%s</code>", array($template)));
- }
-
- # Try the theme first
- try {
- $this->theme->getTemplate($template)->display($this->context);
- } catch (Exception $t) {
- # Fallback to the default
- try {
- $this->default->getTemplate($template)->display($this->context);
- } catch (Exception $e) {
- $prettify = preg_replace("/([^:]+): (.+)/", "\\1: <code>\\2</code>", $e->getMessage());
- $trace = debug_backtrace();
- $twig = array("file" => $e->filename, "line" => $e->lineno);
- array_unshift($trace, $twig);
- error(__("Error"), $prettify, $trace);
- }
- }
- }
-
- /**
- * Function: current
- * Returns a singleton reference to the current class.
- */
- public static function & current() {
- static $instance = null;
- return $instance = (empty($instance)) ? new self() : $instance ;
- }
- }
|