/** * Finds informations related to the user identifier. * * @param int $user_id * @param boolean $use_cache * @return array */ function getuserdata($user_id, $use_cache = false) { global $conf; // retrieve basic user data $query = ' SELECT '; $is_first = true; foreach ($conf['user_fields'] as $pwgfield => $dbfield) { if ($is_first) { $is_first = false; } else { $query .= ' , '; } $query .= $dbfield . ' AS ' . $pwgfield; } $query .= ' FROM ' . USERS_TABLE . ' WHERE ' . $conf['user_fields']['id'] . ' = \'' . $user_id . '\''; $row = pwg_db_fetch_assoc(pwg_query($query)); // retrieve additional user data ? if ($conf['external_authentification']) { $query = ' SELECT COUNT(1) AS counter FROM ' . USER_INFOS_TABLE . ' AS ui LEFT JOIN ' . USER_CACHE_TABLE . ' AS uc ON ui.user_id = uc.user_id LEFT JOIN ' . THEMES_TABLE . ' AS t ON t.id = ui.theme WHERE ui.user_id = ' . $user_id . ' GROUP BY ui.user_id ;'; list($counter) = pwg_db_fetch_row(pwg_query($query)); if ($counter != 1) { create_user_infos($user_id); } } // retrieve user info $query = ' SELECT ui.*, uc.*, t.name AS theme_name FROM ' . USER_INFOS_TABLE . ' AS ui LEFT JOIN ' . USER_CACHE_TABLE . ' AS uc ON ui.user_id = uc.user_id LEFT JOIN ' . THEMES_TABLE . ' AS t ON t.id = ui.theme WHERE ui.user_id = ' . $user_id . ' ;'; $result = pwg_query($query); $user_infos_row = pwg_db_fetch_assoc($result); // then merge basic + additional user data $userdata = array_merge($row, $user_infos_row); foreach ($userdata as &$value) { // If the field is true or false, the variable is transformed into a boolean value. if ($value == 'true') { $value = true; } elseif ($value == 'false') { $value = false; } } unset($value); if ($use_cache) { if (!isset($userdata['need_update']) or !is_bool($userdata['need_update']) or $userdata['need_update'] == true) { $userdata['cache_update_time'] = time(); // Set need update are done $userdata['need_update'] = false; $userdata['forbidden_categories'] = calculate_permissions($userdata['id'], $userdata['status']); /* now we build the list of forbidden images (this list does not contain images that are not in at least an authorized category)*/ $query = ' SELECT DISTINCT(id) FROM ' . IMAGES_TABLE . ' INNER JOIN ' . IMAGE_CATEGORY_TABLE . ' ON id=image_id WHERE category_id NOT IN (' . $userdata['forbidden_categories'] . ') AND level>' . $userdata['level']; $forbidden_ids = query2array($query, null, 'id'); if (empty($forbidden_ids)) { $forbidden_ids[] = 0; } $userdata['image_access_type'] = 'NOT IN'; //TODO maybe later $userdata['image_access_list'] = implode(',', $forbidden_ids); $query = ' SELECT COUNT(DISTINCT(image_id)) as total FROM ' . IMAGE_CATEGORY_TABLE . ' WHERE category_id NOT IN (' . $userdata['forbidden_categories'] . ') AND image_id ' . $userdata['image_access_type'] . ' (' . $userdata['image_access_list'] . ')'; list($userdata['nb_total_images']) = pwg_db_fetch_row(pwg_query($query)); // now we update user cache categories $user_cache_cats = get_computed_categories($userdata, null); if (!is_admin($userdata['status'])) { // for non admins we forbid categories with no image (feature 1053) $forbidden_ids = array(); foreach ($user_cache_cats as $cat) { if ($cat['count_images'] == 0) { $forbidden_ids[] = $cat['cat_id']; remove_computed_category($user_cache_cats, $cat); } } if (!empty($forbidden_ids)) { if (empty($userdata['forbidden_categories'])) { $userdata['forbidden_categories'] = implode(',', $forbidden_ids); } else { $userdata['forbidden_categories'] .= ',' . implode(',', $forbidden_ids); } } } // delete user cache $query = ' DELETE FROM ' . USER_CACHE_CATEGORIES_TABLE . ' WHERE user_id = ' . $userdata['id']; pwg_query($query); // Due to concurrency issues, we ask MySQL to ignore errors on // insert. This may happen when cache needs refresh and that Piwigo is // called "very simultaneously". mass_inserts(USER_CACHE_CATEGORIES_TABLE, array('user_id', 'cat_id', 'date_last', 'max_date_last', 'nb_images', 'count_images', 'nb_categories', 'count_categories'), $user_cache_cats, array('ignore' => true)); // update user cache $query = ' DELETE FROM ' . USER_CACHE_TABLE . ' WHERE user_id = ' . $userdata['id']; pwg_query($query); // for the same reason as user_cache_categories, we ignore error on // this insert $query = ' INSERT IGNORE INTO ' . USER_CACHE_TABLE . ' (user_id, need_update, cache_update_time, forbidden_categories, nb_total_images, last_photo_date, image_access_type, image_access_list) VALUES (' . $userdata['id'] . ',\'' . boolean_to_string($userdata['need_update']) . '\',' . $userdata['cache_update_time'] . ',\'' . $userdata['forbidden_categories'] . '\',' . $userdata['nb_total_images'] . ',' . (empty($userdata['last_photo_date']) ? 'NULL' : '\'' . $userdata['last_photo_date'] . '\'') . ',\'' . $userdata['image_access_type'] . '\',\'' . $userdata['image_access_list'] . '\')'; pwg_query($query); } } return $userdata; }
$template->append('related_categories', $name); } } // jump to link // // 1. find all linked categories that are reachable for the current user. // 2. if a category is available in the URL, use it if reachable // 3. if URL category not available or reachable, use the first reachable // linked category // 4. if no category reachable, no jumpto link $query = ' SELECT category_id FROM ' . IMAGE_CATEGORY_TABLE . ' WHERE image_id = ' . $_GET['image_id'] . ' ;'; $authorizeds = array_diff(array_from_query($query, 'category_id'), explode(',', calculate_permissions($user['id'], $user['status']))); if (isset($_GET['cat_id']) and in_array($_GET['cat_id'], $authorizeds)) { $url_img = make_picture_url(array('image_id' => $_GET['image_id'], 'image_file' => $image_file, 'category' => $cache['cat_names'][$_GET['cat_id']])); } else { foreach ($authorizeds as $category) { $url_img = make_picture_url(array('image_id' => $_GET['image_id'], 'image_file' => $image_file, 'category' => $cache['cat_names'][$category])); break; } } if (isset($url_img)) { $template->assign('U_JUMPTO', $url_img); } // associate to albums $query = ' SELECT id FROM ' . CATEGORIES_TABLE . '
/** * API method * Returns a list of categories * @param mixed[] $params * @option int cat_id (optional) * @option bool recursive * @option bool public * @option bool tree_output * @option bool fullname */ function ws_categories_getList($params, &$service) { global $user, $conf; $where = array('1=1'); $join_type = 'INNER'; $join_user = $user['id']; if (!$params['recursive']) { if ($params['cat_id'] > 0) { $where[] = '( id_uppercat = ' . (int) $params['cat_id'] . ' OR id=' . (int) $params['cat_id'] . ' )'; } else { $where[] = 'id_uppercat IS NULL'; } } else { if ($params['cat_id'] > 0) { $where[] = 'uppercats ' . DB_REGEX_OPERATOR . ' \'(^|,)' . (int) $params['cat_id'] . '(,|$)\''; } } if ($params['public']) { $where[] = 'status = "public"'; $where[] = 'visible = "true"'; $join_user = $conf['guest_id']; } else { if (is_admin()) { // in this very specific case, we don't want to hide empty // categories. Function calculate_permissions will only return // categories that are either locked or private and not permitted // // calculate_permissions does not consider empty categories as forbidden $forbidden_categories = calculate_permissions($user['id'], $user['status']); $where[] = 'id NOT IN (' . $forbidden_categories . ')'; $join_type = 'LEFT'; } } $query = ' SELECT id, name, comment, permalink, uppercats, global_rank, id_uppercat, nb_images, count_images AS total_nb_images, representative_picture_id, user_representative_picture_id, count_images, count_categories, date_last, max_date_last, count_categories AS nb_categories FROM ' . CATEGORIES_TABLE . ' ' . $join_type . ' JOIN ' . USER_CACHE_CATEGORIES_TABLE . ' ON id=cat_id AND user_id=' . $join_user . ' WHERE ' . implode("\n AND ", $where) . ' ;'; $result = pwg_query($query); // management of the album thumbnail -- starts here $image_ids = array(); $categories = array(); $user_representative_updates_for = array(); // management of the album thumbnail -- stops here $cats = array(); while ($row = pwg_db_fetch_assoc($result)) { $row['url'] = make_index_url(array('category' => $row)); foreach (array('id', 'nb_images', 'total_nb_images', 'nb_categories') as $key) { $row[$key] = (int) $row[$key]; } if ($params['fullname']) { $row['name'] = strip_tags(get_cat_display_name_cache($row['uppercats'], null)); } else { $row['name'] = strip_tags(trigger_change('render_category_name', $row['name'], 'ws_categories_getList')); } $row['comment'] = strip_tags(trigger_change('render_category_description', $row['comment'], 'ws_categories_getList')); // management of the album thumbnail -- starts here // // on branch 2.3, the algorithm is duplicated from // include/category_cats, but we should use a common code for Piwigo 2.4 // // warning : if the API method is called with $params['public'], the // album thumbnail may be not accurate. The thumbnail can be viewed by // the connected user, but maybe not by the guest. Changing the // filtering method would be too complicated for now. We will simply // avoid to persist the user_representative_picture_id in the database // if $params['public'] if (!empty($row['user_representative_picture_id'])) { $image_id = $row['user_representative_picture_id']; } else { if (!empty($row['representative_picture_id'])) { // if a representative picture is set, it has priority $image_id = $row['representative_picture_id']; } else { if ($conf['allow_random_representative']) { // searching a random representant among elements in sub-categories $image_id = get_random_image_in_category($row); } else { // searching a random representant among representant of sub-categories if ($row['count_categories'] > 0 and $row['count_images'] > 0) { $query = ' SELECT representative_picture_id FROM ' . CATEGORIES_TABLE . ' INNER JOIN ' . USER_CACHE_CATEGORIES_TABLE . ' ON id=cat_id AND user_id=' . $user['id'] . ' WHERE uppercats LIKE \'' . $row['uppercats'] . ',%\' AND representative_picture_id IS NOT NULL ' . get_sql_condition_FandF(array('visible_categories' => 'id'), "\n AND") . ' ORDER BY ' . DB_RANDOM_FUNCTION . '() LIMIT 1 ;'; $subresult = pwg_query($query); if (pwg_db_num_rows($subresult) > 0) { list($image_id) = pwg_db_fetch_row($subresult); } } } } } if (isset($image_id)) { if ($conf['representative_cache_on_subcats'] and $row['user_representative_picture_id'] != $image_id) { $user_representative_updates_for[$row['id']] = $image_id; } $row['representative_picture_id'] = $image_id; $image_ids[] = $image_id; $categories[] = $row; } unset($image_id); // management of the album thumbnail -- stops here $cats[] = $row; } usort($cats, 'global_rank_compare'); // management of the album thumbnail -- starts here if (count($categories) > 0) { $thumbnail_src_of = array(); $new_image_ids = array(); $query = ' SELECT id, path, representative_ext, level FROM ' . IMAGES_TABLE . ' WHERE id IN (' . implode(',', $image_ids) . ') ;'; $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { if ($row['level'] <= $user['level']) { $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); } else { // problem: we must not display the thumbnail of a photo which has a // higher privacy level than user privacy level // // * what is the represented category? // * find a random photo matching user permissions // * register it at user_representative_picture_id // * set it as the representative_picture_id for the category foreach ($categories as &$category) { if ($row['id'] == $category['representative_picture_id']) { // searching a random representant among elements in sub-categories $image_id = get_random_image_in_category($category); if (isset($image_id) and !in_array($image_id, $image_ids)) { $new_image_ids[] = $image_id; } if ($conf['representative_cache_on_level']) { $user_representative_updates_for[$category['id']] = $image_id; } $category['representative_picture_id'] = $image_id; } } unset($category); } } if (count($new_image_ids) > 0) { $query = ' SELECT id, path, representative_ext FROM ' . IMAGES_TABLE . ' WHERE id IN (' . implode(',', $new_image_ids) . ') ;'; $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { $thumbnail_src_of[$row['id']] = DerivativeImage::thumb_url($row); } } } // compared to code in include/category_cats, we only persist the new // user_representative if we have used $user['id'] and not the guest id, // or else the real guest may see thumbnail that he should not if (!$params['public'] and count($user_representative_updates_for)) { $updates = array(); foreach ($user_representative_updates_for as $cat_id => $image_id) { $updates[] = array('user_id' => $user['id'], 'cat_id' => $cat_id, 'user_representative_picture_id' => $image_id); } mass_updates(USER_CACHE_CATEGORIES_TABLE, array('primary' => array('user_id', 'cat_id'), 'update' => array('user_representative_picture_id')), $updates); } foreach ($cats as &$cat) { foreach ($categories as $category) { if ($category['id'] == $cat['id'] and isset($category['representative_picture_id'])) { $cat['tn_url'] = $thumbnail_src_of[$category['representative_picture_id']]; } } // we don't want them in the output unset($cat['user_representative_picture_id'], $cat['count_images'], $cat['count_categories']); } unset($cat); // management of the album thumbnail -- stops here if ($params['tree_output']) { return categories_flatlist_to_tree($cats); } return array('categories' => new PwgNamedArray($cats, 'category', ws_std_get_category_xml_attributes())); }
function pshare_section_init() { global $tokens, $page, $conf, $user, $template; if ($tokens[0] == 'pshare') { $page['section'] = 'pshare'; $page['title'] = l10n('Shared Picture'); if (!isset($tokens[1])) { die("missing key"); } if (!preg_match(PSHARE_KEY_PATTERN, $tokens[1])) { die("invalid key"); } $page['pshare_key'] = $tokens[1]; $query = ' SELECT *, NOW() AS dbnow FROM ' . PSHARE_KEYS_TABLE . ' WHERE uuid = \'' . $page['pshare_key'] . '\' ;'; $shares = query2array($query); if (count($shares) == 0) { die('unknown key'); } $share = $shares[0]; pshare_log($share['pshare_key_id'], 'visit'); // is the key still valid? if (strtotime($share['expire_on']) < strtotime($share['dbnow'])) { die('expired key'); } // if the user is permitted for this photo, let's redirect to // picture.php (with full details and actions) if (!is_a_guest() and pshare_is_photo_visible($share['image_id'])) { // find the first reachable category linked to the photo $query = ' SELECT category_id FROM ' . IMAGE_CATEGORY_TABLE . ' WHERE image_id = ' . $share['image_id'] . ' ;'; $authorizeds = array_diff(array_from_query($query, 'category_id'), explode(',', calculate_permissions($user['id'], $user['status']))); foreach ($authorizeds as $category_id) { $url = make_picture_url(array('image_id' => $share['image_id'], 'category' => get_cat_info($category_id))); if (function_exists('Fotorama_is_replace_picture') and Fotorama_is_replace_picture()) { $url .= '&slidestop'; } redirect($url); } redirect(make_picture_url(array('image_id' => $share['image_id']))); } $query = ' SELECT * FROM ' . IMAGES_TABLE . ' WHERE id = ' . $share['image_id'] . ' ;'; $rows = query2array($query); $image = $rows[0]; $src_image = new SrcImage($image); if (isset($tokens[2]) && 'download' == $tokens[2]) { $format_id = null; if (isset($tokens[3]) && preg_match('/^f(\\d+)$/', $tokens[3], $matches)) { $format_id = $matches[1]; $query = ' SELECT * FROM ' . IMAGE_FORMAT_TABLE . ' WHERE format_id = ' . $format_id . ' AND image_id = ' . $image['id'] . ' ;'; $formats = query2array($query); if (count($formats) == 0) { do_error(400, 'Invalid request - format'); } $format = $formats[0]; $file = original_to_format(get_element_path($image), $format['ext']); $image['file'] = get_filename_wo_extension($image['file']) . '.' . $format['ext']; } else { $file = $image['path']; } $gmt_mtime = gmdate('D, d M Y H:i:s', filemtime($file)) . ' GMT'; $http_headers = array('Content-Length: ' . @filesize($file), 'Last-Modified: ' . $gmt_mtime, 'Content-Type: ' . mime_content_type($file), 'Content-Disposition: attachment; filename="' . $image['file'] . '";', 'Content-Transfer-Encoding: binary'); foreach ($http_headers as $header) { header($header); } readfile($file); pshare_log($share['pshare_key_id'], 'download', $format_id); exit; } $template->set_filename('shared_picture', realpath(PSHARE_PATH . 'template/shared_picture.tpl')); $derivative = new DerivativeImage(ImageStdParams::get_by_type(IMG_MEDIUM), $src_image); $derivative_size = $derivative->get_size(); // a random string to avoid browser cache $rand = '&download=' . substr(md5(time()), 0, 6); $template->assign(array('SRC' => $derivative->get_url(), 'IMG_WIDTH' => $derivative_size[0], 'IMG_HEIGHT' => $derivative_size[1], 'DOWNLOAD_URL' => duplicate_index_url() . '/' . $page['pshare_key'] . '/download' . $rand)); // formats if (defined('IMAGE_FORMAT_TABLE')) { $query = ' SELECT * FROM ' . IMAGE_FORMAT_TABLE . ' WHERE image_id = ' . $share['image_id'] . ' ;'; $formats = query2array($query); if (!empty($formats)) { foreach ($formats as &$format) { $format['download_url'] = duplicate_index_url() . '/' . $page['pshare_key'] . '/download'; $format['download_url'] .= '/f' . $format['format_id'] . $rand; $format['filesize'] = sprintf('%.1fMB', $format['filesize'] / 1024); } } $template->assign('formats', $formats); } $template->parse('shared_picture'); $template->p(); exit; } }