array('GetId', null, null, null, null), 'smart' => array('GetName', 'SmartAlbum::GetByNames', null, 'SmartHasItem', 'Decorator::SmartFormula'), 'tag' => array('GetId', 'Label::GetByIds', null, 'TagHasItem', 'Decorator::TagFormula'), 'album' => array('GetName', 'Album::GetBySharename', 'AlbumAccessible', 'AlbumHasItem', 'Decorator::AlbumFormula'), 'category' => array('GetId', 'Category::GetByIds', 'CategoryAccessible', 'CategoryHasItem', 'Decorator::CategoryFormula'), 'photo' => array('GetItemName', 'File::GetPhotoByDBPath', 'ItemAccessible', 'HasNoItem', 'Decorator::PhotoFormula'), 'video' => array('GetItemName', 'File::GetVideoByDBPath', 'ItemAccessible', 'HasNoItem', 'Decorator::VideoFormula') ); function __construct() { parent::__construct(SZ_WEBAPI_API_DESCRIPTION_PATH); } protected function Process() { if (!strcasecmp($this->method, "getpath")) { $this->GetPath(); } else if (!strcasecmp($this->method, "checkpath")) { $this->CheckPath(); } } private function GetPath() { $param = $this->GetParam_GetPath(); $items = array(); if (!$param) { $this->SetError(WEBAPI_ERR_BAD_REQUEST); goto End; } $items[] = AlbumAPIUtil::GetRootAlbumInfo($param); if (0 !== count($param['sharepath'])) { $result = Album::GetBySharename($param['sharepath']); $allowComment = AlbumAPIUtil::IsAlbumCommentalbGlobal(); $showAlbumHit = AlbumAPIUtil::IsShowAlbumHit(); $needThumbSize = in_array('thumb_size', $param['additional']); foreach ($param['sharepath'] as $sharepath) { $item = array(); $item = Decorator::AlbumFormula($result[$sharepath], array( 'allowComment' => $allowComment, 'showAlbumHit' => $showAlbumHit, 'param' => $param, 'needThumbSize' => $needThumbSize )); $items[] = $item; } } $resp = array( 'items' => $items, 'total' => count($items) ); $this->SetResponse($resp); End: return; } private function GetParam_GetPath() { if (!isset($_REQUEST['id'])){ return false; } if (preg_match('/^(photo|video)_/', $_REQUEST['id'])) { $ids = explode("_", $_REQUEST['id']); $path = @pack("H*", $ids[1]) .'/'. @pack("H*", $ids[2]); } else { $path = $this->DecodeItemId($_REQUEST['id'], '_'); } if (false === $path) { return false; } $dir = pathinfo($path, PATHINFO_DIRNAME);; $dirs = array(); while (!in_array($dir, array('.', '', '/'), true)) { $dirs[] = $dir; $dir = pathinfo($dir, PATHINFO_DIRNAME); } $param = array( 'additional' => explode(',', $_REQUEST['additional']), 'sharepath' => array_reverse($dirs), 'ignore' => explode(',', $_REQUEST['ignore']) ); return $param; } private function CheckPath() { $param = $this->GetParam_CheckPath(); if (!$param) { $this->SetError(WEBAPI_ERR_BAD_REQUEST); goto End; } $allowComment = AlbumAPIUtil::IsAlbumCommentalbGlobal(); $showAlbumHit = AlbumAPIUtil::IsShowAlbumHit(); $needThumbSize = in_array('thumb_size', $param['additional']); $previous = false; $items = array(); $formedItem = array(); $last_token = end($param['validToken']); foreach ($param['validToken'] as $token => $value) { $type = $value['type']; $id = $value['id']; list($idProcessFunc, $GetObjFunc, $permissionFunc, $hasItemFunc, $formula) = $this->validIdPrefix[$type]; if (!$GetObjFunc) { continue; } $id = $this->$idProcessFunc($id); if (in_array($type, array('photo', 'video'))) { $objs = call_user_func($GetObjFunc, array($id['dbPath'])); $item = $objs[$id['dbPath']]; } else { $objs = call_user_func($GetObjFunc, array($id)); $item = $objs[$id]; } if (!$item) { $this->SetError(array(PHOTOSTATION_PATH_ACCESS_DENY)); goto End; } $items[$token] = array( 'id' => $token, 'type' => $type, 'info' => $item ); // check current permission if ($permissionFunc) { $code = $this->$permissionFunc($item); if ($type === 'album') { if ($code === WEBAPI_ERR_NONE && !$previousCode) { $previousToken = $previousCode = null; } else if ($last_token != $value && in_array($code, array(PHOTOSTATION_ALBUM_NO_ACCESS_RIGHT, PHOTOSTATION_ALBUM_PASSWORD_ERROR)) && !$previousCode) { $previousCode = $code; $previousToken = $token; // password -> public / private } else if ($code === PHOTOSTATION_ALBUM_NO_ACCESS_RIGHT && $previousCode === PHOTOSTATION_ALBUM_PASSWORD_ERROR) { // password -> public if ($item['public']) { $this->SetError(array($previousCode, $previousToken)); goto End; // password -> private } else { $this->SetError(array($code, $token)); goto End; } // private/password -> password (error) } else if ($code === PHOTOSTATION_ALBUM_PASSWORD_ERROR && in_array($previousCode, array(PHOTOSTATION_ALBUM_NO_ACCESS_RIGHT, PHOTOSTATION_ALBUM_PASSWORD_ERROR))) { $this->SetError(array($code, $token)); goto End; // private/password -> password (passed) } else if ($code == WEBAPI_ERR_NONE && $previousCode && $item['password']) { $previousCode = $previousToken = null; // private -> public } else if ($code == WEBAPI_ERR_NONE && $previousCode && $this->NotPasswordAlbum($item)) { $this->SetError(array($previousCode, $previousToken)); goto End; } else if ($code !== WEBAPI_ERR_NONE) { $this->SetError(array($code, $token)); goto End; } } else { if ($previousCode) { $this->SetError(array($previousCode, $previousToken)); goto End; } if ($code !== WEBAPI_ERR_NONE) { $this->SetError(array($code, $token)); goto End; } } } // check previous and current valid if ($previous) { $parentObj = $items[$previous]; $parentFunc = $this->validIdPrefix[$parentObj['type']]; // check previous has current $hasItemFunc = $parentFunc[3]; if ($hasItemFunc && !$this->$hasItemFunc($parentObj['info'], $type, $id, $item)) { $this->SetError(array(PHOTOSTATION_PATH_ACCESS_DENY)); goto End; } } if ($formula) { $formedItem[$token] = call_user_func($formula, $item, array( 'allowComment' => $allowComment, 'showAlbumHit' => $showAlbumHit, 'param' => $param, 'id' => $token, 'needThumbSize' => $needThumbSize ) ); } else { $formedItem[$token] = $items[$token]; } $previous = $token; } $result = array(); foreach ($param['tokens'] as $token) { if ($formedItem[$token]) { $result[] = $formedItem[$token]; } else { $result[] = array( "id" => $token ); } } $resp['total'] = count($result); $resp['items'] = $result; $this->SetResponse($resp); End: return; } private function ItemAccessible($obj) { $relativePath = substr($obj['path'], strlen(SYNOPHOTO_SERVICE_REAL_DIR_PATH)); $dirname = pathinfo($relativePath, PATHINFO_DIRNAME); $sharename = '.' === $dirname ? '/' : $dirname; $accessible = csSYNOPhotoMisc::CheckAlbumAccessible($sharename); return $accessible ? WEBAPI_ERR_NONE : PHOTOSTATION_PHOTO_ACCESS_DENY; } private function AlbumAccessible($obj) { $sharename = $obj['sharename']; $accessible = csSYNOPhotoMisc::CheckAlbumAccessible($sharename); if ($obj['password'] && !$accessible) { return PHOTOSTATION_ALBUM_PASSWORD_ERROR; } else if (!$accessible) { return PHOTOSTATION_ALBUM_NO_ACCESS_RIGHT; } return WEBAPI_ERR_NONE; } private function CategoryAccessible($obj) { if ($obj['hidden'] && !$this->isAdmin) { return PHOTOSTATION_CATEGORY_ACCESS_DENY; } return WEBAPI_ERR_NONE; } private function SmartHasItem($parentObj, $itemType, $itemId, $itemObj) { $itemlist = SmartAlbum::GetSmartAlbumInstance()->GetItemsInSmartAlbum($parentObj, "filename", "asc", 0, -1); foreach ($itemlist as $item) { if ($item['id'] === $itemObj['id']) { return true; } } return false; } private function TagHasItem($parentObj, $itemType, $itemId, $itemObj) { if ('photo' === $itemType) { $item = ItemLabel::GetByItemKeyLabelId($itemObj['id'], $parentObj['id'], true); } else if ('video' === $itemType) { $item = ItemLabel::GetByItemKeyLabelId($itemObj['path'], $parentObj['id'], false); } else { return false; } return $item ? true : false; } private function AlbumHasItem($parentObj, $itemType, $itemId, $itemObj) { if (in_array($itemType, array('photo', 'video'))) { return $itemObj['shareid'] === $parentObj['shareid']; } return Album::HasItem($parentObj['sharename'], $itemObj['sharename']); } private function CategoryHasItem($parentObj, $itemType, $itemId, $itemObj) { if ('album' === $itemType) { return Category::HasItem($parentObj['id'], $itemType, $itemObj['shareid']); } return Category::HasItem($parentObj['id'], $itemType, $itemId); } private function HasNoItem($parentObj, $itemType, $itemId, $itemObj) { return false; } private function GetParam_CheckPath() { $param = array(); if(!isset($_REQUEST['token'])) { return false; } $tokens = split('/', $_REQUEST['token']); $validTokens = array(); foreach($tokens as $token) { $token = trim($token); if (!$token) { continue; } $parts = explode('_', $token, 2); if (2 > count($parts) || !array_key_exists($parts[0], $this->validIdPrefix)) { continue; } $validTokens[$token] = array( 'type' => $parts[0], 'id' => $parts[1] ); } $param = array( 'tokens' => $tokens, 'validToken' => $validTokens, 'ignore' => explode(',', $_REQUEST['ignore']), 'additional' => explode(',', $_REQUEST['additional']) ); return $param; } private function GetId ($id) { return $id; } private function GetName ($id) { return @pack('H*', $id); } private function GetItemName ($id) { $parts = split('_', $id); $sharename = $this->GetName($parts[0]); $filename = $this->GetName($parts[1]); return array( 'sharename' => $sharename, 'filename' => $filename, 'dbPath' => SYNOPHOTO_SERVICE_REAL_DIR_PATH. ('/' === $sharename ? '': "$sharename/"). $filename ); } private function NotPasswordAlbum ($item) { return !$item['password']; } protected function CheckPermission() { $this->isAdmin = isset($_SESSION[SYNOPHOTO_ADMIN_USER]['admin_syno_user']); return true; } } $api = new PathAPI(); $api->Run();