<?php
/*
 * $RCSfile: Gallery1DataParser.class,v $
 *
 * Gallery - a web based photo album viewer and editor
 * Copyright (C) 2000-2005 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.
 */
/**
 * @version $Revision: 1.36 $ $Date: 2005/08/23 03:49:46 $
 * @package Migrate
 * @author Jesse Mullan <jmullan@visi.com>
 */
/**
 * This class provides an API for parsing Gallery 1 data files
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Gallery1DataParser {

    /**
     * Verify that the given path holds an albumdb and that the albumdb is readable
     *
     * @param string Path to albums
     * @return boolean True if the path is valid, otherwise false
     */
    function isValidAlbumsPath($path) {
	global $gallery;
	$platform = $gallery->getPlatform();

	if ($platform->file_exists($path . 'albumdb.dat')
	    && $platform->is_readable($path . 'albumdb.dat')) {
	    return true;
	} else {
	    return false;
	}
    }

    /**
     * Load and return user metadata from given file
     *
     * @param string Path to user file to unserialize
     * @return array object GalleryStatus a status code,
     *               object Unserialized user metadata
     */
    function loadFile($fileName) {
        global $gallery;
        $platform = $gallery->getPlatform();

	if (!$platform->file_exists($fileName) || !$platform->is_readable($fileName)) {
	    if ($platform->file_exists($fileName . '.bak') &&
		    $platform->is_readable($fileName . '.bak')) {
		$fileName .= '.bak';
	    } else {
		return array(GalleryStatus::error(ERROR_BAD_PARAMETER, __FILE__, __LINE__,
					      "Missing or not readable file: $fileName"), null);
	    }
	}
        $tmp = $platform->file($fileName);

	if (empty($tmp)) {
	    return array(GalleryStatus::error(ERROR_MISSING_VALUE, __FILE__, __LINE__), null);
	}

	$tmp = join('', $tmp);

	/*
	 * We renamed User.php to Gallery_User.php in v1.2, so port forward
	 * any saved user objects.
	 */
	if (!strcmp(substr($tmp, 0, 10), 'O:4:"user"')) {
	    $tmp = ereg_replace('O:4:"user"', 'O:12:"gallery_user"', $tmp);
	}

	$object = unserialize($tmp);
	return array(GalleryStatus::success(), $object);
    }

    /**
     * Fetch an array of albums from a given path
     *
     * @param string Path to albums directory
     * @return array object GalleryStatus a status code,
     *               array of objects
     */
    function getAlbumList($path) {
        global $gallery;
        $platform = $gallery->getPlatform();
	$slash = $platform->getDirectorySeparator();

	list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}

	/* TODO: check that there is an $albumOrder */
	foreach ($albumOrder as $albumName){
	    list ($ret, $albumFields) =
		Gallery1DataParser::loadAlbumFields($path . $albumName . $slash);
	    if ($ret->isError()) {
		return array($ret->wrap(__FILE__, __LINE__),'');
	    }
	    $albumList[$albumName] = $albumFields;
	}

	return array(GalleryStatus::success(), $albumList);
    }

    /**
     * Fetch an associative array of parentalbum names from a given path to
     * gallery1 albums
     *
     * @param string Path to albums directory
     * @return array object GalleryStatus a status code,
     *               array of albums and their parents
     */
    function getParentAlbumList($path) {
	global $gallery;
        $platform = $gallery->getPlatform();
	$slash = $platform->getDirectorySeparator();

	list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}

	foreach($albumOrder as $albumName){
	    list ($ret, $albumFields) =
		Gallery1DataParser::loadAlbumFields($path . $albumName . $slash);
	    if ($ret->isError()) {
		return array($ret->wrap(__FILE__, __LINE__),'');
	    }
	    $parentAlbumList[$albumName] = $albumFields['parentAlbumName'];
	}
	return array(GalleryStatus::success(), $parentAlbumList);
    }

    /**
     * Build a data tree of albums
     *
     * @param string Path to albums directory
     * @return array object GalleryStatus a status code,
     *               array of albumnames and their children, and their children...
     */
    function getAlbumHierarchy($path) {
	list ($ret, $parentAlbumList) = Gallery1DataParser::getParentAlbumList($path);
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}

	foreach($parentAlbumList as $myName => $parentName) {
	    if (!isset($tempAlbums[$myName])) {
		$tempAlbums[$myName] = array();
	    }
	    if (empty($parentName) || $parentName == '.root') {
		$hierarchy[$myName] = &$tempAlbums[$myName];
	    } else {
		if (!isset($tempAlbums[$parentName])) {
		    $tempAlbums[$parentName] = array();
		}
		$tempAlbums[$parentName][$myName] = &$tempAlbums[$myName];
	    }
	}
	return array(GalleryStatus::success(), $hierarchy);
    }

    /**
     * Fetch an array of albums with no parents
     *
     * @param string Path to albums directory
     * @return array object GalleryStatus a status code,
     *               array of albumnames
     */
    function getRootAlbums($path) {
	global $gallery;
	$platform = $gallery->getPlatform();
	$slash = $platform->getDirectorySeparator();

	list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}

	foreach($albumOrder as $albumName){
	    list ($ret, $albumFields) =
		Gallery1DataParser::loadAlbumFields($path . $albumName . $slash);
	    if ($ret->isError()) {
		return array($ret->wrap(__FILE__, __LINE__),'');
	    }
	    if ($albumFields['parentAlbumName'] == '.root') {
		$rootAlbums[] = $albumName;
	    }
	}
	return array(GalleryStatus::success(), $rootAlbums);
    }

    /**
     * Load and return album metadata from given directory
     *
     * @param string Path to album directory
     * @return array object GalleryStatus a status code,
     *               object Unserialized album metadata
     */
    function loadAlbumFields($path) {
        global $gallery;
	$platform = $gallery->getPlatform();
	$slash = $platform->getDirectorySeparator();

	$tmp = trim($path);
	if ($tmp[strlen($tmp)-1] != $slash) {
	    $tmp .= $slash;
	}
	$path = trim($tmp);
	$albumPath = explode($slash, $path);
	$albumName = $albumPath[count($albumPath)-2];
        list ($ret, $album) = Gallery1DataParser::loadFile($path . 'album.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}
	$album->fields['name'] = $albumName;
	if (!$album->fields['parentAlbumName']){
	    $album->fields['parentAlbumName'] = '.root';
	}
	return array(GalleryStatus::success(), $album->fields);
    }

    /**
     * Count the number of photos in an album dir
     *
     * @param string Path to album directory
     * @return array object GalleryStatus a status code,
     *               integer Count of photos
     */
    function getPhotoCount($path) {
	list ($ret, $photos) = Gallery1DataParser::loadFile($path . 'photos.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}
	$photoCount = count($photos);
	return array(GalleryStatus::success(), $photoCount);
    }

    /**
     * Count the photo data from an album dir
     *
     * @param string Path to album directory
     * @return array object GalleryStatus a status code,
     *               array object Galleryphotos
     */
    function getPhotos($path) {
	global $gallery;
        $platform = $gallery->getPlatform();
	$slash = $platform->getDirectorySeparator();

	list ($ret, $photos) = Gallery1DataParser::loadFile($path . $slash . 'photos.dat');
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}
	return array(GalleryStatus::success(), $photos);
    }

    /**
     * Load user uids from path
     *
     * @param string Path to album directory
     * @return array object GalleryStatus a status code,
     *               array Associative array of uids and usernames
     */
    function getUserUids($path) {
        global $gallery;
	static $uids;
	if (!isset($uids[$path])) {
	    if (!isset($uids)) {
		$uids = array();
	    }
	    $platform = $gallery->getPlatform();
	    $slash = $platform->getDirectorySeparator();

	    list ($ret, $userDB) =
		Gallery1DataParser::loadFile($path . '.users' . $slash . 'userdb.dat');
	    if ($ret->isError()) {
		return array($ret->wrap(__FILE__, __LINE__), null);
	    }
	    $uids[$path] = array();
	    foreach ($userDB->userMap as $username => $uid) {
		if (Gallery1DataParser::isValidUid($path, $uid)
		    && !Gallery1DataParser::isValidUid($path, $username)
		    && !eregi('nobody|everybody|loggedin', $username)) {
		    $uids[$path][$uid] = $username;
		}
	    }
	}
	return array(GalleryStatus::success(), $uids[$path]);
    }

    /**
     * Validate user id string from gallery v1.x.x
     *
     * @param string Uid to be tested
     * @return boolean True or False
     */
    function isValidUidString($uid) {
	if (ereg('^[0-9]{9,}_[0-9]+$', $uid)) {
	    return TRUE;
	} else {
	    return FALSE;
	}
    }

    /**
     * Validate user id from gallery v1.x.x
     *
     * @param string Uid to be tested
     * @return boolean True or False
     */
    function isValidUid($path, $uid) {
	global $gallery;
	static $valid;
	if (!isset($valid[$path][$uid])) {
	    if (!isset($valid)) {
		$valid = array();
	    }
	    if (!isset($valid[$path])) {
		$valid[$path] = array();
	    }
	    $platform = $gallery->getPlatform();
	    $slash = $platform->getDirectorySeparator();
	    if (Gallery1DataParser::isValidUidString($uid)) {
		list ($ret, $fields) = Gallery1DataParser::getUserFieldsByUid($path, $uid);
		if ($ret->isSuccess()) {
		    $valid[$path][$uid] = TRUE;
		} else {
		    $valid[$path][$uid] = FALSE;
		}
	    } else {
		$valid[$path][$uid] = FALSE;
	    }
	}
	return $valid[$path][$uid];
    }

    /**
     * Load user metadata given a path and uid
     *
     * @param string Path to album directory
     * @param string Username to import
     * @return array object GalleryStatus a status code,
     *               array User metadata
     */
    function getUserFieldsByUid($path, $uid) {
        global $gallery;
	static $fields;

	if (!isset($fields[$path][$uid])) {
	    if (!isset($fields)) {
		$fields = array();
	    }
	    if (!isset($fields[$path])) {
		$fields[$path] = array();
	    }
	    $platform = $gallery->getPlatform();
	    $slash = $platform->getDirectorySeparator();
	    $fields[$path][$uid] = array();
	    if (Gallery1DataParser::isValidUidString($uid)) {
		list ($ret, $user) = Gallery1DataParser::loadFile($path . '.users' . $slash . $uid);
		if ($ret->isError()) {
		    return array($ret->wrap(__FILE__, __LINE__), null);
		}
		foreach ($user as $key => $value){
		    $fields[$path][$uid][$key] = $value;
		}
	    }
	}
	return array(GalleryStatus::success(), $fields[$path][$uid]);
    }

    /**
     * Load user metadata given a path and username
     *
     * @param string Path to album directory
     * @param string Username to import
     * @return array object GalleryStatus a status code,
     *               array User metadata
     */
    function getUserFieldsByUsername($path, $username) {
        global $gallery;
        list($ret, $uids) = Gallery1DataParser::getUserUids($path);
        if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
        }
	$usernames = array_flip($uids);
        $uid = $usernames[$username];
	list ($ret, $fields) = Gallery1DataParser::getUserFieldsByUid($path, $uid);
	if ($ret->isError()) {
	    return array($ret->wrap(__FILE__, __LINE__), null);
	}
	return array(GalleryStatus::success(), $fields);
    }
}


/* Define these classes so that unserialize can use them */
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class AlbumDB{ }
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Album { }
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Gallery_UserDB { }
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Gallery_User { }
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class AlbumItem { }
/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Image { }

/**
 * A stub class into which various G1 objects can be unserialized.
 *
 * @package Migrate
 * @subpackage Gallery1DataParser
 */
class Comment { }
?>
