SetPublicShareSessionCache($_REQUEST['public_share_id']); } else if (isset($_REQUEST['filter_public_share'])) { csSYNOPhotoDB::GetDBInstance()->SetPublicShareSessionCache($_REQUEST['filter_public_share']); } if (!strcasecmp($this->method, "list")) { $force = "true" === $_REQUEST['force_update'] ? true : false; csSYNOPhotoDB::GetDBInstance()->SetSessionCache($force); session_write_close(); $this->ListItem(); } else if (!strcasecmp($this->method, "listexif")) { session_write_close(); $this->ListExif(); } else if (!strcasecmp($this->method, "listfeatureditem")) { $force = "true" === $_REQUEST['force_update'] ? true : false; csSYNOPhotoDB::GetDBInstance()->SetSessionCache($force); session_write_close(); $this->ListFeaturedItem(); } else if (!strcasecmp($this->method, "listgpsgroup")) { session_write_close(); $this->ListGPSGroup(); } else if (!strcasecmp($this->method, "listgpsgroupeditem")) { session_write_close(); $this->ListGPSGroupedItem(); } else if (!strcasecmp($this->method, "getinfo")) { csSYNOPhotoDB::GetDBInstance()->SetSessionCache(); session_write_close(); $this->GetInfo(); } else if (!strcasecmp($this->method, "getexif")) { session_write_close(); $this->GetExif(); } else { csSYNOPhotoDB::GetDBInstance()->SetSessionCache(); csSYNOPhotoMisc::CheckSessionTimeOut(true); if (!strcasecmp($this->method, "edit")) { $this->Edit(); } if (!strcasecmp($this->method, "delete")) { session_write_close(); $this->DeleteItem(); } if (!strcasecmp($this->method, "copy")) { csSYNOPhotoDB::GetDBInstance()->ExpireSessionCache(); session_write_close(); $this->CopyItem(); } if (!strcasecmp($this->method, "cancel")) { session_write_close(); $this->Cancel(); } } } private function GetInfo() { $ret = false; $resp = array(); /* return when lack of params */ if (!isset($_REQUEST['id'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $publicShareId = NULL; if (isset($_REQUEST['public_share_id'])) { $publicShareId = $_REQUEST['public_share_id']; if (!SharedAlbum::CheckPublicSharePermission($publicShareId)) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $publicShareInfo = SharedAlbum::GetInfoByPublicShare($publicShareId); if (NULL === $publicShareInfo || 'valid' !== $publicShareInfo['share_status']) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } } $additional = isset($_REQUEST['additional']) ? explode(',', $_REQUEST['additional']) : array(); $ids = explode(',', $_REQUEST['id']); foreach ($ids as $id_str) { $id_arr = explode('_', $id_str); if (3 !== count($id_arr) || ('photo' !== $id_arr[0] && 'video' !== $id_arr[0])) { continue; } $albumName = @pack('H*', $id_arr[1]); $fileName = @pack('H*', $id_arr[2]); $path = SYNOPHOTO_SERVICE_REAL_DIR . "/" . ("/" === $albumName ? "" : $albumName . "/") . $fileName; if (!csSynoPhotoMisc::CheckPathValid($path)) { continue; } if (!csSYNOPhotoMisc::CheckAlbumAccessible($albumName, false, $publicShareId)) { continue; } $filePath = ('/' === $albumName ? "" : $albumName . "/") . $fileName; if (NULL !== $publicShareId && !SharedAlbum::CheckSharedAlbumItemValid($filePath, $id_arr[0], $publicShareId)) { continue; } if (@file_exists($path)) { if (false !== ($item = PhotoAPIUtil::getItemByPath($path, $additional, $id_arr[0], false))) { $resp[] = $item; } } } $ret = true; $this->SetResponse($resp); End: return $ret; } private function GetParams_ListItem() { global $SYNOPHOTO_ALLOW_SORT_TYPE; if (!isset($_REQUEST['offset']) || !isset($_REQUEST['limit']) || !isset($_REQUEST['type'])) { return false; } $params = array( 'offset' => $_REQUEST['offset'] + 0, 'limit' => $_REQUEST['limit'] + 0, 'type' => explode(',', $_REQUEST['type']), 'labelIds' => array() ); foreach ($params['type'] as $_) { if (!in_array($_, array('photo', 'video'))) { return false; } } $options_params = array( // key => default value 'sort_by' => 'filename', 'sort_direction' => 'asc', 'filter_smart' => '', 'filter_tag' => '', 'filter_album' => '', 'filter_shared_album' => '', 'filter_public_share' => '', 'item_id' => '', 'additional' => array(), 'gps' => false ); foreach ($options_params as $k => $v) { if (!isset($_REQUEST[$k])) { $params[$k] = $v; continue; } if ('sort_by' === $k) { if (in_array($_REQUEST[$k], $SYNOPHOTO_ALLOW_SORT_TYPE)) { $params[$k] = $_REQUEST[$k]; } else { $params[$k] = 'filename'; } } else if ('sort_direction' === $k) { $params[$k] = 'desc' === $_REQUEST[$k] ? 'desc' : 'asc'; } else if ('additional' === $k) { $params[$k] = explode(',', $_REQUEST[$k]); } else if ('gps' === $k) { $params[$k] = 'true' === $_REQUEST[$k]; } else if ('filter_tag' === $k) { $temps = explode(",", $_REQUEST['filter_tag']); $ids = array(); foreach ($temps as $tagId) { if (SYNOPHOTO_UNCONFIRM_TAG_ID === $tagId) { $ids[] = SYNOPHOTO_UNCONFIRM_TAG_ID; } else { $arrs = explode("tag_", $tagId); $ids[] = $arrs[1] + 0; } } $params['labelIds'] = $ids; } else { $params[$k] = $_REQUEST[$k]; } } // compatible with [time] [time1,time2] [time1,] [,time2] if (isset($_REQUEST['taken_date'])) { $taken_dates = explode(',' , trim($_REQUEST['taken_date'])); if (1 === count($taken_dates)) { if ($taken_dates[0]) { $taken_date = date_create($taken_dates[0]); if ($taken_date) { $date_begin = $taken_date; } } $params['date_end'] = $params['date_begin'] = $date_begin->format('Y-m-d'); } else { if ($taken_dates[0]) { $taken_date = date_create($taken_dates[0]); if ($taken_date) { $date_begin = $taken_date; } } if ($taken_dates[1]) { $taken_date_end = date_create($taken_dates[1]); if ($taken_date_end) { $date_end = $taken_date_end; } } if ($date_begin && $date_end) { if ($date_begin > $date_end) { list($params['date_begin'], $params['date_end']) = array($date_end->format('Y-m-d'), $date_begin->format('Y-m-d')); } else { list($params['date_begin'], $params['date_end']) = array($date_begin->format('Y-m-d'), $date_end->format('Y-m-d')); } } else if ($date_begin) { $params['date_begin'] = $date_begin->format('Y-m-d'); } else if ($date_end) { $params['date_end'] = $date_end->format('Y-m-d'); } else { return false; } } } return $params; } private function ListItem() { $ret = false; $resp = array(); $items = array(); /* return when lack of params */ $params = $this->GetParams_ListItem(); if (!$params) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $hasPhoto = in_array('photo', $params['type']); $hasVideo = in_array('video', $params['type']); // create the variable which name is the same as the key of params foreach ($params as $k => $v) { ${$k} = $v; } if ('' !== $filter_album) { $arr = explode('_', $filter_album); if ('album' !== $arr[0]) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $albumName = empty($arr[1]) ? '/' : @pack('H*', $arr[1]); $sharename = $albumName; /* users may have no access right to root album but can access layer one album * (Setting: Set photos and videos stored at the root folder of Photo Station as public)*/ if ($albumName !== "/" && !csSYNOPhotoMisc::CheckAlbumAccessible($albumName)) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $albumPath = SYNOPHOTO_SERVICE_REAL_DIR . ("/" === $albumName ? "" : "/" . $albumName); if (false === csSynoPhotoMisc::CheckPathValid($albumPath)) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $personalAlbumPath = @pack('H*', $arr[1]); } else { $albumPath = SYNOPHOTO_SERVICE_REAL_DIR; $sharename = '/'; $personalAlbumPath = ''; } if ('root' !== SYNOPHOTO_ADMIN_USER) { //personal photo station if ('' !== $filter_album && '' !== $personalAlbumPath) { $escPath = "$personalAlbumPath/%"; } else { $escPath = "$personalAlbumPath%"; } } else { $escPath = "$albumPath/%"; } $getRealPath = ('root' === SYNOPHOTO_ADMIN_USER) ? false : true; $total = 0; /* unconfirmed people tag */ if ($hasPhoto && in_array(SYNOPHOTO_UNCONFIRM_TAG_ID, $params['labelIds'])) { $list = AlbumAPIUtil::GetUnConfirmItemList($limit, $offset); foreach ($list as $key => $value) { if (false !== ($item = PhotoAPIUtil::getItemByPath($key, $additional, 'photo', false))) { $items[] = $item; } } $total = intval($list['total']); } elseif ('' !== $filter_shared_album || '' !== $filter_public_share) { // check permission $publicShareId = '' !== $filter_public_share ? $filter_public_share : NULL; if (!SharedAlbum::CheckPublicSharePermission($publicShareId)) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $dbPath = NULL; $blSingleItem = false; if ('' !== $filter_shared_album) { // filter by shared album id, check userid in session own this shared album $id_arr = explode("_", $filter_shared_album); if (2 !== count($id_arr) || 'sharedalbum' != $id_arr[0]) { $this->SetError(PHOTOSTATION_SHARED_ALBUM_BAD_PARAMS); goto End; } if ($id_arr[1] === 'single') { $sharedAlbum = SharedAlbum::GetHiddenAlbumInfo(); $blSingleItem = true; $id_arr[1] = explode("_", $sharedAlbum['id'])[1]; } else { $sharedAlbum = SharedAlbum::GetInfoById($id_arr[1], array('public_share')); } if ($sharedAlbum === NULL) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $userid = isset($_SESSION[SYNOPHOTO_ADMIN_USER]['reg_syno_userid']) ? $_SESSION[SYNOPHOTO_ADMIN_USER]['reg_syno_userid'] : 0; $sharedAlbumId = $id_arr[1]; $shareStatus = $sharedAlbum['additional']['public_share']['share_status']; // for generating public share url // equal to publicShareId, avoid GetAccessibleAlbumQueryConditionWithExcludeFormat use wrong session data $publicShareLink = $sharedAlbum['additional']['public_share']['shareid']; } else if ('' !== $filter_public_share) { // filter by public share link, check public share is existent and valid $publicShareInfo = SharedAlbum::GetInfoByPublicShare($publicShareId); if (NULL === $publicShareInfo || 'valid' !== $publicShareInfo['share_status']) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $sharedAlbumId = (int)$publicShareInfo['id']; $userid = (int)$publicShareInfo['userid']; $publicShareLink = $publicShareId; $shareStatus = $publicShareInfo['share_status']; if ('' !== $item_id) { $id_arr = explode("_", $item_id); $type = $id_arr[0]; if (count($id_arr) !== 3 || ($type !== 'photo' && $type !== 'video')) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $albumName = @pack('H*', $id_arr[1]); $fileName = @pack('H*', $id_arr[2]); $filePath = ('/' === $albumName ? "" : $albumName . "/") . $fileName; $dbPath = SYNOPHOTO_SERVICE_REAL_DIR_PATH . $filePath; } } $albumCondition = csSYNOPhotoMisc::GetAccessibleAlbumQueryConditionWithExcludeFormat('A', $publicShareId); if (!$albumCondition['albumCond']) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $PublicSharePhotoTable = SHARED_ALBUM_PHOTO_TABLE_NAME; $PublicShareVideoTable = SHARED_ALBUM_VIDEO_TABLE_NAME; if (0 === $userid) { $PublicSharePhotoTable = SHARED_ALBUM_PHOTO_ADMIN_TABLE_NAME; $PublicShareVideoTable = SHARED_ALBUM_VIDEO_ADMIN_TABLE_NAME; } $sqlParam = array(); $photoQuery = ''; if ($hasPhoto) { $photoQuery = "SELECT A.path as path, A.name as filename, A.timetaken as takendate, A.create_time as createdate, 'photo' as type FROM photo_image A, $PublicSharePhotoTable B WHERE A.id = B.photoid AND B.collectionid = ?"; $sqlParam[] = $sharedAlbumId; if ($dbPath !== NULL) { $photoQuery .= " AND A.path = ?"; $sqlParam[] = $dbPath; } $photoQuery .= " AND {$albumCondition['albumCond']} "; $sqlParam = array_merge($sqlParam, $albumCondition['sqlParam']); } $videoQuery = ''; if ($hasVideo) { $videoQuery = "SELECT A.path as path, A.title as filename, A.mdate as takendate, A.date as createdate, 'video' as type FROM video A, $PublicShareVideoTable B WHERE A.id = B.videoid AND B.collectionid = ?"; $sqlParam[] = $sharedAlbumId; if ($dbPath !== NULL) { $videoQuery .= " AND A.path = ?"; $sqlParam[] = $dbPath; } $videoQuery .= " AND {$albumCondition['albumCond']} "; $sqlParam = array_merge($sqlParam, $albumCondition['sqlParam']); } $limitOffsetString = PHOTO_DB_GetLimitOffsetString($limit, $offset); if ('' !== $photoQuery && '' !== $videoQuery) { $query = "$photoQuery UNION $videoQuery ORDER BY $sort_by $sort_direction $limitOffsetString"; $queryCount = "SELECT COUNT(*) FROM ($photoQuery UNION $videoQuery) AS totalCount"; } elseif ('' === $photoQuery) { $query = "$videoQuery ORDER BY $sort_by $sort_direction $limitOffsetString"; $queryCount = "SELECT COUNT(*) FROM ($videoQuery) AS totalCount"; } else { $query = "$photoQuery ORDER BY $sort_by $sort_direction $limitOffsetString"; $queryCount = "SELECT COUNT(*) FROM ($photoQuery) AS totalCount"; } $db_result = PHOTO_DB_Query($query, $sqlParam); $serverHost = csSYNOPhotoMisc::GetServerHost(true); while ($row = PHOTO_DB_FetchRow($db_result)) { if (false !== ($item = PhotoAPIUtil::getItemByPath($row['path'], $additional, $row['type'], $getRealPath))) { if ($shareStatus === 'valid') { $item['public_share_url'] = $serverHost . SYNOPHOTO_URL_PREFIX . '/photo/share/' . $publicShareLink . ($blSingleItem ? '/' : '#!List/') . $item['id']; } $items[] = File::FormatDBData($item); } } $db_result = PHOTO_DB_Query($queryCount, $sqlParam); $row = PHOTO_DB_FetchRow($db_result); $total = intval($row[0]); } elseif ('' === $filter_smart) { /* filter by albumname and tag */ $itemObjs = File::ListItems($hasPhoto, $hasVideo, array( 'sharename' => $sharename, 'labels' => $params['labelIds'], 'date_begin' => $params['date_begin'], 'date_end' => $params['date_end'], 'gps' => $params['gps'] ), $sort_by, $sort_direction, 0 > $limit ? NULL : $limit, $offset >= 0 ? $offset : NULL); $formularExtraParam = array( 'needThumbSize' => in_array('thumb_size', $params['additional']), 'param' => $params ); $total = $itemObjs['total']; $items = array(); foreach ($itemObjs['items'] as $obj) { if ('photo' === $obj['type']) { $items[] = Decorator::PhotoFormula($obj, $formularExtraParam); } else if ('video' === $obj['type']) { $items[] = Decorator::VideoFormula($obj, $formularExtraParam); } } } else { /* for smart album */ $arr = explode('_', $filter_smart); if ('smart' !== $arr[0]) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $albumName = @pack('H*', $arr[1]); $data = array( "name" => $albumName, "offset" => $offset, "limit" => $limit, 'date_begin' => $params['date_begin'], 'date_end' => $params['date_end'] ); $smart = json_decode(SmartAlbum::GetSmartAlbumInstance()->ListItem(json_encode($data), $sort_by, $sort_direction), true); if (!$smart['success']) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $itemLists = $smart['data']['itemList']; $gpsTotal = 0; $idx = $offset; foreach ($itemLists as $row) { if (!in_array($row['type'], $params['type'])) { continue; } if (false !== ($item = PhotoAPIUtil::getItemByPath($row['path'], $additional, $row['type'], false))) { $item['pos'] = $idx++; if ($gps) { // special filter for map view if (null !== $item['additional']['photo_exif']['gps']) { $gpsTotal++; $items[] = $item; } } else { $items[] = $item; } } } $total = $gps ? $gpsTotal : $smart['data']['total']; } /* set return data */ $resp['total'] = $total; $resp['offset'] = (-1 == $limit || $offset + $limit > $total) ? $total : $offset + $limit; $resp['items'] = $items; $this->SetResponse($resp); $ret = true; End: return $ret; } private function GetParams_ListFeaturedItem () { $params = array(); if (!isset($_REQUEST['taken_date']) || !isset($_REQUEST['count'])) { return false; } if (!isset($_REQUEST['filter_smart']) && !isset($_REQUEST['filter_album']) && !isset($_REQUEST['filter_tag'])) { return false; } $listType = false; if (isset($_REQUEST['filter_album'])) { if ($_REQUEST['filter_album']) { $sharename = $this->DecodeItemId($_REQUEST['filter_album'], "album_"); } else { $sharename = "/"; } if (!$sharename) { return false; } $params['sharename'] = $sharename; $listType = "album"; } else if (isset($_REQUEST['filter_tag'])) { $temps = explode(",", $_REQUEST['filter_tag']); $ids = array(); foreach ($temps as $tagId) { if (SYNOPHOTO_UNCONFIRM_TAG_ID === $tagId) { $ids[] = SYNOPHOTO_UNCONFIRM_TAG_ID; } else { $arrs = explode("tag_", $tagId); $ids[] = $arrs[1] + 0; } } $params['labelIds'] = $ids; $listType = "label"; } else if (isset($_REQUEST['filter_smart'])) { $smart = $this->DecodeItemId($_REQUEST['filter_smart'], "smart_"); $params['smart'] = $smart; $listType = "smart"; } if (false === $listType) { return false; } $params['listType'] = $listType; // compatible with [time] [time1,time2] [time1,] [,time2] $taken_dates = explode(',' , trim($_REQUEST['taken_date'])); if (1 === count($taken_dates)) { if ($taken_dates[0]) { $taken_date = date_create($taken_dates[0]); if ($taken_date) { $date_begin = $taken_date; } } $params['date_end'] = $params['date_begin'] = $date_begin->format('Y-m-d'); } else { if ($taken_dates[0]) { $taken_date = date_create($taken_dates[0]); if ($taken_date) { $date_begin = $taken_date; } } if ($taken_dates[1]) { $taken_date_end = date_create($taken_dates[1]); if ($taken_date_end) { $date_end = $taken_date_end; } } if ($date_begin && $date_end) { if ($date_begin > $date_end) { list($params['date_begin'], $params['date_end']) = array($date_end->format('Y-m-d'), $date_begin->format('Y-m-d')); } else { list($params['date_begin'], $params['date_end']) = array($date_begin->format('Y-m-d'), $date_end->format('Y-m-d')); } } else if ($date_begin) { $params['date_begin'] = $date_begin->format('Y-m-d'); } else if ($date_end) { $params['date_end'] = $date_end->format('Y-m-d'); } else { return false; } } // count = -1 means all $params['count'] = $_REQUEST['count'] + 0; $params['type'] = explode(',', $_REQUEST['type']); $params['additional'] = explode(',', $_REQUEST['additional']); return $params; } private function ListFeaturedItem () { $resp = array(); $items = array(); /* return when lack of params */ $params = $this->GetParams_ListFeaturedItem(); if (!$params) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } if ("album" === $params['listType']) { $itemObjs = File::ListFeatured($params['date_begin'], $params['date_end'], $params['sharename'], $params['count'], array(), in_array('photo', $params['type']), in_array('video', $params['type'])); } else if ("label" === $params["listType"]) { $itemObjs = File::ListFeatured($params['date_begin'], $params['date_end'], '/', $params['count'], $params['labelIds'], in_array('photo', $params['type']), in_array('video', $params['type'])); } else if ("smart" === $params["listType"]) { $smart = json_decode(SmartAlbum::GetSmartAlbumInstance()->ListItem(json_encode(array( 'name' => $params['smart'], 'offset' => 0, 'limit' => -1, 'date_begin' => $params['date_begin'], 'date_end' => $params['date_end'] )), 'takendate', 'asc'), true); if (!$smart['success']) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $data = SmartAlbum::FilterFeatured($smart['data']['itemList'], $smart['data']['total'], $params['count']); $itemObjs = array( 'items' => $data, 'total' => $smart['data']['total'] ); } $formularExtraParam = array( 'needThumbSize' => in_array('thumb_size', $params['additional']), 'param' => $params ); foreach ($itemObjs['items'] as $obj) { if ('photo' === $obj['type']) { $items[] = Decorator::PhotoFormula($obj, $formularExtraParam); } else if ('video' === $obj['type']) { $items[] = Decorator::VideoFormula($obj, $formularExtraParam); } } $resp['total'] = $itemObjs['total']; $resp['items'] = $items; $this->SetResponse($resp); End: return; } private function GetParams_ListGPSGroup() { $params = array(); if (!isset($_REQUEST['filter_smart']) && !isset($_REQUEST['filter_album']) && !isset($_REQUEST['filter_tag'])) { return false; } $listType = false; if (isset($_REQUEST['filter_album'])) { if ($_REQUEST['filter_album']) { $sharename = $this->DecodeItemId($_REQUEST['filter_album'], "album_"); } else { $sharename = "/"; } if (!$sharename) { return false; } $params['sharename'] = $sharename; $listType = "album"; } else if (isset($_REQUEST['filter_tag'])) { $temps = explode(",", $_REQUEST['filter_tag']); $ids = array(); foreach ($temps as $tagId) { if (SYNOPHOTO_UNCONFIRM_TAG_ID === $tagId) { $ids[] = SYNOPHOTO_UNCONFIRM_TAG_ID; } else { $arrs = explode("tag_", $tagId); $ids[] = $arrs[1] + 0; } } $params['labelIds'] = $ids; $listType = "label"; } else if (isset($_REQUEST['filter_smart'])) { $smart = $this->DecodeItemId($_REQUEST['filter_smart'], "smart_"); $params['smart'] = $smart; $listType = "smart"; } $params['listType'] = $listType; if ($_REQUEST['bounds']) { $bounds = json_decode($_REQUEST['bounds'], true); $params['bounds'] = array( 'sw' => array( 'lat' => $bounds['sw']['lat'] + 0, 'lng' => $bounds['sw']['lng'] + 0 ), 'ne' => array( 'lat' => $bounds['ne']['lat'] + 0, 'lng' => $bounds['ne']['lng'] + 0 ) ); } if ($_REQUEST['gps_idx']) { $params['gps_idx'] = json_decode($_REQUEST['gps_idx'], true); if (null === $params['gps_idx']['lat'] || null === $params['gps_idx']['lng']) { return false; } } if ($_REQUEST['limit']) { $params['limit'] = $_REQUEST['limit'] + 0; } if ($_REQUEST['offset']) { $params['offset'] = $_REQUEST['offset'] + 0; } $params['zoom'] = $_REQUEST['zoom'] ? (int)$_REQUEST['zoom'] : 5; $params['type'] = explode(',', $_REQUEST['type']); $params['additional'] = explode(',', $_REQUEST['additional']); return $params; } private function ListGPSGroup () { $resp = array(); $items = array(); /* return when lack of params */ $params = $this->GetParams_ListGPSGroup(); if (!$params) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } if ("album" === $params['listType']) { $itemObjs = File::ListGPSGroup($params['sharename'], array(), $params['bounds'], $params['zoom'], in_array('photo', $params['type']), false); } else if ("label" === $params["listType"]) { $itemObjs = File::ListGPSGroup('/', $params['labelIds'], $params['bounds'], $params['zoom'], in_array('photo', $params['type']), false); } else if ("smart" === $params["listType"]) { $itemObjs = SmartAlbum::GetSmartAlbumInstance()->ListGPSGroup($params['smart'], $params['bounds'], $params['zoom']); } $formularExtraParam = array( 'needThumbSize' => in_array('thumb_size', $params['additional']), 'param' => $params ); $output = array(); foreach ($itemObjs['groups'] as $group) { $item = Decorator::PhotoFormula($group['item'], $formularExtraParam); $groupItem = array( 'count' => $group['count'], 'item' => $item, 'gps_idx' => $group['gps_idx'] ); $output[] = $groupItem; } $resp['total'] = $itemObjs['total']; $resp['items'] = $output; $this->SetResponse($resp); End: return; } private function ListGPSGroupedItem () { $params = $this->GetParams_ListGPSGroup(); if (!$params) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } if ("album" === $params['listType']) { $itemObjs = File::ListGPSGroupedItems($params['sharename'], array(), $params['gps_idx'], $params['zoom'], $params['limit'], $params['offset']); } else if ("label" === $params["listType"]) { $itemObjs = File::ListGPSGroupedItems('/', $params['labelIds'], $params['gps_idx'], $params['zoom'], $params['limit'], $params['offset']); } else if ("smart" === $params["listType"]) { $itemObjs = SmartAlbum::GetSmartAlbumInstance()->ListGPSGroupedItem($params['smart'], $params['gps_idx'], $params['zoom'], $params['limit'], $params['offset']); } $formularExtraParam = array( 'needThumbSize' => in_array('thumb_size', $params['additional']), 'param' => $params ); $output = array(); foreach ($itemObjs['items'] as $item) { $item = Decorator::PhotoFormula($item, $formularExtraParam); $output[] = $item; } $resp['total'] = $itemObjs['total']; $resp['items'] = $output; $this->SetResponse($resp); End: return; } private function ListExif() { $resp = array(); if (!isset($_REQUEST['type'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $map = array( "focal_length" => "focal_length_v2", "flash" => "flash_v2", "lens" => "lens_v2" ); $column = $type = $_REQUEST['type']; if (array_key_exists($type, $map)) { $column = $map[$type]; } $results = csSYNOPhotoDB::GetDBInstance()->getExifList($column); if (false === $results) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $items = array(); foreach ($results as $result) { if ('flash' === $type) { $item['id'] = $type.'_'.str_replace(',', '#', $result); } else { $item['id'] = $type.'_'.$result; } $item['name'] = $result; $item['type'] = 'exif'; $item['tag_type'] = $type; $items[] = $item; } $resp['total'] = count($results); $resp['tags'] = $items; $this->SetResponse($resp); End: return; } private function GetExif() { $resp = array(); if (!isset($_REQUEST['id'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $id_arr = explode('_', $_REQUEST['id']); if ('photo' !== $id_arr[0]) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $albumName = @pack('H*', $id_arr[1]); $fileName = @pack('H*', $id_arr[2]); $path = SYNOPHOTO_SERVICE_REAL_DIR . "/" . ("/" === $albumName ? "" : $albumName . "/") . $fileName; if (!csSynoPhotoMisc::CheckPathValid($path)) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $command = "/usr/syno/bin/exiv2 -pa " . escapeshellarg($path); $commandTagLabel = "/usr/syno/bin/exiv2 -Pl " . escapeshellarg($path); @exec($command, $outputs, $retval); @exec($commandTagLabel, $outputsTagLabel, $retvalTagLabel); $tagLableCount = count($outputsTagLabel); $items = array(); foreach ($outputs as $i => $output) { unset($item); $nonEmptyString = 0; $data = explode(" ", $output); $item['label'] = ($tagLableCount > $i) ? $outputsTagLabel[$i] : 'Unknown'; foreach ($data as $datum) { if("" !== $datum) { if (3 <= $nonEmptyString) { //Last is the value of the tag $item['value'] = ($item['value']) ? $item['value'] . " " . $datum : $datum; } $nonEmptyString ++; } //check utf-8 $value = iconv('UTF-8', 'UTF-8//IGNORE', $item['value']); $item['value'] = ($value) ? $value : ''; } $items[] = $item; } $resp = array(); $resp['total'] = count($items); $resp['exifs'] = $items; $this->SetResponse($resp); End: return; } private function Edit() { $ret = false; $resp = array(); /* return when lack of params */ if (!isset($_REQUEST['id'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } /* set optional params */ $title = isset($_REQUEST['title']) ? $_REQUEST['title'] : ''; $description = isset($_REQUEST['description']) ? $_REQUEST['description'] : ''; /* update records */ $ids = explode(',', $_REQUEST['id']); foreach ($ids as $idStr) { self::OutputSingleSpace(); $id_arr = explode('_', $idStr); $albumName = @pack('H*', $id_arr[1]); $fileName = @pack('H*', $id_arr[2]); $path = SYNOPHOTO_SERVICE_REAL_DIR . "/" . ("/" === $albumName ? "" : $albumName . "/") . $fileName; if (!csSynoPhotoMisc::CheckPathValid($path)) { continue; } if (!csSYNOPhotoMisc::CheckAlbumManageable($albumName)) { continue; } if (isset($_REQUEST['title']) || isset($_REQUEST['description'])) { $dbPath = $this->GetDbPath($path); if ('photo' === $id_arr[0]) { $require_update = false; $query = "UPDATE photo_image SET "; $queryParam = array(); if (isset($_REQUEST['title'])) { $query .= "title = ? "; $queryParam[] = $_REQUEST['title']; $require_update = true; } if (isset($_REQUEST['description'])) { if ($require_update) { $query .= ", "; } $query .= "description = ? "; $queryParam[] = $_REQUEST['description']; $require_update = true; $description = str_replace('"', '\"', $_REQUEST['description']); File::UpdateDescriptionMetadata($path, $description); } $query .= "WHERE path = ?"; $queryParam[] = $dbPath; PHOTO_DB_Query($query, $queryParam); } elseif ('video' === $id_arr[0]) { $require_update = false; $query = "UPDATE video_desc SET "; $queryParam = array(); if (isset($_REQUEST['title'])) { $query .= "title = ? "; $queryParam[] = $_REQUEST['title']; $require_update = true; } if (isset($_REQUEST['description'])) { if ($require_update) { $query .= ", "; } $query .= "description = ? "; $queryParam[] = $_REQUEST['description']; } $query .= "WHERE path = ?"; $queryParam[] = $dbPath; $db_result = PHOTO_DB_Query($query, $queryParam); if (false === ($row = PHOTO_DB_FetchRow($db_result))) { $query = "INSERT INTO video_desc (path, title, description) VALUES (?, ?, ?)"; $sqlParam = array($dbPath, $title, $description); PHOTO_DB_Query($query, $sqlParam); } } } if (isset($_REQUEST['gps_lat']) && isset($_REQUEST['gps_lng'])) { if (is_numeric($_REQUEST['gps_lat']) && is_numeric($_REQUEST['gps_lng'])) { SYNOPHOTO_GPS_UTIL_SetGPSLatLng($path, $_REQUEST['gps_lat'], $_REQUEST['gps_lng']); } } } $ret = true; End: return $ret; } private function DeleteItem() { $ret = false; /* return when lack of params */ if (!isset($_REQUEST['id'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $cancelPath = PHOTO_ACTION_TMP.md5(PHOTO_ACTION_DEL_KEY.$_REQUEST['id']); /* delete records */ $ids = explode(',', $_REQUEST['id']); foreach ($ids as $idStr) { self::OutputSingleSpace(); if (file_exists($cancelPath)) { @unlink($cancelPath); break; } $id_arr = explode('_', $idStr); $albumName = trim(@pack('H*', $id_arr[1])); $fileName = trim(@pack('H*', $id_arr[2])); if (!$albumName || !$fileName || $fileName == '/') { continue; } if (!csSYNOPhotoMisc::CheckAlbumManageable($albumName)) { continue; } $path = SYNOPHOTO_SERVICE_REAL_DIR . "/" . ("/" === $albumName ? "" : $albumName . "/") . $fileName; if (!csSynoPhotoMisc::CheckPathValid($path)) { continue; } $isPhoto = 'photo' === $id_arr[0] ? true : false; SYNOPHOTO_ADMIN_DeleteItemByPath($path, $isPhoto); SYNOPHOTO_LABEL_UTIL_Check_Photo_Label(); PhotoLog::Add("File [".$fileName."] was deleted from album [".$albumName."].", true, strtolower(GetLoginUsername())); } $ret = true; End: return $ret; } private function CopyItem() { $ret = false; $resp = array(); /* return when lack of params */ if (!isset($_REQUEST['id']) || !isset($_REQUEST['sharepath']) || !isset($_REQUEST['mode']) || !isset($_REQUEST['duplicate'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } /* set params */ if (preg_match('/^album_/', $_REQUEST['sharepath'])) { $ids = explode('_', $_REQUEST['sharepath']); $destShareName = @pack('H*', $ids[1]); } else { $destShareName = @pack('H*', $_REQUEST['sharepath']); } $destPath = SYNOPHOTO_SERVICE_REAL_DIR . "/" . $destShareName; if (!csSynoPhotoMisc::CheckPathValid($destPath)) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } $mode = $_REQUEST['mode']; if ('copy' !== $mode && 'move' !== $mode) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } if (!csSYNOPhotoMisc::CheckAlbumUploadable('' == $destShareName ? '/' : $destShareName)) { $this->SetError(PHOTOSTATION_PHOTO_ACCESS_DENY); goto End; } $dirpath = $destShareName ? $destShareName : '/'; $ids = explode(',', $_REQUEST['id']); $items = array(); foreach ($ids as $idStr) { $id_arr = explode('_', $idStr); $albumName = @pack('H*', $id_arr[1]); $fileName = @pack('H*', $id_arr[2]); if ($albumName === $dirpath) { $this->SetError(PHOTOSTATION_PHOTO_SELECT_CONFLICT); goto End; } $item = array( 'albumName' => $albumName, 'fileName' => $fileName, 'type' => $id_arr[0] ); $items[] = $item; } $dup = 'rename' === $_REQUEST['duplicate'] ? 2 : ('ignore' === $_REQUEST['duplicate'] ? 0 : 1); $cancelPath = PHOTO_ACTION_TMP.md5(PHOTO_ACTION_MVCP_KEY.$_REQUEST['id']); foreach($items as $item) { self::OutputSingleSpace(); if (file_exists($cancelPath)) { @unlink($cancelPath); break; } $path = SYNOPHOTO_SERVICE_REAL_DIR . "/" . ("/" === $item['albumName'] ? "" : $item['albumName'] . "/") . $item['fileName']; if (!csSynoPhotoMisc::CheckPathValid($path)) { continue; } if (!csSYNOPhotoMisc::CheckAlbumManageable($item['albumName'])) { continue; } $dbPath = $this->GetDbPath($path); /* get item id first */ if ('photo' === $item['type']) { $query = "SELECT id FROM photo_image WHERE path = ?"; } elseif ('video' === $item['type']) { $query = "SELECT id FROM video WHERE path = ?"; } $db_result = PHOTO_DB_Query($query, array($dbPath)); if ($row = PHOTO_DB_FetchRow($db_result)) { $id = $row['id']; if ('copy' === $mode) { if ('photo' === $item['type']) { SYNOPHOTO_ADMIN_CopyOnePhoto($destShareName, $id, $dup); @exec("/usr/syno/bin/synomkthumb -a " . escapeshellarg($destPath)); } elseif ('video' === $item['type']) { SYNOPHOTO_ADMIN_CopyOneVideo($destShareName, $id, $dup); } } elseif ('move' === $mode) { if ('photo' === $item['type']) { SYNOPHOTO_ADMIN_MoveOnePhoto($destShareName, $id, $dup); @exec("/usr/syno/bin/synomkthumb -a " . escapeshellarg($destPath)); } elseif ('video' === $item['type']) { SYNOPHOTO_ADMIN_MoveOneVideo($destShareName, $id, $dup); } } } } $ret = true; End: return $ret; } private function Cancel() { $ret = false; $resp = array(); /* return when lack of params */ if (!isset($_REQUEST['id']) || !isset($_REQUEST['action'])) { $this->SetError(PHOTOSTATION_PHOTO_BAD_PARAMS); goto End; } if ('mvcp' === $_REQUEST['action']) { $key = PHOTO_ACTION_MVCP_KEY; } else if ('delete' === $_REQUEST['action']) { $key = PHOTO_ACTION_DEL_KEY; } $filePath = PHOTO_ACTION_TMP.md5($key.$_REQUEST['id']); @file_put_contents($filePath, ""); $ret = true; End: return $ret; } private function GetDbPath($path) { return substr($path, strlen(SYNOPHOTO_SERVICE_REAL_DIR_PREFIX)); } } $api = new PhotoAPI(); $api->Run();