<?php
/*
* Gallery2Flickr
*
* A bridge between your gallery2 installation and flickr.com
*
* File: Gallery2Flickr.class.php
*
* Helper class to interface gallery2 with flickr
*
* Copyright:
* (c) 2006 - 2008 hide@address.com
* Distributed under the terms of the GNU General Public License v2
*
* Author(s):
* Gunnar Wrobel <hide@address.com>
*
* 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.
*
* (Gallery2Flickr is a module for Gallery2 - a web based photo album
* viewer and editor - Copyright for Gallery2: (C) 2000-2008 Bharat
* Mediratta)
*/
/**
* @package Gallery2Flickr
* @version $Id: Gallery2Flickr.class.php 10 2008-01-18 09:39:31Z luciferc $
* @author Gunnar Wrobel <hide@address.com>
*/
class FlickrToGallery
{
var $flickr_api_key = '1ec6e0da9b85ab695169b4cab430562a';
var $flickr_shared_secret = 'b7a499460670674e';
var $flickr_bridge_perms = 'write';
var $flickr;
var $user;
function FlickrToGallery() {
GalleryCoreApi::requireOnce('modules/Gallery2Flickr/classes/phpFlickr/phpFlickr.php');
// We get the token from our db, not the session.
unset($_SESSION['phpFlickr_auth_token']);
$this->flickr = new phpFlickr($this->flickr_api_key,
$this->flickr_shared_secret);
// Try to get the token
list ($ret, $flickr_api_token) = FlickrToGalleryHelper::retrieveToken();
if ($ret) {
return array($ret, null);
}
if (!$ret && $flickr_api_token) {
$this->flickr->setToken($flickr_api_token);
$check_token = $this->flickr->auth_checkToken($flickr_api_token);
// valid token?
if (!$check_token || $check_token['token'] != $flickr_api_token) {
// Clear invalid token
$ret = FlickrToGalleryHelper::setToken('');
$this->flickr = new phpFlickr($this->flickr_api_key,
$this->flickr_shared_secret);
} else {
if (isset($check_token['user']) && isset($check_token['user']['nsid'])) {
$this->user = $this->flickr->people_getInfo($check_token['user']['nsid']);
}
}
}
}
// Generate a link to flickr that the user can use to give us access
function auth_link() {
$error = array();
// Try to get the frob
list ($ret, $flickr_api_frob) = FlickrToGalleryHelper::retrieveFrob();
if ($ret || !$flickr_api_frob) {
// Get new frob
$flickr_api_frob = $this->flickr->auth_getFrob();
if (!$flickr_api_frob) {
$error['code'] = $this->flickr->error_code;
$error['message'] = $this->flickr->error_msg;
}
}
// generate the api signature
$flickr_api_sig = md5($this->flickr_shared_secret .
"api_key" . $this->flickr_api_key .
"frob" . $flickr_api_frob .
"perms" . $this->flickr_bridge_perms);
$flickr_auth_link = 'http://flickr.com/services/auth/?' .
'api_key=' . $this->flickr_api_key .
'&perms=' . $this->flickr_bridge_perms .
'&frob=' . $flickr_api_frob .
'&api_sig=' . $flickr_api_sig;
return array('frob' => $flickr_api_frob,
'link' => $flickr_auth_link,
'error' => $error);
}
function import_set($set_id, $g2id) {
$set = $this->flickr->photosets_getInfo($set_id);
$photos = $this->flickr->photosets_getPhotos($set_id);
$name = 'flickr_owner_' . $set['owner'] . '_id_' . $set['id'];
$title = $set['title'];
$description = $set['description'];
$summary = 'Flickr: ' . $this->flickr->urls_getUserPhotos() . 'sets/' . $set['id'];
$keywords = '';
list ($ret, $album) = GalleryCoreApi::createAlbum($g2id,
$name,
$title,
$summary,
$description,
$keywords);
if ($ret) {
return false;
}
foreach ($photos['photo'] as $photo) {
if (!$this->import_image($photo['id'], $album->getId())) {
return false;
}
}
return true;
}
function update_set($set_id, $g2id) {
$set = $this->flickr->photosets_getInfo($set_id);
$photos = $this->flickr->photosets_getPhotos($set_id);
$name = 'flickr_owner_' . $set['owner'] . '_id_' . $set['id'];
$title = $set['title'];
$description = $set['description'];
$summary = 'Flickr: ' . $this->flickr->urls_getUserPhotos() . 'sets/' . $set['id'];
$keywords = '';
global $gallery;
$platform =& $gallery->getPlatform();
/* Find the child set with this name */
$pathComponent = $platform->legalizePathComponent(trim($name));
list ($ret, $setId) =
GalleryCoreApi::fetchChildIdByPathComponent($g2id, $pathComponent);
if ($ret) {
return false;
}
list ($ret, $album) = GalleryCoreApi::loadEntitiesById($g2id);
if ($ret) {
return false;
}
list ($ret, $setItem) = GalleryCoreApi::loadEntitiesById($setId);
if ($ret) {
return false;
}
/* List of pictures in the set */
list ($ret, $childIds) = GalleryCoreApi::fetchChildItemIds($setItem);
if ($ret) {
return false;
}
/* Get Flickr id of every picture already in the gallery set */
$chunkSize = 200;
while (!empty($childIds)) {
$chunk = array_splice($childIds, 0, $chunkSize);
$gallery->guaranteeTimeLimit(60);
list ($ret, $childs) = GalleryCoreApi::loadEntitiesById($chunk);
if ($ret) {
return false;
}
foreach ($childs as $item) {
$path = $item->getPathComponent();
$pos = strpos($path, '_');
$photo_id[] = substr($path, 0, $pos);
}
}
/* Import pictures from Flickr set which are not yet locally present */
foreach ($photos['photo'] as $photo) {
if (empty($photo_id) || ! in_array ($photo['id'], $photo_id)) {
if (!$this->import_image($photo['id'], $setId)) {
return false;
}
}
}
return true;
}
function import_image($photo_id, $g2id, $import_size = 'Original') {
global $gallery;
$g2id = (int)$g2id;
$photo = $this->flickr->photos_getInfo($photo_id);
$photo_sizes = $this->flickr->photos_getSizes($photo_id);
$sizes = array('Square' => 0,
'Thumbnail' => 1,
'Small' => 2,
'Medium' => 3,
'Large' => 4,
'Original' => 5);
$sorted_sizes = array();
foreach ($photo_sizes as $size) {
$sorted_sizes[$sizes[$size['label']]] = $size;
}
$isize = $sizes[$import_size];
while (!in_array($isize, array_keys($sorted_sizes))) {
$isize--;
}
$photo_url = $sorted_sizes[$isize]['source'];
/* var_dump($photo_sizes);
var_dump($sorted_sizes);
var_dump($isize);
var_dump($photo_url);
die();*/
/* Define basic information */
$mimeType = 'image/jpeg';
$title = (isset($photo['title'])) ? $photo['title'] : '';
$fileName = basename($photo_url);
$description = (isset($photo['description'])) ? $photo['description'] : '';
$summary = (isset($photo['urls']['url'][0]['_content'])) ? 'Flickr: ' . $photo['urls']['url'][0]['_content'] : '';
$tags = '';
if (isset($photo['tags']['tag'])) {
foreach ($photo['tags']['tag'] as $tag) {
$tags .= $tag['_content'] . ' ';
}
}
/* Copy the file locally */
$tmpDir = $gallery->getConfig('data.gallery.tmp');
$platform =& $gallery->getPlatform();
$tmpFile = $platform->tempnam($tmpDir, 'add');
$successfullyCopied = false;
GalleryUtilities::unsanitizeInputValues($photo_url, false);
if (empty($extraHeaders)) {
$extraHeaders = array('Referer' => str_replace('&', '&', $photo_url));
}
// Use the web helper class directly here since we need to specify the
// redirection depth
GalleryCoreApi::requireOnce('modules/core/classes/helpers/WebHelper_simple.class');
list ($successfullyCopied, $response, $headers) =
WebHelper_simple::fetchWebFile($photo_url, $tmpFile, $extraHeaders, 2);
if ($successfullyCopied) {
/* Add it */
$lock = GalleryCoreApi::acquireWriteLock($g2id);
list ($ret, $newItem) = GalleryCoreApi::addItemToAlbum($tmpFile,
$fileName,
$title,
$summary,
$description,
$mimeType,
$g2id);
GalleryCoreApi::releaseLocks($lock);
$lock = GalleryCoreApi::acquireWriteLock($newItem->getId());
$newItem->setKeywords($tags);
$newItem->save();
GalleryCoreApi::releaseLocks($lock);
@$platform->unlink($tmpFile);
// var_dump($newItem->getKeywords());die();
if ($ret) {
return false;
}
} else {
return false;
}
return true;
}
function export($g2id, $set = null, $permissions = 'none') {
$g2id = (int)$g2id;
list ($ret, $item) = GalleryCoreApi::loadEntitiesById($g2id);
if ($ret) {
return false;
}
if (!$item->getCanContainChildren()) {
$pid = $this->export_image($g2id, $permissions);
if (isset($set)) {
$result = $this->flickr->photosets_addPhoto($set, $pid);
}
return $pid;
} else {
list ($ret, $children) = GalleryCoreApi::fetchChildItemIds($item);
if ($ret) {
return false;
}
$pids = array();
foreach ($children as $child) {
$pid = $this->export($child, $set, $permissions);
if ($pid) {
$pids[] = $pid;
}
}
if (!$set) {
$description = $item->getDescription();
if (!$description) {
$description = 'Imported by Gallery2Flickr';
}
$new_set = $this->flickr->photosets_create($item->getTitle(),
$description,
$pids[0]);
if ($new_set) {
$setid = $new_set['id'];
}
foreach ($pids as $pid) {
$this->flickr->photosets_addPhoto($setid, $pid);
}
}
return null;
}
}
function export_image($g2id, $permissions = 'none') {
global $gallery;
list ($ret, $item) = GalleryCoreApi::loadEntitiesById($g2id);
if ($ret) {
return false;
}
$is_public = "0";
$is_friend = "0";
$is_family = "0";
switch ($permissions) {
case 'friends':
$is_friend = "1";
break;
case 'family':
$is_family = "1";
break;
case 'frfa':
$is_friend = "1";
$is_family = "1";
break;
case 'all':
$is_public = "1";
break;
case 'none':
default:
$is_public = "0";
$is_friend = "0";
$is_family = "0";
break;
}
$lock = GalleryCoreApi::acquireReadLock($g2id);
// Instead of just fetching the file from our disk, we try to
// ensure that the image gets processed through all filters that
// might apply to the image
$platform =& $gallery->getPlatform();
$path = $platform->tempnam($tmpDir, 'export');
/* Who is the anonymous user? */
list ($ret, $anonymousUserId) =
GalleryCoreApi::getPluginParameter('module', 'core', 'id.anonymousUser');
if ($ret) {
return $ret;
}
/* Can the current image be accessed by anonymous? */
list ($ret, $pref) = GalleryCoreApi::fetchPreferredSource($item);
if ($ret) {
return $ret;
}
$itemId = $pref->getId();
list ($ret, $permissions) = GalleryCoreApi::getPermissions($itemId);
if ($ret) {
return $ret;
}
list ($ret, $publicPermissions) =
GalleryCoreApi::getPermissions($itemId, $anonymousUserId, false);
if ($ret) {
return $ret;
}
$needSession = !isset($publicPermissions['core.viewSource']);
if ($needSession) {
/*
* Get G2 session for gallery2flickr to access non-public images.
* We can't use this session because hijack protection will prevent access
* plus the current user could logout before fotokasten retrieves the images.
* Create a new session with the rights of current user for fotokasten to use.
*/
$gfSession = new GallerySession();
$ret = $gfSession->initEmpty(true, $gallery->getActiveUserId());
if ($ret) {
return array($ret, null);
}
}
if ($needSession) {
$sessionParam = array($gfSession->getKey() => $gfSession->getId());
} else {
$sessionParam = array();
}
$urlGenerator =& $gallery->getUrlGenerator();
$src = $urlGenerator->generateUrl(
array_merge(
array('view' => 'core.DownloadItem', 'itemId' => $itemId),
$sessionParam
),
array('forceFullUrl' => true)
);
if (isset($gfSession)) {
/* Mark this session so that it can be treated specially */
$gfSession->put('core.isPrintService', array($itemId));
$ret = $gfSession->save();
if ($ret) {
return array($ret, null);
}
}
list ($success, $response, $headers, $url) = GalleryCoreApi::fetchWebFile($src, $path);
if (!$success) {
return false;
}
list($ret, $plugins) = GalleryCoreApi::fetchPluginStatus('module');
$commentsOn = false;
if (!empty($plugins['comment']) && !empty($plugins['comment']['active']) && $plugins['comment']['active']) {
$commentsOn = true;
}
if ($commentsOn) {
// get the comments for a photo
GalleryCoreApi::requireOnce('modules/comment/classes/GalleryCommentHelper.class');
list ($ret, $comments) =
GalleryCommentHelper::fetchComments($item->getId(), null, ORDER_ASCENDING);
if ($ret) {
return $ret;
}
// an array of the users who left comments indexed by commenterId
$commenters = array();
if (!empty($comments)) {
for ($i = 0; $i < sizeof($comments); $i++) {
/* Get the commenter ids */
$commenters[$comments[$i]->getCommenterId()] = 1;
}
/* Load all the commenters user information */
if (sizeof($commenters) > 0) {
list ($ret, $commentersList) =
GalleryCoreApi::loadEntitiesById(array_keys($commenters));
if ($ret) {
return $ret;
}
}
foreach ($commentersList as $commenter) {
$commenters[$commenter->getId()] = $commenter;
}
}
}
// disable PHP script timeout feature
// without this uploads of large images
// may fail
set_time_limit(0);
$pid = $this->flickr->sync_upload ($path,
$item->getTitle(),
$item->getDescription(),
$item->getKeywords() . ' gallery2flickr',
$is_public,
$is_friend,
$is_family);
GalleryCoreApi::releaseLocks($lock);
if (!$pid) {
return false;
}
if ($commentsOn) {
// set the photo comments in flickr
define("FLICKR_COMMENT_DELIMITER", " :: ");
if (!empty($comments)) {
for ($i = 0; $i < sizeof($comments); $i++) {
$currentComment = $comments[$i];
$flickrCommentText = "Gallery Comment" . FLICKR_COMMENT_DELIMITER;
if($commenters[$currentComment->getCommenterId()]->getFullName() != null) {
$flickrCommentText .= $commenters[$currentComment->getCommenterId()]->getFullName();
} else {
$flickrCommentText .= $commenters[$currentComment->getCommenterId()]->getUserName();
}
if(null != $currentComment->getSubject()) {
$flickrCommentText .= FLICKR_COMMENT_DELIMITER . $currentComment->getSubject();
}
if(null != $currentComment->getComment()) {
$flickrCommentText .= FLICKR_COMMENT_DELIMITER . $currentComment->getComment();
}
// TODO error handling on result code
$result = $this->flickr->photos_comments_addComment($pid,$flickrCommentText);
}
}
}
return $pid;
}
}
class FlickrToGalleryHelper {
function accessAllowed() {
list($ret, $token) = FlickrToGalleryHelper::retrieveToken();
if ($ret) {
return array($ret, false);
}
if (!$token) {
return array(GalleryCoreApi::error(ERROR_PERMISSION_DENIED, __FILE__, __LINE__, 'No token found!'), false);
}
return array(null, true);
}
function adminAccessAllowed($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
/*
* This should be only accessible to registered users
*/
list ($ret, $anonymous) =
GalleryCoreApi::getPluginParameter('module', 'core', 'id.anonymousUser');
if ($ret) {
return array($ret, null);
}
// The next gallery version allows locking
//list ($ret, $user) = GalleryCoreApi::loadEntitiesById($user);
//if ($ret) {
// return array($ret, null);
//}
//if ($isAnonymous || $user->isLocked()) {
if ($user == $anonymous) {
return array(GalleryCoreApi::error(ERROR_PERMISSION_DENIED, __FILE__, __LINE__, 'Not allowed!'), null);
}
return array(null, true);
}
function storeFrob($frob, $user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $allowed) = FlickrToGalleryHelper::adminAccessAllowed();
if ($ret) {
return array($ret, null);
}
$ret = GalleryCoreApi::setPluginParameter('module', 'Gallery2Flickr', 'ufrob', $frob, $user);
if ($ret) {
return array($ret, null);
}
}
function storeToken($token, $user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $allowed) = FlickrToGalleryHelper::adminAccessAllowed($user);
if ($ret) {
return array($ret, null);
}
$ret = GalleryCoreApi::setPluginParameter('module', 'Gallery2Flickr', 'utoken', $token, $user);
if ($ret) {
return array($ret, null);
}
}
function hasFrob($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $has) = FlickrToGalleryHelper::retrieveFrob($user);
if ($ret || !$has) {
return false;
}
return true;
}
function hasToken($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $has) = FlickrToGalleryHelper::retrieveToken($user);
if ($ret || !$has) {
return false;
}
return true;
}
function deleteFrob($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
if (FlickrToGalleryHelper::retrieveFrob($user)) {
$ret = GalleryCoreApi::removePluginParameter('module', 'Gallery2Flickr', 'ufrob', $user);
}
return false;
}
function deleteToken($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
if (FlickrToGalleryHelper::retrieveToken($user)) {
$ret = GalleryCoreApi::removePluginParameter('module', 'Gallery2Flickr', 'utoken', $user);
}
return false;
}
function retrieveFrob($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $allowed) = FlickrToGalleryHelper::adminAccessAllowed($user);
if ($ret) {
return array($ret, null);
}
list ($ret, $frob) = GalleryCoreApi::getPluginParameter('module', 'Gallery2Flickr', 'ufrob', $user);
if ($ret) {
return array($ret, null);
}
return array(null, $frob);
}
function retrieveToken($user = null) {
if (!$user) {
global $gallery;
$user = $gallery->getActiveUserId();
}
list($ret, $allowed) = FlickrToGalleryHelper::adminAccessAllowed($user);
if ($ret) {
return array($ret, null);
}
list ($ret, $token) = GalleryCoreApi::getPluginParameter('module', 'Gallery2Flickr', 'utoken', $user);
if ($ret) {
return array($ret, null);
}
return array(null, $token);
}
}