1562 lines
51 KiB
PHP
1562 lines
51 KiB
PHP
<?php
|
|
|
|
/*
|
|
* API v2 : Bindings to built in functions
|
|
*
|
|
* Montala Limited, July 2016
|
|
*
|
|
* This allows us to exclude certain parameters for security reasons (such as $use_permissions) and also to
|
|
* map to more API-appropriate parameters and output if necessary.
|
|
*
|
|
* For documentation please see: http://www.resourcespace.com/knowledge-base/api/
|
|
*
|
|
*/
|
|
|
|
function api_do_search($search, $restypes = "", $order_by = "relevance", $archive = 0, $fetchrows = -1, $sort = "desc", $offset = 0)
|
|
{
|
|
$offset = (int) $offset;
|
|
|
|
// Parse fetchrows
|
|
$fetchrows = array_map('intval', explode(',', trim($fetchrows, ' []')));
|
|
$structured_fetchrows = count($fetchrows) === 2;
|
|
if (!$structured_fetchrows) {
|
|
$fetch = array_pop($fetchrows);
|
|
$fetchrows = $fetch > 0 ? $fetch : -1;
|
|
if ($offset > 0 && $fetchrows != -1) {
|
|
$fetchrows = $fetchrows + $offset;
|
|
}
|
|
}
|
|
|
|
$no_results = $structured_fetchrows ? ['total' => 0, 'data' => []] : [];
|
|
|
|
if (!checkperm('s')) {
|
|
return $no_results;
|
|
}
|
|
|
|
# Note the subset of the available parameters. We definitely don't want to allow override of permissions or filters.
|
|
$results = do_search($search, $restypes, $order_by, $archive, $fetchrows, $sort);
|
|
if (!is_array($results)) {
|
|
return $no_results;
|
|
}
|
|
|
|
$resultcount = count($structured_fetchrows ? $results['data'] : $results);
|
|
if ($resultcount < $offset) {
|
|
return $no_results;
|
|
}
|
|
|
|
$resultset = array();
|
|
$get_resource_table_joins = get_resource_table_joins();
|
|
$i = 0;
|
|
for ($n = $offset; $n < $resultcount; $n++) {
|
|
$row = $structured_fetchrows ? $results['data'][$n] : $results[$n];
|
|
if (is_array($row)) {
|
|
$resultset[$i] = process_resource_data_joins_values($row, $get_resource_table_joins);
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
if ($structured_fetchrows) {
|
|
$results['data'] = $resultset;
|
|
return $results;
|
|
}
|
|
return $resultset;
|
|
}
|
|
|
|
function api_search_get_previews($search, $restypes = "", $order_by = "relevance", $archive = 0, $fetchrows = -1, $sort = "desc", $recent_search_daylimit = "", $getsizes = "", $previewext = "jpg")
|
|
{
|
|
# Extension to search capability that also returns the URLs of preview file sizes requested using the $getsizes parameter that match the requested extension.
|
|
if (!checkperm('s')) {
|
|
return array();
|
|
}
|
|
$getsizes = explode(",", $getsizes);
|
|
|
|
$structured = false;
|
|
if (strpos((string)$fetchrows, ",") !== false) {
|
|
// Convert string into array, removing square brackets if passed as array syntax in string form
|
|
$fetchrows = explode(",", trim($fetchrows, " []"));
|
|
}
|
|
if (is_array($fetchrows)) {
|
|
$structured = true;
|
|
}
|
|
$results = search_get_previews($search, $restypes, $order_by, $archive, $fetchrows, $sort, false, false, false, $recent_search_daylimit, false, false, false, false, false, $getsizes, $previewext);
|
|
|
|
if (is_array($results) && isset($results["total"])) {
|
|
$totalcount = $results["total"];
|
|
$results = $results["data"];
|
|
$resultcount = count($results);
|
|
} elseif (is_array($results)) {
|
|
$totalcount = $resultcount = count($results);
|
|
} else {
|
|
return $structured ? ["total" => 0, "data" => []] : [];
|
|
}
|
|
|
|
$get_resource_table_joins = get_resource_table_joins();
|
|
for ($n = 0; $n < $resultcount; $n++) {
|
|
if (is_array($results[$n])) {
|
|
$results[$n] = process_resource_data_joins_values($results[$n], $get_resource_table_joins);
|
|
if ($GLOBALS["hide_real_filepath"]) {
|
|
// Add a temporary key so the file can be accessed unauthenticated
|
|
foreach ($getsizes as $getsize) {
|
|
if (isset($results[$n]["url_" . $getsize])) {
|
|
$accesskey = generate_temp_download_key($GLOBALS["userref"], $results[$n]["ref"], $getsize);
|
|
if ($accesskey !== '') {
|
|
$results[$n]["url_" . $getsize] .= "&access_key={$accesskey}";
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $structured ? ["total" => $totalcount, "data" => $results] : $results;
|
|
}
|
|
|
|
function api_get_resource_field_data($resource)
|
|
{
|
|
# Get all field data for a resource
|
|
$results = get_resource_field_data($resource);
|
|
if (is_array($results)) {
|
|
$resultcount = count($results);
|
|
{
|
|
for ($n = 0; $n < $resultcount; $n++) {
|
|
// Remove node_values array as not required for the API
|
|
unset($results[$n]['nodes_values']);
|
|
$results[$n] = array_map("i18n_get_translated", $results[$n]);
|
|
}
|
|
}
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
function api_create_resource($resource_type, $archive = 999, $url = "", $no_exif = false, $revert = false, $autorotate = false, $metadata = "")
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $lang;
|
|
if (!(checkperm("c") || checkperm("d")) || checkperm("XU" . $resource_type)) {
|
|
return false;
|
|
}
|
|
|
|
if ($archive !== 999 && get_default_archive_state($archive) != $archive) {
|
|
// User supplied archive state which they don't have permission to use.
|
|
return false;
|
|
}
|
|
|
|
$no_exif = filter_var($no_exif, FILTER_VALIDATE_BOOLEAN);
|
|
$revert = filter_var($revert, FILTER_VALIDATE_BOOLEAN);
|
|
$autorotate = filter_var($autorotate, FILTER_VALIDATE_BOOLEAN);
|
|
|
|
if ($url != "" && !api_validate_upload_url($url)) {
|
|
// URL failed validation
|
|
return false;
|
|
}
|
|
|
|
# Create a new resource
|
|
$ref = create_resource($resource_type, $archive, -1, $lang["createdfromapi"]);
|
|
if (!is_int($ref)) {
|
|
return false;
|
|
}
|
|
|
|
# Also allow upload URL in the same pass (API specific, to reduce calls)
|
|
if ($url != "") {
|
|
// Generate unique hash to use so that other uploads with the same name won't conflict
|
|
$upload_key = uniqid($ref . "_");
|
|
$tmp_dld_fpath = temp_local_download_remote_file($url, $upload_key);
|
|
if ($tmp_dld_fpath === false) {
|
|
return "FAILED: Resource #{$ref} was created, but the file was not uploaded. Enable debug log and try again to identify why uploading it failed.";
|
|
}
|
|
|
|
#Check for duplicates if required
|
|
$duplicates = check_duplicate_checksum($tmp_dld_fpath, false);
|
|
if (count($duplicates) > 0) {
|
|
$duplicates_string = implode(",", $duplicates);
|
|
return "FAILED: Resource {$ref} was created, but the file was not uploaded. Resources {$duplicates_string} already have a matching file.";
|
|
} else {
|
|
$return = upload_file_by_url($ref, $no_exif, $revert, $autorotate, $tmp_dld_fpath, $upload_key);
|
|
if ($return === false) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
# Also allow metadata to be passed here.
|
|
if ($metadata != "") {
|
|
$metadata = json_decode($metadata, true);
|
|
if (is_array($metadata)) {
|
|
foreach ($metadata as $field => $value) {
|
|
// check $value is not an array
|
|
if (is_array($value)) {
|
|
return false;
|
|
}
|
|
update_field($ref, $field, $value);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $ref;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
* Provides simple way to update field by passing in simple string values for text fields,
|
|
* comma separated values for fixed list (node) fields, using double quotes
|
|
* to enclose strings and backslash as escape character
|
|
* Uses update_field and add_resource_nodes/delete_resource_nodes
|
|
*
|
|
*/
|
|
|
|
function api_update_field($resource, $field, $value, $nodevalues = false)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $FIXED_LIST_FIELD_TYPES, $category_tree_add_parents, $resource_field_column_limit, $userref;
|
|
|
|
// This user's template or real resources only
|
|
if ($resource < 1 && $resource != 0 - $userref) {
|
|
return false;
|
|
}
|
|
|
|
$resourcedata = get_resource_data($resource, true);
|
|
if (!$resourcedata) {
|
|
return false;
|
|
}
|
|
|
|
$editaccess = get_edit_access($resource, $resourcedata['archive'], $resourcedata);
|
|
|
|
if (!is_numeric($field)) {
|
|
// Name may have been passed
|
|
$field = ps_value("SELECT ref value FROM resource_type_field WHERE name = ?", ['s',$field], "", "schema");
|
|
}
|
|
|
|
if (!$editaccess || !metadata_field_edit_access($field)) {
|
|
return false;
|
|
}
|
|
$fieldinfo = get_resource_type_field($field);
|
|
|
|
if (!$fieldinfo) {
|
|
return false;
|
|
}
|
|
$errors = [];
|
|
return update_field($resource, $field, $value, $errors, true, $nodevalues);
|
|
}
|
|
|
|
function api_delete_resource($resource)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
return delete_resource($resource);
|
|
}
|
|
|
|
function api_copy_resource($from, $resource_type = -1)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $lang;
|
|
return copy_resource($from, $resource_type, $lang["createdfromapi"]);
|
|
}
|
|
|
|
function api_get_resource_log($resource, $fetchrows = -1)
|
|
{
|
|
return get_resource_log($resource, $fetchrows)["data"] ?? [];
|
|
}
|
|
|
|
function api_update_resource_type($resource, $type)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
return update_resource_type($resource, $type);
|
|
}
|
|
|
|
function api_get_resource_path($ref, $not_used = null, $size = "", $generate = true, $extension = "jpg", $page = 1, $watermarked = false, $alternative = -1)
|
|
{
|
|
# Set defaults
|
|
if ($alternative == "") {
|
|
$alternative = -1;
|
|
}
|
|
if ($page == "") {
|
|
$page = 1;
|
|
}
|
|
|
|
$refs = json_decode($ref, true);
|
|
if (!is_array($refs)) {
|
|
$refs = [$refs];
|
|
}
|
|
|
|
$return = array();
|
|
foreach ($refs as $ref) {
|
|
$resource = get_resource_data($ref);
|
|
if (!$resource || !is_numeric($ref) || !resource_download_allowed($ref, $size, $resource["resource_type"], $alternative)) {
|
|
$return[$ref] = "";
|
|
continue;
|
|
}
|
|
|
|
if (!$GLOBALS["hide_real_filepath"] && !$watermarked) {
|
|
// Check if watermarks are required - handled at download when $hide_real_filepath = true;
|
|
$GLOBALS['access'] = $resource['access'];
|
|
$watermarked = check_use_watermark();
|
|
}
|
|
|
|
$return[$ref] = get_resource_path($ref, false, $size, $generate, $extension, -1, $page, $watermarked, '', $alternative, false);
|
|
if ($GLOBALS["hide_real_filepath"]) {
|
|
// Add a temporary key so the file can be accessed unauthenticated
|
|
$accesskey = generate_temp_download_key($GLOBALS["userref"], $ref, $size);
|
|
if ($accesskey !== "") {
|
|
$return[$ref] .= "&access_key={$accesskey}";
|
|
}
|
|
}
|
|
}
|
|
return count($return) > 1 ? $return : reset($return);
|
|
}
|
|
|
|
function api_get_resource_data($resource)
|
|
{
|
|
$resdata = get_resource_data($resource);
|
|
|
|
// Check access
|
|
$access = get_resource_access($resource);
|
|
if ($access == 2) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if ($access == RESOURCE_ACCESS_INVALID_REQUEST) {
|
|
return false;
|
|
}
|
|
|
|
// Remove column data from inaccessible fields
|
|
$joins = get_resource_table_joins();
|
|
foreach ($joins as $datajoin) {
|
|
$joinfield = get_resource_type_field($datajoin);
|
|
if ((!metadata_field_view_access($datajoin)) || ($access == 1 && $joinfield["hide_when_restricted"] == 1)) {
|
|
unset($resdata["field" . $datajoin]);
|
|
}
|
|
}
|
|
|
|
$resdata = process_resource_data_joins_values($resdata, $joins);
|
|
return $resdata;
|
|
}
|
|
|
|
function api_put_resource_data($resource, array $data)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (is_null($data)) {
|
|
return false;
|
|
}
|
|
return put_resource_data($resource, $data);
|
|
}
|
|
|
|
function api_get_alternative_files($resource, $order_by = "", $sort = "", $type = "")
|
|
{
|
|
global $alt_files_visible_when_restricted;
|
|
$access = get_resource_access($resource);
|
|
|
|
if ($access == RESOURCE_ACCESS_INVALID_REQUEST) {
|
|
return false;
|
|
}
|
|
|
|
if ($access != 0 && !($access == 1 && $alt_files_visible_when_restricted)) {
|
|
return false;
|
|
}
|
|
|
|
return get_alternative_files($resource, $order_by, $sort, $type);
|
|
}
|
|
|
|
function api_get_resource_types()
|
|
{
|
|
return get_resource_types("", true);
|
|
}
|
|
|
|
function api_add_alternative_file($resource, $name, $description = '', $file_name = '', $file_extension = '', $file_size = 0, $alt_type = '', $file = '')
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (0 < $resource && (!(get_edit_access($resource) || checkperm('A')))) {
|
|
return false;
|
|
}
|
|
|
|
if ($file_extension != '' && is_banned_extension($file_extension)) {
|
|
return false;
|
|
}
|
|
|
|
// Just insert record in the database
|
|
if ('' == trim($file)) {
|
|
return add_alternative_file($resource, $name, $description, $file_name, $file_extension, $file_size, $alt_type);
|
|
}
|
|
|
|
// A file has been specified so add it as alternative
|
|
global $valid_upload_paths;
|
|
$deletesourcefile = false;
|
|
if (api_validate_upload_url($file)) {
|
|
// Path is a url
|
|
$upload_key = uniqid($resource . "_");
|
|
$file = temp_local_download_remote_file($file, $upload_key);
|
|
$deletesourcefile = true;
|
|
} elseif (is_valid_upload_path($file, $valid_upload_paths)) {
|
|
// Path is a file
|
|
if (is_banned_extension(pathinfo($file, PATHINFO_EXTENSION))) {
|
|
return false;
|
|
}
|
|
} elseif ($file != "") {
|
|
// Couldn't validate path supplied
|
|
return false;
|
|
}
|
|
|
|
if (trim($file_extension) == "") {
|
|
$path_parts = pathinfo($file);
|
|
$file_extension = $path_parts['extension'] ?? '';
|
|
}
|
|
|
|
$alternative_ref = add_alternative_file($resource, $name, $description, $file_name, $file_extension, $file_size, $alt_type);
|
|
$rs_alternative_path = get_resource_path($resource, true, '', true, $file_extension, -1, 1, false, '', $alternative_ref);
|
|
|
|
if (!copy($file, $rs_alternative_path)) {
|
|
return false;
|
|
}
|
|
|
|
chmod($rs_alternative_path, 0777);
|
|
if ($deletesourcefile) {
|
|
unlink($file);
|
|
}
|
|
$file_size = @filesize_unlimited($rs_alternative_path);
|
|
|
|
ps_query("UPDATE resource_alt_files SET file_size= ?, creation_date = NOW() WHERE resource = ? AND ref = ?", ['s', $file_size, 's', $resource, 's', $alternative_ref]);
|
|
|
|
global $alternative_file_previews_batch;
|
|
if ($alternative_file_previews_batch) {
|
|
create_previews($resource, false, $file_extension, false, false, $alternative_ref);
|
|
}
|
|
|
|
return $alternative_ref;
|
|
}
|
|
|
|
function api_delete_access_keys($access_keys, $resources, $collections)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
// Incoming parameters are csv strings; "-" entries denote a null resource or collection
|
|
// The number of entries in each parameter is always the same
|
|
$access_key_array = explode(",", $access_keys);
|
|
$resource_array = explode(",", $resources);
|
|
$collection_array = explode(",", $collections);
|
|
|
|
for ($i = 0; $i < count($access_key_array); $i++) {
|
|
if ($collection_array[$i] != "-") {
|
|
debug("ACCESSKEY DELETING COL=" . $collection_array[$i] . " KEY=" . $access_key_array[$i]);
|
|
delete_collection_access_key($collection_array[$i], $access_key_array[$i]);
|
|
} else {
|
|
debug("ACCESSKEY DELETING RES=" . $resource_array[$i] . " KEY=" . $access_key_array[$i]);
|
|
delete_resource_access_key($resource_array[$i], $access_key_array[$i]);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
function api_delete_alternative_file($resource, $ref)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (0 < $resource && (!(get_edit_access($resource) || checkperm('A')))) {
|
|
return false;
|
|
}
|
|
return delete_alternative_file($resource, $ref);
|
|
}
|
|
|
|
function api_upload_file($ref, $no_exif = false, $revert = false, $autorotate = false, $file_path = "")
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
$no_exif = filter_var($no_exif, FILTER_VALIDATE_BOOLEAN);
|
|
$revert = filter_var($revert, FILTER_VALIDATE_BOOLEAN);
|
|
$autorotate = filter_var($autorotate, FILTER_VALIDATE_BOOLEAN);
|
|
|
|
// Check not over quota
|
|
if (overquota()) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['disk_size_no_upload_explain']));
|
|
}
|
|
|
|
// Check for duplicates
|
|
$duplicates = check_duplicate_checksum($file_path, false);
|
|
if (count($duplicates) > 0) {
|
|
$duplicates_string = implode(",", $duplicates);
|
|
return "FAILED: The file for resource {$ref} was not uploaded. Resources {$duplicates_string} already have a matching file.";
|
|
} else {
|
|
$return = upload_file($ref, $no_exif, $revert, $autorotate, $file_path);
|
|
if ($return === false) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $ref;
|
|
}
|
|
|
|
function api_upload_file_by_url($ref, $no_exif = false, $revert = false, $autorotate = false, $url = "")
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
$no_exif = filter_var($no_exif, FILTER_VALIDATE_BOOLEAN);
|
|
$revert = filter_var($revert, FILTER_VALIDATE_BOOLEAN);
|
|
$autorotate = filter_var($autorotate, FILTER_VALIDATE_BOOLEAN);
|
|
|
|
if (!api_validate_upload_url($url)) {
|
|
// URL failed validation
|
|
return false;
|
|
}
|
|
|
|
// Check not over quota
|
|
if (overquota()) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['disk_size_no_upload_explain']));
|
|
}
|
|
|
|
// Generate unique hash to use so that other uploads with the same name won't conflict
|
|
$upload_key = uniqid((int)$ref . "_");
|
|
$tmp_dld_fpath = temp_local_download_remote_file($url, $upload_key);
|
|
|
|
if ($tmp_dld_fpath === false) {
|
|
return "FAILED: The file for resource #{$ref} was not uploaded. Enable debug log and try again to identify why uploading it failed.";
|
|
}
|
|
|
|
$duplicates = check_duplicate_checksum($tmp_dld_fpath, false);
|
|
if (count($duplicates) > 0) {
|
|
$duplicates_string = implode(",", $duplicates);
|
|
return "FAILED: The file for resource {$ref} was not uploaded. Resources {$duplicates_string} already have a matching file.";
|
|
} else {
|
|
$return = upload_file_by_url($ref, $no_exif, $revert, $autorotate, $tmp_dld_fpath, $upload_key);
|
|
if ($return === false) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return $ref;
|
|
}
|
|
|
|
function api_get_related_resources($ref)
|
|
{
|
|
global $enable_related_resources;
|
|
$access = get_resource_access($ref);
|
|
if ($access == RESOURCE_ACCESS_INVALID_REQUEST) {
|
|
return array();
|
|
}
|
|
|
|
if (!$enable_related_resources || $access == 2) {
|
|
return array();
|
|
}
|
|
return get_related_resources($ref);
|
|
}
|
|
|
|
function api_get_field_options($ref, $nodeinfo = false)
|
|
{
|
|
if (!is_numeric($ref)) {
|
|
// Name may have been passed
|
|
$ref = ps_value("select ref value from resource_type_field where name= ?", ['s',$ref], "", "schema");
|
|
}
|
|
|
|
if (!metadata_field_view_access($ref)) {
|
|
return false;
|
|
}
|
|
|
|
return get_field_options($ref, $nodeinfo);
|
|
}
|
|
|
|
function api_get_nodes($ref, $parent = null, $recursive = false, $offset = null, $rows = null, $name = "", $use_count = false, $order_by_translated_name = false)
|
|
{
|
|
// Check access to field.
|
|
if (!metadata_field_view_access($ref)) {
|
|
return false;
|
|
}
|
|
|
|
return get_nodes($ref, $parent, $recursive, $offset, $rows, $name, $use_count, $order_by_translated_name);
|
|
}
|
|
|
|
function api_get_user_collections()
|
|
{
|
|
global $userref;
|
|
if (checkperm("b")) {
|
|
return array();
|
|
}
|
|
return get_user_collections($userref);
|
|
}
|
|
|
|
function api_add_resource_to_collection($resource, $collection = '', $search = '')
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $usercollection;
|
|
if ($collection == '') {
|
|
$collection = $usercollection;
|
|
}
|
|
return add_resource_to_collection($resource, $collection, false, '', '', null, null, $search);
|
|
}
|
|
|
|
function api_collection_add_resources($collection = '', $resources = '', $search = '', $selected = false)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $usercollection;
|
|
if ($collection == '') {
|
|
$collection = $usercollection;
|
|
}
|
|
return collection_add_resources($collection, $resources, $search, $selected);
|
|
}
|
|
|
|
function api_remove_resource_from_collection($resource, $collection = '')
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $usercollection;
|
|
if ($collection == '') {
|
|
$collection = $usercollection;
|
|
}
|
|
return remove_resource_from_collection($resource, $collection);
|
|
}
|
|
|
|
function api_collection_remove_resources($collection = '', $resources = '', $removeall = false, $selected = false)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $usercollection;
|
|
if ($collection == '') {
|
|
$collection = $usercollection;
|
|
}
|
|
return collection_remove_resources($collection, $resources, $removeall, $selected);
|
|
}
|
|
|
|
function api_create_collection($name, $forupload = false)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $userref, $collection_allow_creation;
|
|
if (!can_create_collections()) {
|
|
return false;
|
|
}
|
|
if ($forupload && trim($name) == "") {
|
|
# Do not translate this string, the collection name is translated when displayed!
|
|
$name = "Upload " . offset_user_local_timezone(date('YmdHis'), 'YmdHis');
|
|
}
|
|
|
|
return create_collection($userref, $name);
|
|
}
|
|
|
|
function api_delete_collection($ref)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (checkperm("b") || !collection_writeable($ref)) {
|
|
return false;
|
|
}
|
|
return delete_collection($ref);
|
|
}
|
|
|
|
function api_search_public_collections($search = "", $order_by = "name", $sort = "ASC", $exclude_themes = true)
|
|
{
|
|
$exclude_themes = filter_var($exclude_themes, FILTER_VALIDATE_BOOLEAN);
|
|
$results = search_public_collections($search, $order_by, $sort, $exclude_themes);
|
|
$resultcount = count($results);
|
|
{
|
|
for ($n = 0; $n < $resultcount; $n++) {
|
|
if (is_array($results[$n])) {
|
|
$results[$n] = array_map("i18n_get_translated", $results[$n]);
|
|
}
|
|
}
|
|
}
|
|
return $results;
|
|
}
|
|
|
|
function api_set_node($ref, $resource_type_field, $name, $parent = '', $order_by = 0, $returnexisting = false)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $FIXED_LIST_FIELD_TYPES;
|
|
|
|
$fieldinfo = get_resource_type_field($resource_type_field);
|
|
if (
|
|
!in_array($fieldinfo['type'], $FIXED_LIST_FIELD_TYPES)
|
|
||
|
|
!(checkperm('a') || checkperm('k') || ($fieldinfo['type'] == FIELD_TYPE_DYNAMIC_KEYWORDS_LIST && !checkperm('bdk' . $resource_type_field)))
|
|
) {
|
|
// API user doesn't have permission to add new nodes
|
|
return false;
|
|
}
|
|
if (strtoupper($ref) == 'NULL') {
|
|
$ref = null;
|
|
}
|
|
if (strtoupper($parent) == 'NULL') {
|
|
$parent = null;
|
|
}
|
|
return set_node($ref, $resource_type_field, $name, $parent, $order_by);
|
|
}
|
|
|
|
function api_add_resource_nodes($resource, $nodestring)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
// This is only for super admins
|
|
if (!checkperm('a')) {
|
|
return false;
|
|
}
|
|
$nodes = explode(",", $nodestring);
|
|
if (!add_resource_nodes($resource, $nodes)) {
|
|
return false;
|
|
}
|
|
|
|
# If this is a 'joined' field we need to add it to the resource column
|
|
$joins = get_resource_table_joins();
|
|
$joined_fields_to_update = array();
|
|
foreach ($nodes as $newnode) {
|
|
$returned_node = array();
|
|
if (!get_node($newnode, $returned_node)) {
|
|
return false;
|
|
}
|
|
if (in_array($returned_node['resource_type_field'], $joins) && !in_array($returned_node['resource_type_field'], $joined_fields_to_update)) {
|
|
$joined_fields_to_update[] = $returned_node['resource_type_field'];
|
|
}
|
|
}
|
|
foreach ($joined_fields_to_update as $field_update) {
|
|
// get_data_by_field() always returns the value separated by ", " when flattening so we have to ensure it's stored
|
|
// using the field_column_string_separator in the data_joins (ie fieldX) columns
|
|
$resource_node_data = str_replace(', ', $GLOBALS['field_column_string_separator'], get_data_by_field($resource, $field_update));
|
|
update_resource_field_column($resource, $field_update, $resource_node_data);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function api_add_resource_nodes_multi($resources, $nodestring)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
// This is only for super admins
|
|
if (!checkperm('a')) {
|
|
return false;
|
|
}
|
|
$resourcearr = explode(",", $resources);
|
|
$nodes = explode(",", $nodestring);
|
|
return add_resource_nodes_multi($resourcearr, $nodes, false, true);
|
|
}
|
|
|
|
function api_resource_log_last_rows($minref = 0, $days = 7, $maxrecords = 0, string $field = '', string $log_code = '')
|
|
{
|
|
$fields = explode(',', $field);
|
|
$log_codes = explode(',', $log_code);
|
|
return resource_log_last_rows($minref, $days, $maxrecords, $fields, $log_codes);
|
|
}
|
|
|
|
function api_get_resource_all_image_sizes($resource)
|
|
{
|
|
$sizes = get_resource_all_image_sizes($resource);
|
|
if ($GLOBALS["hide_real_filepath"]) {
|
|
// Add a temporary key so the file can be accessed unauthenticated
|
|
for ($n = 0; $n < count($sizes); $n++) {
|
|
if ($sizes[$n]['size_code'] == 'original') {
|
|
$size_id = '';
|
|
} else {
|
|
$size_id = $sizes[$n]['size_code'];
|
|
}
|
|
|
|
$accesskey = generate_temp_download_key($GLOBALS["userref"], $resource, $size_id);
|
|
if ($accesskey !== "") {
|
|
$sizes[$n]["url"] .= "&access_key={$accesskey}";
|
|
}
|
|
}
|
|
}
|
|
// Remove the path elements
|
|
array_walk($sizes, function (&$size) {
|
|
unset($size["path"]);
|
|
});
|
|
return $sizes;
|
|
}
|
|
|
|
function api_get_node_id($value, $resource_type_field)
|
|
{
|
|
if (!metadata_field_view_access($resource_type_field)) {
|
|
return false;
|
|
} # Need at least view access to the field.
|
|
|
|
return get_node_id($value, $resource_type_field);
|
|
}
|
|
function api_replace_resource_file($ref, $file_location, $no_exif = false, $autorotate = false, $keep_original = true)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $rse_version_block, $plugins, $usergroup,$rse_version_override_groups, $replace_resource_preserve_option,
|
|
$valid_upload_paths;
|
|
$no_exif = filter_var($no_exif, FILTER_VALIDATE_BOOLEAN);
|
|
$autorotate = filter_var($autorotate, FILTER_VALIDATE_BOOLEAN);
|
|
$keep_original = filter_var($keep_original, FILTER_VALIDATE_BOOLEAN);
|
|
$generic_err_msg = [
|
|
"Status" => "FAILED",
|
|
"Message" => "Resource not replaced. Refer to ResourceSpace system administrator",
|
|
];
|
|
|
|
$file_location_parts = pathinfo($file_location);
|
|
|
|
if (is_valid_upload_path($file_location_parts["dirname"], $valid_upload_paths)) {
|
|
if (is_banned_extension(pathinfo($file_location_parts["basename"], PATHINFO_EXTENSION))) {
|
|
return array("Status" => "FAILED","Message" => "The file for resource {$ref} was not replaced. File {$file_location} is invalid.");
|
|
}
|
|
} elseif (api_validate_upload_url($file_location)) {
|
|
if (overquota()) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['disk_size_no_upload_explain']));
|
|
}
|
|
$upload_key = uniqid((int) $ref . "_");
|
|
$tmp_file_location = temp_local_download_remote_file($file_location, $upload_key);
|
|
if ($tmp_file_location === false) {
|
|
return ["Status" => "FAILED", "Message" => "The file for resource {$ref} was not replaced. The file could not be retrieved from {$file_location}"];
|
|
}
|
|
$file_location = $tmp_file_location;
|
|
} else {
|
|
return array("Status" => "FAILED","Message" => "The file for resource {$ref} was not replaced. File location {$file_location} is invalid.");
|
|
}
|
|
|
|
$duplicates = check_duplicate_checksum($file_location, false);
|
|
if (count($duplicates) > 0) {
|
|
$duplicates_string = implode(",", $duplicates);
|
|
return array("Status" => "FAILED","Message" => "The file for resource {$ref} was not replaced. Resources {$duplicates_string} already have a matching file.");
|
|
} else {
|
|
if (!$keep_original) {
|
|
if (in_array("rse_version", $plugins) && (!isset($rse_version_override_groups) || !in_array($usergroup, $rse_version_override_groups))) {
|
|
return array("Status" => "FAILED","Message" => "Invalid option 'keep_original=false'. Original file must be preserved because versioning is enabled.");
|
|
}
|
|
// Set flag that we want to override the versioning behaviour of the rse_version plugin
|
|
$rse_version_block = true;
|
|
} else {
|
|
// Set global otion so that this is not dependent on config
|
|
$replace_resource_preserve_option = true;
|
|
}
|
|
|
|
$GLOBALS["use_error_exception"] = true;
|
|
try {
|
|
$success = replace_resource_file($ref, $file_location, $no_exif, $autorotate, $keep_original);
|
|
} catch (Throwable $t) {
|
|
debug(
|
|
sprintf(
|
|
'[api_replace_resource_file] Failed to replace resource %s file with %s. Reason: %s',
|
|
$ref,
|
|
$file_location,
|
|
$t->getMessage()
|
|
)
|
|
);
|
|
unset($GLOBALS["use_error_exception"]);
|
|
return $generic_err_msg;
|
|
}
|
|
unset($GLOBALS["use_error_exception"]);
|
|
|
|
if (!$success) {
|
|
return $generic_err_msg;
|
|
}
|
|
}
|
|
|
|
return array("Status" => "SUCCESS","Message" => "Resource ID #$ref replaced");
|
|
}
|
|
|
|
|
|
/**
|
|
* API binding to get_data_by_field function.
|
|
*
|
|
* @param integer $ref Resource ref
|
|
* @param integer $field Resource type field ref
|
|
*
|
|
* @return boolean|array
|
|
*/
|
|
function api_get_data_by_field($ref, $field)
|
|
{
|
|
// Security: Check resource access, if not accessible to user, return FALSE.
|
|
$access = get_resource_access($ref);
|
|
if ($access == 2 || $access == RESOURCE_ACCESS_INVALID_REQUEST) {
|
|
return false;
|
|
}
|
|
|
|
// Get the data for a specific field for a specific resource.
|
|
$results = metadata_field_view_access($field) ? get_data_by_field($ref, $field) : false;
|
|
|
|
if (is_array($results)) {
|
|
$results_count = count($results);
|
|
for ($n = 0; $n < $results_count; $n++) {
|
|
$results[$n] = array_map("i18n_get_translated", $results[$n]);
|
|
}
|
|
}
|
|
|
|
return $results;
|
|
}
|
|
|
|
|
|
/**
|
|
* API binding to modified get_resource_collections function, as we only want to pass collection ID, name, and
|
|
* description for security purposes.
|
|
*
|
|
* @param integer $ref Resource ref
|
|
*
|
|
* @return boolean|array
|
|
*/
|
|
function api_get_resource_collections($ref)
|
|
{
|
|
// Security: Check for numeric input value; otherwise, return FALSE.
|
|
if (!is_numeric($ref)) {
|
|
return false;
|
|
}
|
|
|
|
// Get all the collections a resource is part of.
|
|
$results = get_resource_collections($ref);
|
|
|
|
// Create a new array containing only the collection ID, name, and description fields.
|
|
if (is_array($results)) {
|
|
$ref_collections = [];
|
|
$results_count = count($results);
|
|
|
|
for ($n = 0; $n < $results_count; $n++) {
|
|
$ref_collections[$n]["ref"] = $results[$n]["ref"];
|
|
$ref_collections[$n]["name"] = $results[$n]["name"];
|
|
$ref_collections[$n]["description"] = $results[$n]["description"];
|
|
}
|
|
|
|
for ($n = 0; $n < $results_count; $n++) {
|
|
$ref_collections[$n] = array_map("i18n_get_translated", $ref_collections[$n]);
|
|
}
|
|
} else // Resource is not part of a collection or other error.
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return $ref_collections;
|
|
}
|
|
|
|
function api_update_related_resource($ref, $related, $add = 1)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $enable_related_resources;
|
|
if (!$enable_related_resources) {
|
|
return false;
|
|
}
|
|
|
|
$related = explode(",", $related);
|
|
|
|
if (!is_numeric($add)) {
|
|
return false;
|
|
}
|
|
|
|
$addboolean = null;
|
|
if ((int) $add === 1) {
|
|
$addboolean = true;
|
|
} elseif ((int) $add === 0) {
|
|
$addboolean = false;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
return update_related_resource($ref, $related, $addboolean);
|
|
}
|
|
|
|
function api_get_collections_resource_count(string $refs)
|
|
{
|
|
if (checkperm('b')) {
|
|
return [];
|
|
}
|
|
|
|
$cols = array_filter(explode(',', $refs), 'collection_readable');
|
|
|
|
return get_collections_resource_count($cols);
|
|
}
|
|
|
|
function api_get_users($find = "", $exact_username_match = false)
|
|
{
|
|
// Forward to the internal function - with "usepermissions" locked to TRUE.
|
|
// Return specific columns only as there's sensitive information in the others such as password/session key.
|
|
return get_users(0, $find, "u.username", true, -1, "", false, "u.ref,u.username,u.email,u.fullname,u.usergroup", $exact_username_match);
|
|
}
|
|
|
|
function api_save_collection(int $ref, array $coldata)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (checkperm("b")) {
|
|
return false;
|
|
}
|
|
|
|
// DO NOT REMOVE - this is to prevent bypassing allowed coldata. save_collection() uses getvals if coldata is empty!
|
|
if (empty($coldata)) {
|
|
return false;
|
|
}
|
|
|
|
// Security control - only limited data is allowed to be set
|
|
$coldata = array_intersect_key(
|
|
$coldata,
|
|
[
|
|
'keywords' => 0,
|
|
'allow_changes' => 0,
|
|
'users' => 0,
|
|
'name' => 0,
|
|
'public' => 0,
|
|
'type' => 0,
|
|
'force_featured_collection_type' => 0,
|
|
'parent' => 0,
|
|
'thumbnail_selection_method' => 0,
|
|
'bg_img_resource_ref' => 0,
|
|
]
|
|
);
|
|
// Only certain collection types can be edited via the API
|
|
if (
|
|
isset($coldata["type"])
|
|
&& !in_array(
|
|
$coldata["type"],
|
|
array(
|
|
COLLECTION_TYPE_STANDARD,
|
|
COLLECTION_TYPE_FEATURED,
|
|
COLLECTION_TYPE_PUBLIC)
|
|
)
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
$fct_return = save_collection($ref, $coldata);
|
|
return is_null($fct_return) ? true : $fct_return;
|
|
}
|
|
|
|
function api_get_collection(int $ref)
|
|
{
|
|
// Only work for admin access for now - TO DO: incorporate permissions check within get_collections() internal function and remove the basic admin-only check here.
|
|
if (!checkperm("a")) {
|
|
return false;
|
|
}
|
|
return get_collection($ref);
|
|
}
|
|
|
|
function api_send_user_message($users, $text)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
return send_user_message($users, $text);
|
|
}
|
|
|
|
function api_get_profile_image($user)
|
|
{
|
|
return get_profile_image($user);
|
|
}
|
|
|
|
function api_get_system_status($basic = false)
|
|
{
|
|
return get_system_status($basic);
|
|
}
|
|
|
|
function api_relate_all_resources($related)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
global $enable_related_resources;
|
|
if (!$enable_related_resources) {
|
|
return false;
|
|
}
|
|
if (!is_array($related)) {
|
|
$related = explode(",", $related);
|
|
}
|
|
return relate_all_resources($related);
|
|
}
|
|
|
|
function api_show_hide_collection($collection, $show, $user)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
return show_hide_collection($collection, $show, $user);
|
|
}
|
|
|
|
function api_send_collection_to_admin($collection)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
return send_collection_to_admin($collection);
|
|
}
|
|
|
|
function api_reorder_featured_collections($refs)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (can_reorder_featured_collections()) {
|
|
sql_reorder_records('collection', $refs);
|
|
log_activity('via API - reorder_featured_collections', LOG_CODE_REORDERED, implode(', ', $refs), 'collection');
|
|
return true;
|
|
}
|
|
|
|
http_response_code(403);
|
|
return false;
|
|
}
|
|
|
|
function api_get_dash_search_data($link, $promimg)
|
|
{
|
|
return get_dash_search_data($link, $promimg);
|
|
}
|
|
|
|
function api_reorder_tabs($refs)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (acl_can_manage_tabs()) {
|
|
sql_reorder_records('tab', $refs);
|
|
return true;
|
|
}
|
|
|
|
http_response_code(403);
|
|
return false;
|
|
}
|
|
|
|
function api_delete_tabs($refs)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (acl_can_manage_tabs()) {
|
|
return delete_tabs($refs);
|
|
}
|
|
|
|
http_response_code(403);
|
|
return false;
|
|
}
|
|
|
|
function api_save_tab($tab)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (acl_can_manage_tabs()) {
|
|
if (save_tab($tab)) {
|
|
$tab = get_tabs_by_refs([$tab['ref']])[0];
|
|
$tab['name_translated'] = i18n_get_translated($tab['name']);
|
|
return ajax_response_ok($tab);
|
|
}
|
|
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_fail_save']));
|
|
}
|
|
|
|
http_response_code(403);
|
|
return false;
|
|
}
|
|
|
|
function api_mark_email_as_invalid($email)
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (!checkperm('a')) {
|
|
return false;
|
|
}
|
|
|
|
return mark_email_as_invalid($email);
|
|
}
|
|
|
|
function api_get_user_message($ref)
|
|
{
|
|
return get_user_message($ref);
|
|
}
|
|
|
|
function api_get_users_by_permission($permissions)
|
|
{
|
|
if (!is_array($permissions)) {
|
|
$permissions = explode(",", $permissions);
|
|
}
|
|
return get_users_by_permission($permissions);
|
|
}
|
|
|
|
/**
|
|
* Upload files using HTTP multipart.
|
|
*
|
|
* @param int $ref Resource ID
|
|
* @param bool $no_exif Do not extract embedded metadata
|
|
* @param bool $revert Delete all data and re-extract embedded data
|
|
* @param bool $previewonly Will use the uploaded file to replace preview image only
|
|
* @param int $alternative Use the uploaded file to replace the alternative file with the given ID
|
|
* Note that api_add_alternative_file() must be called first if creating a new alternative file
|
|
* If an $alternative identifier is specified then $previewonly is ignored and set to false
|
|
*
|
|
* @return array Returns JSend data back {@see ajax_functions.php} if upload failed, otherwise 204 HTTP status
|
|
*/
|
|
function api_upload_multipart(int $ref, bool $no_exif, bool $revert, bool $previewonly = false, int $alternative = 0): array
|
|
{
|
|
$request_checks = [
|
|
fn(): array => assert_post_request(true),
|
|
fn(): array => assert_content_type('multipart/form-data', $_SERVER['CONTENT_TYPE'] ?? ''),
|
|
// Ensure a "file" has been POSTd
|
|
function (): array {
|
|
http_response_code(400);
|
|
return isset($_FILES['file'])
|
|
? []
|
|
: ajax_response_fail(ajax_build_message(
|
|
str_replace('%key', 'file', $GLOBALS['lang']['error-request-missing-key'])
|
|
));
|
|
},
|
|
// Check file has been received
|
|
function (): array {
|
|
if ($_FILES['file']['error'] === UPLOAD_ERR_INI_SIZE) {
|
|
http_response_code(413);
|
|
return ajax_response_fail(ajax_build_message(
|
|
sprintf($GLOBALS['lang']['plupload-maxfilesize'], ini_get('upload_max_filesize'))
|
|
));
|
|
} elseif ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
|
|
http_response_code(500);
|
|
return ajax_response_fail(ajax_build_message(
|
|
sprintf(
|
|
'(%s #%s) %s',
|
|
$GLOBALS['lang']['error'],
|
|
$_FILES['file']['error'],
|
|
$GLOBALS['lang']['upload_error_unknown']
|
|
)
|
|
));
|
|
} else {
|
|
return [];
|
|
}
|
|
},
|
|
];
|
|
foreach ($request_checks as $check) {
|
|
$check_result = $check();
|
|
if (!empty($check_result)) {
|
|
return $check_result;
|
|
}
|
|
}
|
|
|
|
// Check not over quota
|
|
if (overquota()) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['disk_size_no_upload_explain']));
|
|
}
|
|
|
|
if ($alternative > 0) {
|
|
$previewonly = false;
|
|
}
|
|
// Set the userfile so upload_file can carry out the rest of the work as usual
|
|
$_FILES['userfile'] = $_FILES['file'];
|
|
|
|
if (!get_edit_access($ref)) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error-permissiondenied']));
|
|
}
|
|
|
|
if ($previewonly) {
|
|
if (!can_upload_preview_image($ref)) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error-permissiondenied']));
|
|
}
|
|
$success = upload_preview($ref);
|
|
if ($success) {
|
|
http_response_code(204);
|
|
return ajax_response_ok_no_data();
|
|
} else {
|
|
http_response_code(500);
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_upload_failed']));
|
|
}
|
|
} elseif ($alternative > 0) {
|
|
if (checkperm('A')) {
|
|
// This is a negative permission. If you have it you can't manage alternative files
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error-permissiondenied']));
|
|
}
|
|
// Check this alternative is for the correct resource
|
|
$alternatives = get_alternative_files($ref);
|
|
|
|
if (!in_array($alternative, array_column($alternatives, "ref"))) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_invalid_input']));
|
|
}
|
|
if (!can_upload_preview_image($ref)) {
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error-permissiondenied']));
|
|
}
|
|
$processfile = $_FILES['userfile'];
|
|
$extension = pathinfo($processfile['name'])["extension"] ?? "";
|
|
if (is_banned_extension($extension)) {
|
|
http_response_code(403);
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_upload_invalid_file']));
|
|
}
|
|
|
|
$altpath = get_resource_path($ref, true, "", true, $extension, -1, 1, false, "", $alternative);
|
|
if (move_uploaded_file($processfile['tmp_name'], $altpath)) {
|
|
chmod($altpath, 0777);
|
|
$file_size = filesize_unlimited($altpath);
|
|
// Update alternative file data.
|
|
$altdata = [
|
|
"name" => (string) $processfile["name"],
|
|
"file_name" => (string) $processfile["name"],
|
|
"file_extension" => (string) $extension,
|
|
"file_size" => (int) $file_size,
|
|
];
|
|
save_alternative_file($ref, $alternative, $altdata);
|
|
create_previews($ref, false, $extension, false, false, $alternative);
|
|
http_response_code(204);
|
|
return ajax_response_ok_no_data();
|
|
}
|
|
|
|
http_response_code(500);
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_upload_failed']));
|
|
} else {
|
|
// Main resource file upload
|
|
if ($GLOBALS['file_upload_block_duplicates']) {
|
|
$duplicates = check_duplicate_checksum($_FILES['file']['tmp_name'], false);
|
|
if (count($duplicates) > 0) {
|
|
return ajax_response_fail(ajax_build_message(
|
|
str_replace('[resources]', implode(', ', $duplicates), $GLOBALS['lang']['error_upload_duplicate_file'])
|
|
));
|
|
}
|
|
}
|
|
if (upload_file($ref, $no_exif, $revert)) {
|
|
http_response_code(204);
|
|
return ajax_response_ok_no_data();
|
|
}
|
|
}
|
|
|
|
http_response_code(500);
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_upload_failed']));
|
|
}
|
|
|
|
/**
|
|
* Get metadata field information for all (matching) fields.
|
|
*
|
|
* @param string $by_resource_types Filter result by resource type. If multiple, use a CSV of resource types.
|
|
* @param string $find Filter result by fuzzy searching in different properties (e.g name, title, ref, help text etc)
|
|
* @param string $by_types Filter result by field type ({@see FIELD_TYPE_* constants}). If multiple, use a CSV of field types.
|
|
*
|
|
* @return array Returns the matching fields' information or 403 HTTP status if not authorised
|
|
*/
|
|
function api_get_resource_type_fields(string $by_resource_types = '', string $find = '', string $by_types = ''): array
|
|
{
|
|
if (!checkperm('a')) {
|
|
http_response_code(403);
|
|
return [];
|
|
}
|
|
|
|
return array_map(
|
|
'execution_lockout_remove_resource_type_field_props',
|
|
get_resource_type_fields(
|
|
parse_csv_to_list_of_type($by_resource_types, 'is_int_loose'),
|
|
'ref',
|
|
'asc',
|
|
trim($find),
|
|
parse_csv_to_list_of_type($by_types, 'is_int_loose'),
|
|
true
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Create metadata field
|
|
*
|
|
* @param string $name Field name
|
|
* @param string $resource_types CSV of applicable resource types for this field. Use 0 (zero) for global, for others
|
|
* {@see API get_resource_types()}
|
|
* @param int $type Metadata field type. For values, {@see FIELD_TYPE_* constants}
|
|
* @return array Returns JSend data back {@see ajax_functions.php} and 200 HTTP status or 403 HTTP status if not authorised
|
|
*/
|
|
function api_create_resource_type_field(string $name, string $resource_types, int $type): array
|
|
{
|
|
if (!checkperm('a')) {
|
|
http_response_code(403);
|
|
return [];
|
|
}
|
|
|
|
/** @var int|array $parse_rt_csv */
|
|
$parse_rt_csv = function (string $RT) {
|
|
// Parse CSV to ordered list of integers
|
|
$parse_input = parse_csv_to_list_of_type($RT, 'is_int_loose');
|
|
$parse_input = array_map('intval', $parse_input);
|
|
asort($parse_input, SORT_NUMERIC);
|
|
$parse_input = array_values($parse_input);
|
|
|
|
// Global field? (ie resource type = 0)
|
|
$rev = array_reverse($parse_input);
|
|
return array_pop($rev) === 0 ? 0 : $parse_input;
|
|
};
|
|
|
|
$ref = create_resource_type_field($name, $parse_rt_csv($resource_types), $type, '', true);
|
|
return $ref !== false
|
|
? ajax_response_ok(['ref' => $ref])
|
|
: ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_fail_save']));
|
|
}
|
|
|
|
/**
|
|
* Expose {@see get_featured_collections} to the API
|
|
* @param int $parent The feature collection parent's ref. Use 0 for obtaining the root ones.
|
|
*/
|
|
function api_get_featured_collections($parent): array
|
|
{
|
|
return is_int_loose($parent) ? get_featured_collections($parent, []) : [];
|
|
}
|
|
|
|
function api_get_edit_access(int $resource): bool
|
|
{
|
|
return get_edit_access($resource);
|
|
}
|
|
|
|
/**
|
|
* Toggle active state for nodes
|
|
* @see https://www.resourcespace.com/knowledge-base/developers/fixed-list-fields
|
|
* @param array $refs List of node IDs
|
|
* @return array Returns the affected nodes' active state (including empty list) and 403 HTTP status if not authorised.
|
|
*/
|
|
function api_toggle_active_state_for_nodes(array $refs): array
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if ($assert_post !== []) {
|
|
return $assert_post;
|
|
}
|
|
|
|
if (checkperm('k')) {
|
|
return toggle_active_state_for_nodes($refs);
|
|
}
|
|
|
|
http_response_code(403);
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Expose {@see get_processing_message} to the API
|
|
*
|
|
* @return false|array
|
|
*/
|
|
function api_get_processing_message()
|
|
{
|
|
return get_processing_message();
|
|
}
|
|
|
|
/**
|
|
* Expose {@see checkperm} to the API
|
|
*
|
|
* @param string $perm The permissions string to check for.
|
|
* @return bool
|
|
*/
|
|
function api_checkperm($perm)
|
|
{
|
|
return checkperm($perm);
|
|
}
|
|
|
|
/**
|
|
* Expose {@see get_resource_access} to the API
|
|
*
|
|
* @param int $resource The reference ID of the resource.
|
|
* @return false|int The access level for the resource, or false if a number was not supplied.
|
|
*/
|
|
function api_get_resource_access($resource)
|
|
{
|
|
if (!is_int_loose($resource)) {
|
|
return false;
|
|
}
|
|
return get_resource_access($resource);
|
|
}
|
|
|
|
/**
|
|
* Exposing {@see resource_file_readonly} to the API
|
|
* @param int|numeric-string $ref Resource ID
|
|
* @return array{status:"success","data":{"readonly":bool}}|array{status:"fail","data":{"message":string}}
|
|
*/
|
|
function api_resource_file_readonly($ref): array
|
|
{
|
|
if (is_positive_int_loose($ref)) {
|
|
return ajax_response_ok(['readonly' => resource_file_readonly($ref)]);
|
|
} else {
|
|
http_response_code(400);
|
|
return ajax_response_fail(ajax_build_message($GLOBALS['lang']['error_resource_id_non_numeric']));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exposing {@see delete_resources_in_collection} to the API
|
|
*
|
|
* @param int $collection ID of collection containing resources to be deleted.
|
|
*/
|
|
function api_delete_resources_in_collection($collection): bool
|
|
{
|
|
$assert_post = assert_post_request(defined('API_AUTHMODE_NATIVE'));
|
|
if (!empty($assert_post)) {
|
|
return false;
|
|
}
|
|
|
|
return delete_resources_in_collection($collection);
|
|
}
|