diff options
| author | Nathan Kinkade <nkinkade@nkinka.de> | 2011-01-14 01:12:32 +0000 | 
|---|---|---|
| committer | Nathan Kinkade <nkinkade@nkinka.de> | 2011-01-14 01:12:32 +0000 | 
| commit | 2898fe3b82ce10d045dd2c274a3290bacf209a00 (patch) | |
| tree | 5aced91bb92d8c9136cabf60ebc918248328907a /modules/gallery | |
| parent | 47cbef684d41a4d51a9848091997e10b909abf32 (diff) | |
| parent | e4a43c99e421c830e569eaae6294286ed51e0ad8 (diff) | |
Git pull from devel line.
Diffstat (limited to 'modules/gallery')
34 files changed, 441 insertions, 344 deletions
| diff --git a/modules/gallery/controllers/admin_languages.php b/modules/gallery/controllers/admin_languages.php index 573ededf..f96a0eb7 100644 --- a/modules/gallery/controllers/admin_languages.php +++ b/modules/gallery/controllers/admin_languages.php @@ -74,9 +74,11 @@ class Admin_Languages_Controller extends Admin_Controller {    private function _save_api_key($form) {      $new_key = $form->sharing->api_key->value; -    if ($new_key && !l10n_client::validate_api_key($new_key)) { -      $form->sharing->api_key->add_error("invalid", 1); -      $valid = false; +    if ($new_key) { +      list($connected, $valid) = l10n_client::validate_api_key($new_key); +      if (!$valid) { +        $form->sharing->api_key->add_error($connected ? "invalid" : "no_connection", 1); +      }      } else {        $valid = true;      } @@ -119,7 +121,9 @@ class Admin_Languages_Controller extends Admin_Controller {                    array("server-link" => html::mark_clean(html::anchor($server_link))))                : t("API key"))        ->value($api_key) -      ->error_messages("invalid", t("The API key you provided is invalid.")); +      ->error_messages("invalid", t("The API key you provided is invalid.")) +      ->error_messages( +        "no_connection", t("Could not connect to remote server to validate the API key."));      $group->submit("save")->value(t("Save settings"));      if ($api_key && $this->_outgoing_translations_count()) {        // TODO: UI improvement: hide API key / save button when API key is set. diff --git a/modules/gallery/controllers/admin_maintenance.php b/modules/gallery/controllers/admin_maintenance.php index 7729d797..80247a0f 100644 --- a/modules/gallery/controllers/admin_maintenance.php +++ b/modules/gallery/controllers/admin_maintenance.php @@ -27,7 +27,7 @@ class Admin_Maintenance_Controller extends Admin_Controller {        ->set("state", "stalled")        ->where("done", "=", 0)        ->where("state", "<>", "stalled") -      ->where(new Database_Expression("UNIX_TIMESTAMP(NOW()) - `updated` > 15")) +      ->where(db::expr("UNIX_TIMESTAMP(NOW()) - `updated` > 15"))        ->execute();      $stalled_count = $query->count();      if ($stalled_count) { diff --git a/modules/gallery/controllers/albums.php b/modules/gallery/controllers/albums.php index b0887195..3435465c 100644 --- a/modules/gallery/controllers/albums.php +++ b/modules/gallery/controllers/albums.php @@ -37,7 +37,7 @@ class Albums_Controller extends Items_Controller {      if ($show) {        $child = ORM::factory("item", $show); -      $index = $album->get_position($child); +      $index = item::get_position($child);        if ($index) {          $page = ceil($index / $page_size);          if ($page == 1) { @@ -61,20 +61,18 @@ class Albums_Controller extends Items_Controller {      }      $template = new Theme_View("page.html", "collection", "album"); -    $template->set_global("page", $page); -    $template->set_global("page_title", null); -    $template->set_global("max_pages", $max_pages); -    $template->set_global("page_size", $page_size); -    $template->set_global("item", $album); -    $template->set_global("children", $album->viewable()->children($page_size, $offset)); -    $template->set_global("children_count", $children_count); -    $template->set_global("parents", $album->parents()->as_array()); // view calls empty() on this +    $template->set_global( +      array("page" => $page, +            "page_title" => null, +            "max_pages" => $max_pages, +            "page_size" => $page_size, +            "item" => $album, +            "children" => $album->viewable()->children($page_size, $offset), +            "parents" => $album->parents()->as_array(), // view calls empty() on this +            "children_count" => $children_count));      $template->content = new View("album.html"); -    // We can't use math in ORM or the query builder, so do this by hand.  It's important -    // that we do this with math, otherwise concurrent accesses will damage accuracy. -    db::query("UPDATE {items} SET `view_count` = `view_count` + 1 WHERE `id` = $album->id") -      ->execute(); +    $album->increment_view_count();      print $template;    } diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php index 4b1a342a..64f8d22b 100644 --- a/modules/gallery/controllers/combined.php +++ b/modules/gallery/controllers/combined.php @@ -18,6 +18,9 @@   * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.   */  class Combined_Controller extends Controller { +  const ALLOW_MAINTENANCE_MODE = true; +  const ALLOW_PRIVATE_GALLERY = true; +    /**     * Return the combined Javascript bundle associated with the given key.     */ diff --git a/modules/gallery/controllers/file_proxy.php b/modules/gallery/controllers/file_proxy.php index 22854fbd..98f4e839 100644 --- a/modules/gallery/controllers/file_proxy.php +++ b/modules/gallery/controllers/file_proxy.php @@ -27,10 +27,13 @@   * input is sanitized against the database before we perform any file I/O.   */  class File_Proxy_Controller extends Controller { +  const ALLOW_PRIVATE_GALLERY = true;    public function __call($function, $args) { -    // request_uri: gallery3/var/trunk/albums/foo/bar.jpg +    // request_uri: gallery3/var/albums/foo/bar.jpg?m=1234      $request_uri = rawurldecode(Input::instance()->server("REQUEST_URI")); +    // get rid of query parameters +    // request_uri: gallery3/var/albums/foo/bar.jpg      $request_uri = preg_replace("/\?.*/", "", $request_uri);      // var_uri: gallery3/var/ @@ -42,13 +45,11 @@ class File_Proxy_Controller extends Controller {        throw new Kohana_404_Exception();      } +    // file_uri: albums/foo/bar.jpg      $file_uri = substr($request_uri, strlen($var_uri)); -    // Make sure that we don't leave the var dir -    if (strpos($file_uri, "..") !== false) { -      throw new Kohana_404_Exception(); -    } - +    // type: albums +    // path: foo/bar.jpg      list ($type, $path) = explode("/", $file_uri, 2);      if ($type != "resizes" && $type != "albums" && $type != "thumbs") {        throw new Kohana_404_Exception(); diff --git a/modules/gallery/controllers/login.php b/modules/gallery/controllers/login.php index 62d33345..adb2e50b 100644 --- a/modules/gallery/controllers/login.php +++ b/modules/gallery/controllers/login.php @@ -18,6 +18,8 @@   * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA.   */  class Login_Controller extends Controller { +  const ALLOW_MAINTENANCE_MODE = true; +  const ALLOW_PRIVATE_GALLERY = true;    public function ajax() {      $view = new View("login_ajax.html"); diff --git a/modules/gallery/controllers/movies.php b/modules/gallery/controllers/movies.php index 717eb8aa..7c85dd98 100644 --- a/modules/gallery/controllers/movies.php +++ b/modules/gallery/controllers/movies.php @@ -28,29 +28,29 @@ class Movies_Controller extends Items_Controller {      access::required("view", $movie);      $where = array(array("type", "!=", "album")); -    $position = $movie->parent()->get_position($movie, $where); +    $position = item::get_position($movie, $where);      if ($position > 1) {        list ($previous_item, $ignore, $next_item) = -        $movie->parent()->children(3, $position - 2, $where); +        $movie->parent()->viewable()->children(3, $position - 2, $where);      } else {        $previous_item = null;        list ($next_item) = $movie->parent()->viewable()->children(1, $position, $where);      }      $template = new Theme_View("page.html", "item", "movie"); -    $template->set_global("item", $movie); -    $template->set_global("children", array()); -    $template->set_global("children_count", 0); -    $template->set_global("parents", $movie->parents()->as_array()); -    $template->set_global("next_item", $next_item); -    $template->set_global("previous_item", $previous_item); -    $template->set_global("sibling_count", $movie->parent()->viewable()->children_count($where)); -    $template->set_global("position", $position); +    $template->set_global( +      array("item" => $movie, +            "children" => array(), +            "children_count" => 0, +            "parents" => $movie->parents()->as_array(), +            "next_item" => $next_item, +            "previous_item" => $previous_item, +            "sibling_count" => $movie->parent()->viewable()->children_count($where), +            "position" => $position));      $template->content = new View("movie.html"); -    $movie->view_count++; -    $movie->save(); +    $movie->increment_view_count();      print $template;    } diff --git a/modules/gallery/controllers/packager.php b/modules/gallery/controllers/packager.php index bd51b93c..9da34f9c 100644 --- a/modules/gallery/controllers/packager.php +++ b/modules/gallery/controllers/packager.php @@ -59,7 +59,7 @@ class Packager_Controller extends Controller {      // numbers, keeping our install.sql file more stable.      srand(0); -    foreach (array("gallery", "user", "comment", "organize", "info", "rest", +    foreach (array("gallery", "user", "comment", "organize", "info",                     "rss", "search", "slideshow", "tag") as $module_name) {        module::install($module_name);        module::activate($module_name); diff --git a/modules/gallery/controllers/photos.php b/modules/gallery/controllers/photos.php index b22ac8e5..4578747d 100644 --- a/modules/gallery/controllers/photos.php +++ b/modules/gallery/controllers/photos.php @@ -28,29 +28,29 @@ class Photos_Controller extends Items_Controller {      access::required("view", $photo);      $where = array(array("type", "!=", "album")); -    $position = $photo->parent()->get_position($photo, $where); +    $position = item::get_position($photo, $where);      if ($position > 1) {        list ($previous_item, $ignore, $next_item) = -        $photo->parent()->children(3, $position - 2, $where); +        $photo->parent()->viewable()->children(3, $position - 2, $where);      } else {        $previous_item = null;        list ($next_item) = $photo->parent()->viewable()->children(1, $position, $where);      }      $template = new Theme_View("page.html", "item", "photo"); -    $template->set_global("item", $photo); -    $template->set_global("children", array()); -    $template->set_global("children_count", 0); -    $template->set_global("parents", $photo->parents()->as_array()); -    $template->set_global("next_item", $next_item); -    $template->set_global("previous_item", $previous_item); -    $template->set_global("sibling_count", $photo->parent()->viewable()->children_count($where)); -    $template->set_global("position", $position); +    $template->set_global( +      array("item" => $photo, +            "children" => array(), +            "children_count" => 0, +            "parents" => $photo->parents()->as_array(), +            "next_item" => $next_item, +            "previous_item" => $previous_item, +            "sibling_count" => $photo->parent()->viewable()->children_count($where), +            "position" => $position));      $template->content = new View("photo.html"); -    $photo->view_count++; -    $photo->save(); +    $photo->increment_view_count();      print $template;    } diff --git a/modules/gallery/helpers/gallery.php b/modules/gallery/helpers/gallery.php index 2bb55ccb..282289b5 100644 --- a/modules/gallery/helpers/gallery.php +++ b/modules/gallery/helpers/gallery.php @@ -25,18 +25,27 @@ class gallery_Core {     * down for maintenance" page.     */    static function maintenance_mode() { -    // @todo: we need a mechanism here to identify controllers that are still legally accessible -    // when the entire Gallery is in maintenance mode.  Perhaps a controller class function or -    // method? -    // https://sourceforge.net/apps/trac/gallery/ticket/1411 -    if (Router::$controller != "login" && -        Router::$controller != "combined" && -        module::get_var("gallery", "maintenance_mode", 0) && +    if (module::get_var("gallery", "maintenance_mode", 0) &&          !identity::active_user()->admin) { -      Session::instance()->set("continue_url", url::abs_site("admin/maintenance")); -      Router::$controller = "login"; -      Router::$controller_path = MODPATH . "gallery/controllers/login.php"; -      Router::$method = "html"; +      try { +        $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller'); +        $allowed = $class->getConstant("ALLOW_MAINTENANCE_MODE") === true; +      } catch (ReflectionClass $e) { +        $allowed = false; +      } +      if (!$allowed) { +        if (Router::$controller == "admin") { +          // At this point we're in the admin theme and it doesn't have a themed login page, so +          // we can't just swap in the login controller and have it work.  So redirect back to the +          // root item where we'll run this code again with the site theme. +          url::redirect(item::root()->abs_url()); +        } else { +          Session::instance()->set("continue_url", url::abs_site("admin/maintenance")); +          Router::$controller = "login"; +          Router::$controller_path = MODPATH . "gallery/controllers/login.php"; +          Router::$method = "html"; +        } +      }      }    } @@ -45,26 +54,27 @@ class gallery_Core {     * the login page.     */    static function private_gallery() { -    // @todo: we need a mechanism here to identify controllers that are still legally accessible -    // when the entire Gallery is private.  Perhaps a controller class function or method? -    // https://sourceforge.net/apps/trac/gallery/ticket/1411 -    if (Router::$controller != "login" && -        Router::$controller != "combined" && -        Router::$controller != "digibug" && -        Router::$controller != "rest" && -        identity::active_user()->guest && +    if (identity::active_user()->guest &&          !access::user_can(identity::guest(), "view", item::root()) &&          php_sapi_name() != "cli") { -      if (Router::$controller == "admin") { -        // At this point we're in the admin theme and it doesn't have a themed login page, so -        // we can't just swap in the login controller and have it work.  So redirect back to the -        // root item where we'll run this code again with the site theme. -        url::redirect(item::root()->abs_url()); -      } else { -        Session::instance()->set("continue_url", url::abs_current()); -        Router::$controller = "login"; -        Router::$controller_path = MODPATH . "gallery/controllers/login.php"; -        Router::$method = "html"; +      try { +        $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller'); +        $allowed = $class->getConstant("ALLOW_PRIVATE_GALLERY") === true; +      } catch (ReflectionClass $e) { +        $allowed = false; +      } +      if (!$allowed) { +        if (Router::$controller == "admin") { +          // At this point we're in the admin theme and it doesn't have a themed login page, so +          // we can't just swap in the login controller and have it work.  So redirect back to the +          // root item where we'll run this code again with the site theme. +          url::redirect(item::root()->abs_url()); +        } else { +          Session::instance()->set("continue_url", url::abs_current()); +          Router::$controller = "login"; +          Router::$controller_path = MODPATH . "gallery/controllers/login.php"; +          Router::$method = "html"; +        }        }      }    } @@ -143,8 +153,15 @@ class gallery_Core {      if (is_string($file_name)) {        // make relative to DOCROOT        $parts = explode("/", $file_name); +      $count = count($parts);        foreach ($parts as $idx => $part) { -        if (in_array($part, array("application", "modules", "themes", "lib"))) { +        // If this part is "modules" or "themes" make sure that the part 2 after this +        // is the target directory, and if it is then we're done.  This check makes +        // sure that if Gallery is installed in a directory called "modules" or "themes" +        // We don't parse the directory structure incorrectly. +        if (in_array($part, array("modules", "themes")) && +            $idx + 2 < $count && +            $parts[$idx + 2] == $directory) {            break;          }          unset($parts[$idx]); diff --git a/modules/gallery/helpers/gallery_event.php b/modules/gallery/helpers/gallery_event.php index 5d3ee6ee..13a0bdb4 100644 --- a/modules/gallery/helpers/gallery_event.php +++ b/modules/gallery/helpers/gallery_event.php @@ -178,10 +178,6 @@ class gallery_event_Core {      }      Session::instance()->set("active_auth_timestamp", time());      auth::clear_failed_attempts($user); - -    if ($user->admin && ini_get("session.use_trans_sid")) { -      message::info(t("PHP is configured with <a href=\"url\">session.use_trans_sid</a> enabled which will cause random logouts.  Please disable this setting.", array("url" => "http://www.php.net/manual/en/session.configuration.php#ini.session.use-trans-sid"))); -    }    }    static function user_auth_failed($name) { @@ -377,7 +373,7 @@ class gallery_event_Core {          module::event("admin_menu", $admin_menu, $theme);          $settings_menu = $admin_menu->get("settings_menu"); -        sort($settings_menu->elements); +        uasort($settings_menu->elements, array("Menu", "title_comparator"));        }      }    } diff --git a/modules/gallery/helpers/gallery_graphics.php b/modules/gallery/helpers/gallery_graphics.php index 6038a95b..4cd7143e 100644 --- a/modules/gallery/helpers/gallery_graphics.php +++ b/modules/gallery/helpers/gallery_graphics.php @@ -56,7 +56,7 @@ class gallery_graphics_Core {      }      $dims = getimagesize($input_file); -    if (max($dims[0], $dims[1]) < min($options["width"], $options["height"])) { +    if (max($dims[0], $dims[1]) <= min($options["width"], $options["height"])) {        // Image would get upscaled; do nothing        copy($input_file, $output_file);      } else { @@ -75,7 +75,7 @@ class gallery_graphics_Core {    /**     * Overlay an image on top of the input file.     * -   * Valid options are: file, mime_type, position, transparency_percent, padding +   * Valid options are: file, position, transparency, padding     *     * Valid positions: northwest, north, northeast,     *                  west, center, east, diff --git a/modules/gallery/helpers/gallery_installer.php b/modules/gallery/helpers/gallery_installer.php index a6b8e6a2..f7b8da5f 100644 --- a/modules/gallery/helpers/gallery_installer.php +++ b/modules/gallery/helpers/gallery_installer.php @@ -44,7 +44,7 @@ class gallery_installer {                  `expiration` int(9) NOT NULL,                  `cache` longblob,                  PRIMARY KEY (`id`), -                KEY (`key`), +                UNIQUE KEY (`key`),                  KEY (`tags`))                  DEFAULT CHARSET=utf8;"); @@ -84,7 +84,7 @@ class gallery_installer {                   `album_cover_item_id` int(9) default NULL,                   `captured` int(9) default NULL,                   `created` int(9) default NULL, -                 `description` varchar(2048) default NULL, +                 `description` text default NULL,                   `height` int(9) default NULL,                   `left_ptr` int(9) NOT NULL,                   `level` int(9) NOT NULL, @@ -309,7 +309,7 @@ class gallery_installer {      module::set_var("gallery", "show_user_profiles_to", "registered_users");      module::set_var("gallery", "extra_binary_paths", "/usr/local/bin:/opt/local/bin:/opt/bin"); -    module::set_version("gallery", 41); +    module::set_version("gallery", 43);    }    static function upgrade($version) { @@ -503,7 +503,7 @@ class gallery_installer {        foreach (db::build()                 ->from("items")                 ->select("id", "slug") -               ->where(new Database_Expression("`slug` REGEXP '[^_A-Za-z0-9-]'"), "=", 1) +               ->where(db::expr("`slug` REGEXP '[^_A-Za-z0-9-]'"), "=", 1)                 ->execute() as $row) {          $new_slug = item::convert_filename_to_slug($row->slug);          if (empty($new_slug)) { @@ -540,7 +540,7 @@ class gallery_installer {      if ($version == 25) {        db::build()          ->update("items") -        ->set("title", new Database_Expression("`name`")) +        ->set("title", db::expr("`name`"))          ->and_open()          ->where("title", "IS", null)          ->or_where("title", "=", "") @@ -581,7 +581,7 @@ class gallery_installer {        $db->query("ALTER TABLE {modules} ADD COLUMN `weight` int(9) DEFAULT NULL");        $db->query("ALTER TABLE {modules} ADD KEY (`weight`)");        db::update("modules") -        ->set("weight", new Database_Expression("`id`")) +        ->set("weight", db::expr("`id`"))          ->execute();        module::set_version("gallery", $version = 32);      } @@ -642,6 +642,17 @@ class gallery_installer {        module::clear_var("gallery", "_cache");        module::set_version("gallery", $version = 41);      } + +    if ($version == 41) { +      $db->query("TRUNCATE TABLE {caches}"); +      $db->query("ALTER TABLE {caches} DROP INDEX `key`, ADD UNIQUE `key` (`key`)"); +      module::set_version("gallery", $version = 42); +    } + +    if ($version == 42) { +      $db->query("ALTER TABLE {items} CHANGE `description` `description` text DEFAULT NULL"); +      module::set_version("gallery", $version = 43); +    }    }    static function uninstall() { diff --git a/modules/gallery/helpers/gallery_task.php b/modules/gallery/helpers/gallery_task.php index e69ff91a..9ccff152 100644 --- a/modules/gallery/helpers/gallery_task.php +++ b/modules/gallery/helpers/gallery_task.php @@ -74,7 +74,7 @@ class gallery_task_Core {        // Choose the dirty images in a random order so that if we run this task multiple times        // concurrently each task is rebuilding different images simultaneously.        $result = graphics::find_dirty_images_query()->select("id") -        ->select(new Database_Expression("RAND() as r")) +        ->select(db::expr("RAND() as r"))          ->order_by("r", "ASC")          ->execute();        $total_count = $task->get("total_count", $result->count()); @@ -608,7 +608,7 @@ class gallery_task_Core {    static function find_dupe_slugs() {      return db::build()        ->select_distinct( -        array("parent_slug" => new Database_Expression("CONCAT(`parent_id`, ':', LOWER(`slug`))"))) +        array("parent_slug" => db::expr("CONCAT(`parent_id`, ':', LOWER(`slug`))")))        ->select("id")        ->select(array("C" => "COUNT(\"*\")"))        ->from("items") @@ -620,7 +620,7 @@ class gallery_task_Core {    static function find_dupe_names() {      return db::build()        ->select_distinct( -        array("parent_name" => new Database_Expression("CONCAT(`parent_id`, ':', LOWER(`name`))"))) +        array("parent_name" => db::expr("CONCAT(`parent_id`, ':', LOWER(`name`))")))        ->select("id")        ->select(array("C" => "COUNT(\"*\")"))        ->from("items") diff --git a/modules/gallery/helpers/graphics.php b/modules/gallery/helpers/graphics.php index edba6b76..18820ed7 100644 --- a/modules/gallery/helpers/graphics.php +++ b/modules/gallery/helpers/graphics.php @@ -313,60 +313,42 @@ class graphics_Core {        $toolkits->graphicsmagick->installed = false;        $toolkits->graphicsmagick->error = t("GraphicsMagick requires the <b>exec</b> function");      } else { -      gallery::set_path_env( -        array(module::get_var("gallery", "graphics_toolkit_path"), -              getenv("PATH"), -              module::get_var("gallery", "extra_binary_paths"))); +      // ImageMagick & GraphicsMagick +      $magick_kits = array( +          "imagemagick" => array( +            "name" => "ImageMagick", "binary" => "convert", "version" => "convert -v", +            "version_regex" => "/Version: \S+ (\S+)/"), +          "graphicsmagick" => array( +            "name" => "GraphicsMagick", "binary" => "gm", "version" => "gm version", +            "version_regex" => "/\S+ (\S+)/")); +      // Loop through the kits +      foreach ($magick_kits as $index => $settings) { +        $path = system::find_binary( +          $settings["binary"], module::get_var("gallery", "graphics_toolkit_path")); +        $toolkits->$index->name = $settings["name"]; +        if ($path) { +          if (@is_file($path) && +              preg_match($settings["version_regex"], shell_exec($settings["version"]), $matches)) { +            $version = $matches[1]; -      // @todo: consider refactoring the two segments below into a loop since they are so -      // similar. - -      // ImageMagick -      $path = exec("which convert"); -      $toolkits->imagemagick->name = "ImageMagick"; -      if ($path) { -        if (@is_file($path)) { -          preg_match('/Version: \S+ (\S+)/', `convert -v`, $matches); -          $version = $matches[1]; - -          $toolkits->imagemagick->installed = true; -          $toolkits->imagemagick->version = $version; -          $toolkits->imagemagick->binary = $path; -          $toolkits->imagemagick->dir = dirname($path); -          $toolkits->imagemagick->rotate = true; -          $toolkits->imagemagick->sharpen = true; -        } else { -          $toolkits->imagemagick->installed = false; -          $toolkits->imagemagick->error = -            t("ImageMagick is installed, but PHP's open_basedir restriction prevents Gallery from using it."); -        } -      } else { -        $toolkits->imagemagick->installed = false; -        $toolkits->imagemagick->error = t("We could not locate ImageMagick on your system."); -      } - -      // GraphicsMagick -      $path = exec("which gm"); -      $toolkits->graphicsmagick->name = "GraphicsMagick"; -      if ($path) { -        if (@is_file($path)) { -          preg_match('/\S+ (\S+)/', `gm version`, $matches); -          $version = $matches[1]; - -          $toolkits->graphicsmagick->installed = true; -          $toolkits->graphicsmagick->version = $version; -          $toolkits->graphicsmagick->binary = $path; -          $toolkits->graphicsmagick->dir = dirname($path); -          $toolkits->graphicsmagick->rotate = true; -          $toolkits->graphicsmagick->sharpen = true; +            $toolkits->$index->installed = true; +            $toolkits->$index->version = $version; +            $toolkits->$index->binary = $path; +            $toolkits->$index->dir = dirname($path); +            $toolkits->$index->rotate = true; +            $toolkits->$index->sharpen = true; +          } else { +            $toolkits->$index->installed = false; +            $toolkits->$index->error = +              t("%toolkit_name is installed, but PHP's open_basedir restriction prevents Gallery from using it.", +                array("toolkit_name" => $settings["name"])); +          }          } else { -          $toolkits->graphicsmagick->installed = false; -          $toolkits->graphicsmagick->error = -            t("GraphicsMagick is installed, but PHP's open_basedir restriction prevents Gallery from using it."); +          $toolkits->$index->installed = false; +          $toolkits->$index->error = +            t("We could not locate %toolkit_name on your system.", +              array("toolkit_name" => $settings["name"]));          } -      } else { -        $toolkits->graphicsmagick->installed = false; -        $toolkits->graphicsmagick->error = t("We could not locate GraphicsMagick on your system.");        }      } diff --git a/modules/gallery/helpers/item.php b/modules/gallery/helpers/item.php index 29dd8603..8aa14934 100644 --- a/modules/gallery/helpers/item.php +++ b/modules/gallery/helpers/item.php @@ -304,4 +304,92 @@ class item_Core {        ->where("rand_key", "<", random::percent())        ->order_by("rand_key", "DESC");    } + +  /** +   * Find the position of the given item in its parent album.  The resulting +   * value is 1-indexed, so the first child in the album is at position 1. +   * +   * @param Item_Model $item +   * @param array      $where an array of arrays, each compatible with ORM::where() +   */ +  static function get_position($item, $where=array()) { +    $album = $item->parent(); + +    if (!strcasecmp($album->sort_order, "DESC")) { +      $comp = ">"; +    } else { +      $comp = "<"; +    } +    $query_model = ORM::factory("item"); + +    // If the comparison column has NULLs in it, we can't use comparators on it +    // and will have to deal with it the hard way. +    $count = $query_model->viewable() +      ->where("parent_id", "=", $album->id) +      ->where($album->sort_column, "IS", null) +      ->merge_where($where) +      ->count_all(); + +    if (empty($count)) { +      // There are no NULLs in the sort column, so we can just use it directly. +      $sort_column = $album->sort_column; + +      $position = $query_model->viewable() +        ->where("parent_id", "=", $album->id) +        ->where($sort_column, $comp, $item->$sort_column) +        ->merge_where($where) +        ->count_all(); + +      // We stopped short of our target value in the sort (notice that we're +      // using a inequality comparator above) because it's possible that we have +      // duplicate values in the sort column.  An equality check would just +      // arbitrarily pick one of those multiple possible equivalent columns, +      // which would mean that if you choose a sort order that has duplicates, +      // it'd pick any one of them as the child's "position". +      // +      // Fix this by doing a 2nd query where we iterate over the equivalent +      // columns and add them to our position count. +      foreach ($query_model->viewable() +               ->select("id") +               ->where("parent_id", "=", $album->id) +               ->where($sort_column, "=", $item->$sort_column) +               ->merge_where($where) +               ->order_by(array("id" => "ASC")) +               ->find_all() as $row) { +        $position++; +        if ($row->id == $item->id) { +          break; +        } +      } +    } else { +      // There are NULLs in the sort column, so we can't use MySQL comparators. +      // Fall back to iterating over every child row to get to the current one. +      // This can be wildly inefficient for really large albums, but it should +      // be a rare case that the user is sorting an album with null values in +      // the sort column. +      // +      // Reproduce the children() functionality here using Database directly to +      // avoid loading the whole ORM for each row. +      $order_by = array($album->sort_column => $album->sort_order); +      // Use id as a tie breaker +      if ($album->sort_column != "id") { +        $order_by["id"] = "ASC"; +      } + +      $position = 0; +      foreach ($query_model->viewable() +               ->select("id") +               ->where("parent_id", "=", $album->id) +               ->merge_where($where) +               ->order_by($order_by) +               ->find_all() as $row) { +        $position++; +        if ($row->id == $item->id) { +          break; +        } +      } +    } + +    return $position; +  }  }
\ No newline at end of file diff --git a/modules/gallery/helpers/l10n_client.php b/modules/gallery/helpers/l10n_client.php index 8c2685a8..8fc66b68 100644 --- a/modules/gallery/helpers/l10n_client.php +++ b/modules/gallery/helpers/l10n_client.php @@ -55,15 +55,24 @@ class l10n_client_Core {      $url = self::_server_url("status");      $signature = self::_sign($version, $api_key); -    list ($response_data, $response_status) = remote::post( -      $url, array("version" => $version, -                  "client_token" => l10n_client::client_token(), -                  "signature" => $signature, -                  "uid" => l10n_client::server_uid($api_key))); +    try { +      list ($response_data, $response_status) = remote::post( +        $url, array("version" => $version, +                    "client_token" => l10n_client::client_token(), +                    "signature" => $signature, +                    "uid" => l10n_client::server_uid($api_key))); +    } catch (ErrorException $e) { +      // Log the error, but then return a "can't make connection" error +      Kohana_Log::add("error", $e->getMessage() . "\n" . $e->getTraceAsString()); +    } +    if (!isset($response_data) && !isset($response_status)) { +      return array(false, false); +    } +      if (!remote::success($response_status)) { -      return false; +      return array(true, false);      } -    return true; +    return array(true, true);    }    /** diff --git a/modules/gallery/helpers/locales.php b/modules/gallery/helpers/locales.php index 565e9da8..d06bb319 100644 --- a/modules/gallery/helpers/locales.php +++ b/modules/gallery/helpers/locales.php @@ -64,6 +64,7 @@ class locales_Core {    // @todo Might want to add a localizable language name as well.    // ref: http://cldr.unicode.org/    // ref: http://cldr.unicode.org/index/cldr-spec/picking-the-right-language-code +  // ref: http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/likely_subtags.html    private static function _init_language_data() {      $l["af_ZA"] = "Afrikaans";                // Afrikaans      $l["ar_SA"] = "العربية";                   // Arabic @@ -88,6 +89,7 @@ class locales_Core {      $l["fr_FR"] = "Français";                 // French      $l["ga_IE"] = "Gaeilge";                  // Irish      $l["he_IL"] = "עברית";                    // Hebrew +    $l["hr_HR"] = "hr̀vātskī";                 // Croatian      $l["hu_HU"] = "Magyar";                   // Hungarian      $l["is_IS"] = "Icelandic";                // Icelandic      $l["it_IT"] = "Italiano";                 // Italian diff --git a/modules/gallery/helpers/module.php b/modules/gallery/helpers/module.php index 2b446daa..6efe6162 100644 --- a/modules/gallery/helpers/module.php +++ b/modules/gallery/helpers/module.php @@ -168,7 +168,7 @@ class module_Core {      if (method_exists($installer_class, "install")) {        call_user_func_array(array($installer_class, "install"), array());      } else { -      module::set_version($module_name, 1); +      module::set_version($module_name, module::available()->$module_name->code_version);      }      // Set the weight of the new module, which controls the order in which the modules are @@ -488,7 +488,7 @@ class module_Core {    static function incr_var($module_name, $name, $increment=1) {      db::build()        ->update("vars") -      ->set("value", new Database_Expression("`value` + $increment")) +      ->set("value", db::expr("`value` + $increment"))        ->where("module_name", "=", $module_name)        ->where("name", "=", $name)        ->execute(); diff --git a/modules/gallery/helpers/movie.php b/modules/gallery/helpers/movie.php index 0895c5f4..dd0b437e 100644 --- a/modules/gallery/helpers/movie.php +++ b/modules/gallery/helpers/movie.php @@ -83,22 +83,18 @@ class movie_Core {      }    } +  /** +   * Return the path to the ffmpeg binary if one exists and is executable, or null. +   */    static function find_ffmpeg() {      if (!($ffmpeg_path = module::get_var("gallery", "ffmpeg_path")) || !file_exists($ffmpeg_path)) { -      gallery::set_path_env( -        array(module::get_var("gallery", "graphics_toolkit_path"), -              getenv("PATH"), -              module::get_var("gallery", "extra_binary_paths"))); -      if (function_exists("exec")) { -        $ffmpeg_path = exec("which ffmpeg"); -      } - +      $ffmpeg_path = system::find_binary( +        "ffmpeg", module::get_var("gallery", "graphics_toolkit_path"));        module::set_var("gallery", "ffmpeg_path", $ffmpeg_path);      }      return $ffmpeg_path;    } -    /**     * Return the width, height, mime_type and extension of the given movie file.     */ diff --git a/modules/gallery/helpers/system.php b/modules/gallery/helpers/system.php new file mode 100644 index 00000000..4a6a3c0f --- /dev/null +++ b/modules/gallery/helpers/system.php @@ -0,0 +1,43 @@ +<?php defined("SYSPATH") or die("No direct script access."); +/** + * Gallery - a web based photo album viewer and editor + * Copyright (C) 2000-2010 Bharat Mediratta + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA  02110-1301, USA. + */ +class system_Core { +  /** +   * Return the path to an executable version of the named binary, or null. +   * Traverse the PATH environment variable looking for the given file.  If +   * the $priority_path variable is set, check that path first. +   */ +  static function find_binary($binary, $priority_path=null) { +    $paths = array_merge( +      explode(":", getenv("PATH")), +      explode(":", module::get_var("gallery", "extra_binary_paths"))); +    if ($priority_path) { +      array_unshift($paths, $priority_path); +    } + +    foreach ($paths as $path) { +      $candidate = "$path/$binary"; +      // @suppress errors below to avoid open_basedir issues +      if (@file_exists($candidate) && @is_executable($candidate)) { +        return $candidate; +      } +    } +    return null; +  } +}
\ No newline at end of file diff --git a/modules/gallery/libraries/Admin_View.php b/modules/gallery/libraries/Admin_View.php index 11f8ad14..1a633a34 100644 --- a/modules/gallery/libraries/Admin_View.php +++ b/modules/gallery/libraries/Admin_View.php @@ -34,11 +34,11 @@ class Admin_View_Core extends Gallery_View {        $this->theme_name = Input::instance()->get("theme", $this->theme_name);      }      $this->sidebar = ""; -    $this->set_global("theme", $this); -    $this->set_global("user", identity::active_user()); -    $this->set_global("page_type", "admin"); -    $this->set_global("page_subtype", $name); -    $this->set_global("page_title", null); +    $this->set_global(array("theme" => $this, +                            "user" => identity::active_user(), +                            "page_type" => "admin", +                            "page_subtype" => $name, +                            "page_title" => null));    }    public function admin_menu() { @@ -46,7 +46,7 @@ class Admin_View_Core extends Gallery_View {      module::event("admin_menu", $menu, $this);      $settings_menu = $menu->get("settings_menu"); -    sort($settings_menu->elements); +    uasort($settings_menu->elements, array("Menu", "title_comparator"));      return $menu->render();    } @@ -96,11 +96,6 @@ class Admin_View_Core extends Gallery_View {          }        } -      if ($function == "admin_head") { -        array_unshift($blocks, $this->combine_files($this->scripts, "javascript")); -        array_unshift($blocks, $this->combine_files($this->css, "css")); -      } -        if (Session::instance()->get("debug")) {          if ($function != "admin_head") {            array_unshift( diff --git a/modules/gallery/libraries/Gallery_View.php b/modules/gallery/libraries/Gallery_View.php index b45bb94a..8befda95 100644 --- a/modules/gallery/libraries/Gallery_View.php +++ b/modules/gallery/libraries/Gallery_View.php @@ -19,18 +19,35 @@   */  class Gallery_View_Core extends View {    protected $theme_name = null; -  protected $scripts = array(); -  protected $css = array(); +  protected $combine_queue = array();    /** -   * Add a script to the combined scripts list. +   * Begin gather up scripts or css files so that they can be combined into a single request. +   * +   * @param $types  a comma separated list of types to combine, eg "script,css" +   */ +  public function start_combining($types) { +    foreach (explode(",", $types) as $type) { +      $this->combine_queue[$type] = array(); +    } +  } + +  /** +   * If script combining is enabled, add this script to the list of scripts that will be +   * combined into a single script element.  When combined, the order of scripts is preserved. +   *     * @param $file  the file name or path of the script to include. If a path is specified then     *               it needs to be relative to DOCROOT. Just specifying a file name will result     *               in searching Kohana's cascading file system. +   * @param $group the group of scripts to combine this with.  defaults to "core"     */ -  public function script($file) { +  public function script($file, $group="core") {      if (($path = gallery::find_file("js", $file, false))) { -      $this->scripts[$path] = 1; +      if (isset($this->combine_queue["script"])) { +        $this->combine_queue["script"][$group][$path] = 1; +      } else { +        return html::script($path); +      }      } else {        Kohana_Log::add("error", "Can't find script file: $file");      } @@ -46,14 +63,22 @@ class Gallery_View_Core extends View {    }    /** -   * Add a css file to the combined css list. -   * @param $file  the file name or path of the script to include. If a path is specified then +   * If css combining is enabled, add this css to the list of css that will be +   * combined into a single style element.  When combined, the order of style elements +   * is preserved. +   * +   * @param $file  the file name or path of the css to include. If a path is specified then     *               it needs to be relative to DOCROOT. Just specifying a file name will result     *               in searching Kohana's cascading file system. +   * @param $group the group of css to combine this with.  defaults to "core"     */ -  public function css($file) { +  public function css($file, $group="core") {      if (($path = gallery::find_file("css", $file, false))) { -      $this->css[$path] = 1; +      if (isset($this->combine_queue["css"])) { +        $this->combine_queue["css"][$group][$path] = 1; +      } else { +        return html::stylesheet($path); +      }      } else {        Kohana_Log::add("error", "Can't find css file: $file");      } @@ -61,11 +86,13 @@ class Gallery_View_Core extends View {    /**     * Combine a series of files into a single one and cache it in the database. +   * @param $type  the data type (script or css) +   * @param $group the group of scripts or css we want     */ -  protected function combine_files($paths, $type) { +  public function get_combined($type, $group="core") {      $links = array(); -    if (empty($paths)) { +    if (empty($this->combine_queue[$type][$group])) {        return;      } @@ -73,7 +100,7 @@ class Gallery_View_Core extends View {      // entries.      $key = array(url::abs_file("")); -    foreach (array_keys($paths) as $path) { +    foreach (array_keys($this->combine_queue[$type][$group]) as $path) {        $stats = stat($path);        // 7 == size, 9 == mtime, see http://php.net/stat        $key[] = "$path $stats[7] $stats[9]"; @@ -85,7 +112,7 @@ class Gallery_View_Core extends View {      if (empty($contents)) {        $contents = ""; -      foreach (array_keys($paths) as $path) { +      foreach (array_keys($this->combine_queue[$type][$group]) as $path) {          if ($type == "css") {            $contents .= "/* $path */\n" . $this->process_css($path) . "\n";          } else { @@ -103,12 +130,12 @@ class Gallery_View_Core extends View {        }      } +    unset($this->combine_queue[$type][$group]); +      if ($type == "css") { -      return "<!-- LOOKING FOR YOUR CSS? It's all been combined into the link below -->\n" . -        html::stylesheet("combined/css/$key", "screen,print,projection", true); +      return html::stylesheet("combined/css/$key", "screen,print,projection", true);      } else { -      return "<!-- LOOKING FOR YOUR JAVASCRIPT? It's all been combined into the link below -->\n" . -        html::script("combined/javascript/$key", true); +      return html::script("combined/javascript/$key", true);      }    } diff --git a/modules/gallery/libraries/MY_View.php b/modules/gallery/libraries/MY_View.php index ded77792..2230203a 100644 --- a/modules/gallery/libraries/MY_View.php +++ b/modules/gallery/libraries/MY_View.php @@ -23,8 +23,14 @@ class View extends View_Core {    /**     * Reimplement Kohana 2.3's View::set_global() functionality.     */ -  public function set_global($key, $value) { -    View::$global_data[$key] = $value; +  public function set_global($key, $value = NULL) { +    if (is_array($key)) { +      foreach ($key as $key2 => $value) { +        View::$global_data[$key2] = $value; +      } +    } else { +      View::$global_data[$key] = $value; +    }    }    public function is_set($key=null) { diff --git a/modules/gallery/libraries/Menu.php b/modules/gallery/libraries/Menu.php index 58852a72..78b60196 100644 --- a/modules/gallery/libraries/Menu.php +++ b/modules/gallery/libraries/Menu.php @@ -250,4 +250,8 @@ class Menu_Core extends Menu_Element {      $view->menu = $this;      return $view;    } + +  static function title_comparator($a, $b) { +    return strnatcasecmp((string)$a->label, (string)$b->label); +  }  } diff --git a/modules/gallery/libraries/ORM_MPTT.php b/modules/gallery/libraries/ORM_MPTT.php index f20fafa0..4556273c 100644 --- a/modules/gallery/libraries/ORM_MPTT.php +++ b/modules/gallery/libraries/ORM_MPTT.php @@ -54,12 +54,12 @@ class ORM_MPTT_Core extends ORM {          // Make a hole in the parent for this new item          db::build()            ->update($this->table_name) -          ->set("left_ptr", new Database_Expression("`left_ptr` + 2")) +          ->set("left_ptr", db::expr("`left_ptr` + 2"))            ->where("left_ptr", ">=", $parent->right_ptr)            ->execute();          db::build()            ->update($this->table_name) -          ->set("right_ptr", new Database_Expression("`right_ptr` + 2")) +          ->set("right_ptr", db::expr("`right_ptr` + 2"))            ->where("right_ptr", ">=", $parent->right_ptr)            ->execute();          $parent->right_ptr += 2; @@ -109,12 +109,12 @@ class ORM_MPTT_Core extends ORM {      try {        db::build()          ->update($this->table_name) -        ->set("left_ptr", new Database_Expression("`left_ptr` - 2")) +        ->set("left_ptr", db::expr("`left_ptr` - 2"))          ->where("left_ptr", ">", $this->right_ptr)          ->execute();        db::build()          ->update($this->table_name) -        ->set("right_ptr", new Database_Expression("`right_ptr` - 2")) +        ->set("right_ptr", db::expr("`right_ptr` - 2"))          ->where("right_ptr", ">", $this->right_ptr)          ->execute();      } catch (Exception $e) { @@ -253,7 +253,7 @@ class ORM_MPTT_Core extends ORM {          // Update the levels for the to-be-moved items          db::build()            ->update($this->table_name) -          ->set("level", new Database_Expression("`level` + $level_delta")) +          ->set("level", db::expr("`level` + $level_delta"))            ->where("left_ptr", ">=", $original_left_ptr)            ->where("right_ptr", "<=", $original_right_ptr)            ->execute(); @@ -262,12 +262,12 @@ class ORM_MPTT_Core extends ORM {        // Make a hole in the target for the move        db::build()          ->update($this->table_name) -        ->set("left_ptr", new Database_Expression("`left_ptr` + $size_of_hole")) +        ->set("left_ptr", db::expr("`left_ptr` + $size_of_hole"))          ->where("left_ptr", ">=", $target_right_ptr)          ->execute();        db::build()          ->update($this->table_name) -        ->set("right_ptr", new Database_Expression("`right_ptr` + $size_of_hole")) +        ->set("right_ptr", db::expr("`right_ptr` + $size_of_hole"))          ->where("right_ptr", ">=", $target_right_ptr)          ->execute(); @@ -290,8 +290,8 @@ class ORM_MPTT_Core extends ORM {        $new_offset = $target->right_ptr - $left_ptr;        db::build()          ->update($this->table_name) -        ->set("left_ptr", new Database_Expression("`left_ptr` + $new_offset")) -        ->set("right_ptr", new Database_Expression("`right_ptr` + $new_offset")) +        ->set("left_ptr", db::expr("`left_ptr` + $new_offset")) +        ->set("right_ptr", db::expr("`right_ptr` + $new_offset"))          ->where("left_ptr", ">=", $left_ptr)          ->where("right_ptr", "<=", $right_ptr)          ->execute(); @@ -299,12 +299,12 @@ class ORM_MPTT_Core extends ORM {        // Close the hole in the source's parent after the move        db::build()          ->update($this->table_name) -        ->set("left_ptr", new Database_Expression("`left_ptr` - $size_of_hole")) +        ->set("left_ptr", db::expr("`left_ptr` - $size_of_hole"))          ->where("left_ptr", ">", $right_ptr)          ->execute();        db::build()          ->update($this->table_name) -        ->set("right_ptr", new Database_Expression("`right_ptr` - $size_of_hole")) +        ->set("right_ptr", db::expr("`right_ptr` - $size_of_hole"))          ->where("right_ptr", ">", $right_ptr)          ->execute();      } catch (Exception $e) { diff --git a/modules/gallery/libraries/Theme_View.php b/modules/gallery/libraries/Theme_View.php index d22bb03a..04784ca1 100644 --- a/modules/gallery/libraries/Theme_View.php +++ b/modules/gallery/libraries/Theme_View.php @@ -37,11 +37,11 @@ class Theme_View_Core extends Gallery_View {      }      $this->item = null;      $this->tag = null; -    $this->set_global("theme", $this); -    $this->set_global("user", identity::active_user()); -    $this->set_global("page_type", $page_type); -    $this->set_global("page_subtype", $page_subtype); -    $this->set_global("page_title", null); +    $this->set_global(array("theme" => $this, +                            "user" => identity::active_user(), +                            "page_type" => $page_type, +                            "page_subtype" => $page_subtype, +                            "page_title" => null));      if ($page_type == "collection") {        $this->set_global("thumb_proportion", $this->thumb_proportion());      } @@ -236,13 +236,6 @@ class Theme_View_Core extends Gallery_View {      case "thumb_bottom":      case "thumb_info":      case "thumb_top": -      if ($function == "head") { -        // Stash any CSS we have already; that came from the theme and we want theme CSS to -        // override module CSs -        $save_css = $this->css; -        $this->css = array(); -      } -        $blocks = array();        if (method_exists("gallery_theme", $function)) {          switch (count($args)) { @@ -281,13 +274,6 @@ class Theme_View_Core extends Gallery_View {            array_merge(array($this), $args));        } -      if ($function == "head") { -        // Merge the theme CSS/JS at the end -        $this->css = array_merge($this->css, $save_css); -        array_unshift($blocks, $this->combine_files($this->scripts, "javascript")); -        array_unshift($blocks, $this->combine_files($this->css, "css")); -      } -        if (Session::instance()->get("debug")) {          if ($function != "head" && $function != "body_attributes") {            array_unshift( diff --git a/modules/gallery/libraries/drivers/Cache/Database.php b/modules/gallery/libraries/drivers/Cache/Database.php index b7822811..2e773ca4 100644 --- a/modules/gallery/libraries/drivers/Cache/Database.php +++ b/modules/gallery/libraries/drivers/Cache/Database.php @@ -25,20 +25,6 @@ class Cache_Database_Driver extends Cache_Driver {    protected $db;    /** -   * Checks if a cache id is already set. -   * -   * @param  string   cache id -   * @return boolean -   */ -  public function exists($id) { -    $count = db::build() -      ->where("key", "=", $id) -      ->where("expiration", ">=", time()) -      ->count_records("caches"); -    return $count > 0; -  } - -  /**     * Sets a cache item to the given data, tags, and lifetime.     *     * @param   array    assoc array of key => value pairs @@ -59,22 +45,15 @@ class Cache_Database_Driver extends Cache_Driver {        $lifetime += time();      } +    $db = Database::instance(); +    $tags = $db->escape($tags);      foreach ($items as $id => $data) { -      if ($this->exists($id)) { -        $status = db::build() -          ->update("caches") -          ->set("tags", $tags) -          ->set("expiration", $lifetime) -          ->set("cache", serialize($data)) -          ->where("key", "=", $id) -          ->execute(); -      } else { -        $status = db::build() -          ->insert("caches") -          ->columns("key", "tags", "expiration", "cache") -          ->values($id, $tags, $lifetime, serialize($data)) -          ->execute(); -      } +      $id = $db->escape($id); +      $data = $db->escape(serialize($data)); +      $db->query("INSERT INTO {caches} (`key`, `tags`, `expiration`, `cache`) +                  VALUES ('$id', '$tags', $lifetime, '$data') +                  ON DUPLICATE KEY UPDATE `tags` = VALUES(tags), `expiration` = VALUES(expiration), +                  `cache` = VALUES(cache)");      }      return true; diff --git a/modules/gallery/models/item.php b/modules/gallery/models/item.php index fc5c3ff9..47b062b8 100644 --- a/modules/gallery/models/item.php +++ b/modules/gallery/models/item.php @@ -546,83 +546,12 @@ class Item_Model_Core extends ORM_MPTT {    /**     * Find the position of the given child id in this album.  The resulting value is 1-indexed, so     * the first child in the album is at position 1. +   * +   * This method stands as a backward compatibility for gallery 3.0, and will +   * be deprecated in version 3.1.     */    public function get_position($child, $where=array()) { -    if (!strcasecmp($this->sort_order, "DESC")) { -      $comp = ">"; -    } else { -      $comp = "<"; -    } -    $db = db::build(); - -    // If the comparison column has NULLs in it, we can't use comparators on it and will have to -    // deal with it the hard way. -    $count = $db->from("items") -      ->where("parent_id", "=", $this->id) -      ->where($this->sort_column, "IS", null) -      ->merge_where($where) -      ->count_records(); - -    if (empty($count)) { -      // There are no NULLs in the sort column, so we can just use it directly. -      $sort_column = $this->sort_column; - -      $position = $db->from("items") -        ->where("parent_id", "=", $this->id) -        ->where($sort_column, $comp, $child->$sort_column) -        ->merge_where($where) -        ->count_records(); - -      // We stopped short of our target value in the sort (notice that we're using a < comparator -      // above) because it's possible that we have duplicate values in the sort column.  An -      // equality check would just arbitrarily pick one of those multiple possible equivalent -      // columns, which would mean that if you choose a sort order that has duplicates, it'd pick -      // any one of them as the child's "position". -      // -      // Fix this by doing a 2nd query where we iterate over the equivalent columns and add them to -      // our base value. -      foreach ($db -               ->select("id") -               ->from("items") -               ->where("parent_id", "=", $this->id) -               ->where($sort_column, "=", $child->$sort_column) -               ->merge_where($where) -               ->order_by(array("id" => "ASC")) -               ->execute() as $row) { -        $position++; -        if ($row->id == $child->id) { -          break; -        } -      } -    } else { -      // There are NULLs in the sort column, so we can't use MySQL comparators.  Fall back to -      // iterating over every child row to get to the current one.  This can be wildly inefficient -      // for really large albums, but it should be a rare case that the user is sorting an album -      // with null values in the sort column. -      // -      // Reproduce the children() functionality here using Database directly to avoid loading the -      // whole ORM for each row. -      $order_by = array($this->sort_column => $this->sort_order); -      // Use id as a tie breaker -      if ($this->sort_column != "id") { -        $order_by["id"] = "ASC"; -      } - -      $position = 0; -      foreach ($db->select("id") -               ->from("items") -               ->where("parent_id", "=", $this->id) -               ->merge_where($where) -               ->order_by($order_by) -               ->execute() as $row) { -        $position++; -        if ($row->id == $child->id) { -          break; -        } -      } -    } - -    return $position; +    return item::get_position($child, $where);    }    /** @@ -653,7 +582,7 @@ class Item_Model_Core extends ORM_MPTT {    /**     * Calculate the largest width/height that fits inside the given maximum, while preserving the -   * aspect ratio. +   * aspect ratio.  Don't upscale.     * @param int $max Maximum size of the largest dimension     * @return array     */ @@ -661,6 +590,10 @@ class Item_Model_Core extends ORM_MPTT {      $width = $this->thumb_width;      $height = $this->thumb_height; +    if ($width <= $max && $height <= $max) { +        return array($height, $width); +    } +      if ($height) {        if (isset($max)) {          if ($width > $height) { @@ -1078,6 +1011,16 @@ class Item_Model_Core extends ORM_MPTT {      return $data;    } +  /** +   * Increments the view counter of this item +   * We can't use math in ORM or the query builder, so do this by hand.  It's important +   * that we do this with math, otherwise concurrent accesses will damage accuracy. +   */ +  public function increment_view_count() { +    db::query("UPDATE {items} SET `view_count` = `view_count` + 1 WHERE `id` = $this->id") +      ->execute(); +  } +    private function _cache_buster($path) {      return "?m=" . (string)(file_exists($path) ? filemtime($path) : 0);    } diff --git a/modules/gallery/module.info b/modules/gallery/module.info index 2b684e5e..eb579ab6 100644 --- a/modules/gallery/module.info +++ b/modules/gallery/module.info @@ -1,3 +1,3 @@  name = "Gallery 3"  description = "Gallery core application" -version = 41 +version = 43 diff --git a/modules/gallery/tests/Gallery_Installer_Test.php b/modules/gallery/tests/Gallery_Installer_Test.php index 67e712de..d34c3b0e 100644 --- a/modules/gallery/tests/Gallery_Installer_Test.php +++ b/modules/gallery/tests/Gallery_Installer_Test.php @@ -35,7 +35,7 @@ class Gallery_Installer_Test extends Gallery_Unit_Test_Case {    public function install_creates_root_item_test() {      $max_right_ptr = ORM::factory("item") -      ->select(new Database_Expression("MAX(`right_ptr`) AS `right_ptr`")) +      ->select(db::expr("MAX(`right_ptr`) AS `right_ptr`"))        ->find()->right_ptr;      $root = ORM::factory('item')->find(1);      $this->assert_equal("Gallery", $root->title); diff --git a/modules/gallery/tests/Item_Model_Test.php b/modules/gallery/tests/Item_Model_Test.php index 4987d2f9..0554c0e2 100644 --- a/modules/gallery/tests/Item_Model_Test.php +++ b/modules/gallery/tests/Item_Model_Test.php @@ -362,11 +362,11 @@ class Item_Model_Test extends Gallery_Unit_Test_Case {    }    public function as_restful_array_with_edit_bit_test() { -    $response = item::root()->as_restful_array(true); +    $response = item::root()->as_restful_array();      $this->assert_true($response["can_edit"]);      identity::set_active_user(identity::guest()); -    $response = item::root()->as_restful_array(true); +    $response = item::root()->as_restful_array();      $this->assert_false($response["can_edit"]);    } diff --git a/modules/gallery/tests/xss_data.txt b/modules/gallery/tests/xss_data.txt index 7c5e803d..366391cf 100644 --- a/modules/gallery/tests/xss_data.txt +++ b/modules/gallery/tests/xss_data.txt @@ -399,17 +399,19 @@ themes/wind/views/dynamic.html.php                           29  DIRTY    $theme  themes/wind/views/movie.html.php                             5   DIRTY    $theme->paginator()  themes/wind/views/movie.html.php                             9   DIRTY    $item->movie_img(array("class"=>"g-movie","id"=>"g-item-id-{$item->id}"))  themes/wind/views/page.html.php                              9   DIRTY    $page_title -themes/wind/views/page.html.php                              32  DIRTY_JS $theme->url() -themes/wind/views/page.html.php                              41  DIRTY    $new_width -themes/wind/views/page.html.php                              42  DIRTY    $new_height -themes/wind/views/page.html.php                              43  DIRTY    $thumb_proportion -themes/wind/views/page.html.php                              80  DIRTY    $header_text -themes/wind/views/page.html.php                              82  DIRTY_JS item::root()->url() -themes/wind/views/page.html.php                              86  DIRTY    $theme->user_menu() -themes/wind/views/page.html.php                              107 DIRTY_JS $parent->url($parent->id==$theme->item()->parent_id?"show={$theme->item()->id}":null) -themes/wind/views/page.html.php                              128 DIRTY    $content -themes/wind/views/page.html.php                              134 DIRTY    newView("sidebar.html") -themes/wind/views/page.html.php                              141 DIRTY    $footer_text +themes/wind/views/page.html.php                              12  DIRTY    $theme->item()->title +themes/wind/views/page.html.php                              16  DIRTY    item::root()->title +themes/wind/views/page.html.php                              26  DIRTY_JS $theme->url() +themes/wind/views/page.html.php                              35  DIRTY    $new_width +themes/wind/views/page.html.php                              36  DIRTY    $new_height +themes/wind/views/page.html.php                              37  DIRTY    $thumb_proportion +themes/wind/views/page.html.php                              74  DIRTY    $header_text +themes/wind/views/page.html.php                              76  DIRTY_JS item::root()->url() +themes/wind/views/page.html.php                              80  DIRTY    $theme->user_menu() +themes/wind/views/page.html.php                              101 DIRTY_JS $parent->url($parent->id==$theme->item()->parent_id?"show={$theme->item()->id}":null) +themes/wind/views/page.html.php                              122 DIRTY    $content +themes/wind/views/page.html.php                              128 DIRTY    newView("sidebar.html") +themes/wind/views/page.html.php                              135 DIRTY    $footer_text  themes/wind/views/paginator.html.php                         33  DIRTY_JS $first_page_url  themes/wind/views/paginator.html.php                         42  DIRTY_JS $previous_page_url  themes/wind/views/paginator.html.php                         70  DIRTY_JS $next_page_url diff --git a/modules/gallery/views/movieplayer.html.php b/modules/gallery/views/movieplayer.html.php index 2e79b620..5c280a36 100644 --- a/modules/gallery/views/movieplayer.html.php +++ b/modules/gallery/views/movieplayer.html.php @@ -9,6 +9,9 @@        provider: "pseudostreaming"      },      { +      clip: { +        scaling: 'fit' +      },        plugins: {          pseudostreaming: {            url: "<?= url::abs_file("lib/flowplayer.pseudostreaming.swf") ?>" | 
