function ProcessFolder($folder, $version_dir, &$resource_array, &$resource_error) { global $lang, $syncdir, $nogo, $staticsync_max_files, $count, $done, $modtimes, $lastsync, $ffmpeg_preview_extension, $staticsync_autotheme, $staticsync_folder_structure, $staticsync_extension_mapping_default, $staticsync_extension_mapping, $staticsync_mapped_category_tree, $staticsync_title_includes_path, $staticsync_ingest, $staticsync_mapfolders, $staticsync_alternatives_suffix, $theme_category_levels, $staticsync_defaultstate, $additional_archive_states, $staticsync_extension_mapping_append_values, $image_alternatives, $exclude_resize, $post_host, $media_endpoint, $image_required_height, $sync_bucket, $aws_key, $aws_secret_key; $collection = 0; echo "Processing Folder: {$folder}" . PHP_EOL; #$alt_path = get_resource_path(59, TRUE, '', FALSE, 'png', -1, 1, FALSE, '', 4); # List all files in this folder. $dh = opendir($folder); while (($file = readdir($dh)) !== false) { if ($file == '.' || $file == '..') { continue; } $filetype = filetype($folder . "/" . $file); $fullpath = $folder . "/" . $file; $shortpath = str_replace($syncdir . "/", '', $fullpath); # Work out extension $extension = explode(".", $file); if (count($extension) > 1) { $extension = trim(strtolower($extension[count($extension) - 1])); } else { //No extension $extension = ""; } if (strpos($fullpath, $nogo)) { echo "This directory is to be ignored." . PHP_EOL; continue; } if ($staticsync_mapped_category_tree) { $path_parts = explode("/", $shortpath); array_pop($path_parts); touch_category_tree_level($path_parts); } # -----FOLDERS------------- if (($filetype == "dir" || $filetype == "link") && strpos($nogo, "[{$file}]") === false && strpos($file, $staticsync_alternatives_suffix) === false) { # Get current version direcotries. if (preg_match("/[0-9]{2}-[0-9]{2}-[0-9]{4}\$/", $file)) { if (!in_array($file, $version_dir)) { array_push($version_dir, $file); } if (preg_match('/in_progress*/', $file)) { echo "The Barcode is still being processed." . PHP_EOL; continue; } } # Recurse ProcessFolder($folder . "/" . $file, $version_dir, $resource_array, $resource_error); } $psd_files = array(); if (preg_match('/images/', $fullpath)) { $path_array = explode('/', $fullpath); $psd_array = array_splice($path_array, 0, array_search('images', $path_array)); $psd_path = implode('/', $psd_array) . '/psd/'; $psd_files = array_diff(scandir($psd_path), array('..', '.')); foreach ($psd_files as $index => $psd_file) { $psd_files[$index] = pathinfo($psd_file, PATHINFO_FILENAME); } } # -------FILES--------------- if ($filetype == "file" && substr($file, 0, 1) != "." && strtolower($file) != "thumbs.db") { /* Below Code Adapted from CMay's bug report */ global $banned_extensions; # Check to see if extension is banned, do not add if it is banned if (array_search($extension, $banned_extensions)) { continue; } /* Above Code Adapted from CMay's bug report */ $count++; if ($count > $staticsync_max_files) { return true; } $last_sync_date = sql_value("select value from sysvars where name = 'last_sync'", ""); $file_creation_date = date("Y-m-d H:i:s", filectime($fullpath)); if (isset($last_sync_date) && $last_sync_date > $file_creation_date) { echo "No new file found.." . PHP_EOL; continue; } # Already exists? if (!isset($done[$shortpath])) { echo "Processing file: {$fullpath}" . PHP_EOL; if ($collection == 0 && $staticsync_autotheme) { # Make a new collection for this folder. $e = explode("/", $shortpath); $theme = ucwords($e[0]); $themesql = "theme='" . ucwords(escape_check($e[0])) . "'"; $themecolumns = "theme"; $themevalues = "'" . ucwords(escape_check($e[0])) . "'"; if ($staticsync_folder_structure) { for ($x = 0; $x < count($e) - 1; $x++) { if ($x != 0) { $themeindex = $x + 1; if ($themeindex > $theme_category_levels) { $theme_category_levels = $themeindex; if ($x == count($e) - 2) { echo PHP_EOL . PHP_EOL . "UPDATE THEME_CATEGORY_LEVELS TO {$themeindex} IN CONFIG!!!!" . PHP_EOL . PHP_EOL; } } $th_name = ucwords(escape_check($e[$x])); $themesql .= " AND theme{$themeindex} = '{$th_name}'"; $themevalues .= ",'{$th_name}'"; $themecolumns .= ",theme{$themeindex}"; } } } $name = count($e) == 1 ? '' : $e[count($e) - 2]; echo "Collection {$name}, theme={$theme}" . PHP_EOL; $ul_username = $theme; $escaped_name = escape_check($name); $collection = sql_value("SELECT ref value FROM collection WHERE name='{$escaped_name}' AND {$themesql}", 0); if ($collection == 0) { sql_query("INSERT INTO collection (name,created,public,{$themecolumns},allow_changes)\n VALUES ('{$escaped_name}', NOW(), 1, {$themevalues}, 0)"); $collection = sql_insert_id(); } } # Work out a resource type based on the extension. $type = $staticsync_extension_mapping_default; reset($staticsync_extension_mapping); foreach ($staticsync_extension_mapping as $rt => $extensions) { if (in_array($extension, $extensions)) { $type = $rt; } } $modified_type = hook('modify_type', 'staticsync', array($type)); if (is_numeric($modified_type)) { $type = $modified_type; } # Formulate a title if ($staticsync_title_includes_path) { $title_find = array('/', '_', ".{$extension}"); $title_repl = array(' - ', ' ', ''); $title = ucfirst(str_ireplace($title_find, $title_repl, $shortpath)); } else { $title = str_ireplace(".{$extension}", '', $file); } $modified_title = hook('modify_title', 'staticsync', array($title)); if ($modified_title !== false) { $title = $modified_title; } # Import this file #$r = import_resource($shortpath, $type, $title, $staticsync_ingest); #Check for file name containing the psd. if (!empty($psd_files)) { $image_file_array = explode('/', $fullpath); $image_file = $image_file_array[count($image_file_array) - 1]; $image_psd_name = explode('_', $image_file)[0]; if (array_search($image_psd_name, $psd_files)) { #Image name is in right format. if (!validate_image_size($fullpath, $image_required_height)) { $resource_error['size'][$file] = $fullpath; } $r = import_resource($fullpath, $type, $title, $staticsync_ingest); sql_query("INSERT INTO resource_data (resource,resource_type_field,value)\n VALUES ('{$r}', (SELECT ref FROM resource_type_field WHERE name = 'logical_id'), '{$image_psd_name}')"); $original_filepath = sql_query("SELECT value FROM resource_data WHERE resource = '{$r}' AND\n resource_type_field = (SELECT ref FROM resource_type_field where name = 'original_filepath')"); if (isset($original_filepath)) { sql_query("INSERT INTO resource_data (resource,resource_type_field,value)\n VALUES ('{$r}',(SELECT ref FROM resource_type_field WHERE name = 'original_filepath'), '{$fullpath}')"); } } else { echo "Filename '{$fullpath}' is not in right format.." . PHP_EOL; $resource_error['name'][$file] = $fullpath; continue; } } elseif (word_in_string($exclude_resize, explode('/', $fullpath))) { $r = import_resource($fullpath, $type, $title, $staticsync_ingest); } if ($r !== false) { array_push($resource_array, $r); # Create current version for resource. #print_r($version_dir); if (count($version_dir) == 1) { sql_query("INSERT into resource_data (resource,resource_type_field,value)\n VALUES ('{$r}',(SELECT ref FROM resource_type_field WHERE name = 'current'), 'TRUE')"); } $sync_status = sync_to_s3($syncdir, $sync_bucket, $aws_key, $aws_secret_key); if (!$sync_status) { echo "Failed to sync"; } # Add to mapped category tree (if configured) if (isset($staticsync_mapped_category_tree)) { $basepath = ''; # Save tree position to category tree field # For each node level, expand it back to the root so the full path is stored. for ($n = 0; $n < count($path_parts); $n++) { if ($basepath != '') { $basepath .= "~"; } $basepath .= $path_parts[$n]; $path_parts[$n] = $basepath; } update_field($r, $staticsync_mapped_category_tree, "," . join(",", $path_parts)); } #This is an override to add user data to the resouces if (!isset($userref)) { $ul_username = ucfirst(strtolower($ul_username)); $current_user_ref = sql_query("Select ref from user where username = '******' "); if (!empty($current_user_ref)) { $current_user_ref = $current_user_ref[0]['ref']; sql_query("UPDATE resource SET created_by='{$current_user_ref}' where ref = {$r}"); } } # default access level. This may be overridden by metadata mapping. $accessval = 0; # StaticSync path / metadata mapping # Extract metadata from the file path as per $staticsync_mapfolders in config.php if (isset($staticsync_mapfolders)) { foreach ($staticsync_mapfolders as $mapfolder) { $match = $mapfolder["match"]; $field = $mapfolder["field"]; $level = $mapfolder["level"]; if (strpos("/" . $shortpath, $match) !== false) { # Match. Extract metadata. $path_parts = explode("/", $shortpath); if ($level < count($path_parts)) { // special cases first. if ($field == 'access') { # access level is a special case # first determine if the value matches a defined access level $value = $path_parts[$level - 1]; for ($n = 0; $n < 3; $n++) { # if we get an exact match or a match except for case if ($value == $lang["access" . $n] || strtoupper($value) == strtoupper($lang['access' . $n])) { $accessval = $n; echo "Will set access level to " . $lang['access' . $n] . " ({$n})" . PHP_EOL; } } } else { if ($field == 'archive') { # archive level is a special case # first determin if the value matches a defined archive level $value = $mapfolder["archive"]; $archive_array = array_merge(array(-2, -1, 0, 1, 2, 3), $additional_archive_states); if (in_array($value, $archive_array)) { $archiveval = $value; echo "Will set archive level to " . $lang['status' . $value] . " ({$archiveval})" . PHP_EOL; } } else { # Save the value #print_r($path_parts); $value = $path_parts[$level - 1]; if ($staticsync_extension_mapping_append_values) { $given_value = $value; // append the values if possible...not used on dropdown, date, categroy tree, datetime, or radio buttons $field_info = get_resource_type_field($field); if (in_array($field['type'], array(0, 1, 2, 4, 5, 6, 7, 8))) { $old_value = sql_value("select value value from resource_data where resource={$r} and resource_type_field={$field}", ""); $value = append_field_value($field_info, $value, $old_value); } } update_field($r, $field, trim($value)); if (strtotime(trim($value))) { add_keyword_mappings($r, trim($value), $field, false, true); } else { add_keyword_mappings($r, trim($value), $field); } if ($staticsync_extension_mapping_append_values) { $value = $given_value; } echo " - Extracted metadata from path: {$value}" . PHP_EOL; } } } } } } #Resize only original images. if (!word_in_string($exclude_resize, explode('/', $fullpath))) { echo "Creating preview.."; create_previews($r, false, $extension, false, false, -1, false, $staticsync_ingest); } # update access level sql_query("UPDATE resource SET access = '{$accessval}',archive='{$staticsync_defaultstate}' WHERE ref = '{$r}'"); # Add any alternative files $altpath = $fullpath . $staticsync_alternatives_suffix; if ($staticsync_ingest && file_exists($altpath)) { $adh = opendir($altpath); while (($altfile = readdir($adh)) !== false) { $filetype = filetype($altpath . "/" . $altfile); if ($filetype == "file" && substr($file, 0, 1) != "." && strtolower($file) != "thumbs.db") { # Create alternative file # Find extension $ext = explode(".", $altfile); $ext = $ext[count($ext) - 1]; $description = str_replace("?", strtoupper($ext), $lang["originalfileoftype"]); $file_size = filesize_unlimited($altpath . "/" . $altfile); $aref = add_alternative_file($r, $altfile, $description, $altfile, $ext, $file_size); $path = get_resource_path($r, true, '', true, $ext, -1, 1, false, '', $aref); rename($altpath . "/" . $altfile, $path); # Move alternative file } } } # Add to collection if ($staticsync_autotheme) { $test = ''; $test = sql_query("SELECT * FROM collection_resource WHERE collection='{$collection}' AND resource='{$r}'"); if (count($test) == 0) { sql_query("INSERT INTO collection_resource (collection, resource, date_added)\n VALUES ('{$collection}', '{$r}', NOW())"); } } } else { # Import failed - file still being uploaded? echo " *** Skipping file - it was not possible to move the file (still being imported/uploaded?)" . PHP_EOL; } } else { # check modified date and update previews if necessary $filemod = filemtime($fullpath); if (array_key_exists($shortpath, $modtimes) && $filemod > strtotime($modtimes[$shortpath])) { # File has been modified since we last created previews. Create again. $rd = sql_query("SELECT ref, has_image, file_modified, file_extension FROM resource\n WHERE file_path='" . escape_check($shortpath) . "'"); if (count($rd) > 0) { $rd = $rd[0]; $rref = $rd["ref"]; echo "Resource {$rref} has changed, regenerating previews: {$fullpath}" . PHP_EOL; extract_exif_comment($rref, $rd["file_extension"]); # extract text from documents (e.g. PDF, DOC). global $extracted_text_field; if (isset($extracted_text_field)) { if (isset($unoconv_path) && in_array($extension, $unoconv_extensions)) { // omit, since the unoconv process will do it during preview creation below } else { extract_text($rref, $extension); } } # Store original filename in field, if set global $filename_field; if (isset($filename_field)) { update_field($rref, $filename_field, $file); } create_previews($rref, false, $rd["file_extension"], false, false, -1, false, $staticsync_ingest); sql_query("UPDATE resource SET file_modified=NOW() WHERE ref='{$rref}'"); } } } } } }
resource_type_config_override($resource["resource_type"]); // get mp3 paths if necessary and set $use_mp3_player switch if (!(isset($resource['is_transcoding']) && $resource['is_transcoding'] == 1) && (in_array($resource["file_extension"], $ffmpeg_audio_extensions) || $resource["file_extension"] == "mp3") && $mp3_player) { $use_mp3_player = true; } else { $use_mp3_player = false; } if ($use_mp3_player) { $mp3realpath = get_resource_path($ref, true, "", false, "mp3"); if (file_exists($mp3realpath)) { $mp3path = get_resource_path($ref, false, "", false, "mp3"); } } # Dev feature - regenerate exif data. if (getval("regenexif", "") != "") { extract_exif_comment($ref, $resource["file_extension"]); $resource = get_resource_data($ref, false); } # Load access level $access = get_resource_access($ref); hook("beforepermissionscheck"); # check permissions (error message is not pretty but they shouldn't ever arrive at this page unless entering a URL manually) if ($access == 2) { exit("This is a confidential resource."); } hook("afterpermissionscheck"); # Establish if this is a metadata template resource, so we can switch off certain unnecessary features $is_template = isset($metadata_template_resource_type) && $resource["resource_type"] == $metadata_template_resource_type; $title_field = $view_title_field; # If this is a metadata template and we're using field data, change title_field to the metadata template title field if (isset($metadata_template_resource_type) && $resource["resource_type"] == $metadata_template_resource_type) {
<?php # This script is useful for initial imports when you're working out metadata mappings. However, be aware that # local ResourceSpace field edits could be overwritten by original file metadata during this process. include "../../include/db.php"; include "../../include/authenticate.php"; if (!checkperm("a")) { exit("Permission denied"); } include "../../include/general.php"; include "../../include/resource_functions.php"; include "../../include/image_processing.php"; set_time_limit(60 * 60 * 40); echo "Updating EXIF/IPTC..."; $rd = sql_query("select ref,file_extension from resource where has_image=1 "); for ($n = 0; $n < count($rd); $n++) { $ref = $rd[$n]['ref']; echo "." . $ref; extract_exif_comment($rd[$n]['ref'], $rd[$n]['file_extension']); } echo "...done.";
function update_resource($r,$path,$type,$title,$ingest=false) { # Update the resource with the file at the given path # Note that the file will be used at it's present location and will not be copied. global $syncdir,$staticsync_prefer_embedded_title; update_resource_type($r, $type); # Work out extension based on path $extension=explode(".",$path);$extension=trim(strtolower(end($extension))); # file_path should only really be set to indicate a staticsync location. Otherwise, it should just be left blank. if ($ingest){$file_path="";} else {$file_path=escape_check($path);} # Store extension/data in the database sql_query("update resource set archive=0,file_path='".$file_path."',file_extension='$extension',preview_extension='$extension',file_modified=now() where ref='$r'"); # Store original filename in field, if set if (!$ingest) { # This file remains in situ; store the full path in file_path to indicate that the file is stored remotely. global $filename_field; if (isset($filename_field)) { $s=explode("/",$path); $filename=end($s); update_field($r,$filename_field,$filename); } } else { # This file is being ingested. Store only the filename. $s=explode("/",$path); $filename=end($s); global $filename_field; if (isset($filename_field)) { update_field($r,$filename_field,$filename); } # Move the file global $syncdir; $destination=get_resource_path($r,true,"",true,$extension); $result=rename($syncdir . "/" . $path,$destination); if ($result===false) { # The rename failed. The file is possibly still being copied or uploaded and must be ignored on this pass. # Delete the resouce just created and return false. delete_resource($r); return false; } chmod($destination,0777); } # generate title and extract embedded metadata # order depends on which title should be the default (embedded or generated) if ($staticsync_prefer_embedded_title) { update_field($r,8,$title); extract_exif_comment($r,$extension); } else { extract_exif_comment($r,$extension); update_field($r,8,$title); } # Ensure folder is created, then create previews. get_resource_path($r,false,"pre",true,$extension); # Generate previews/thumbnails (if configured i.e if not completed by offline process 'create_previews.php') global $enable_thumbnail_creation_on_upload; if ($enable_thumbnail_creation_on_upload) {create_previews($r,false,$extension);} # Pass back the newly created resource ID. return $r; }
if (!$ref) { $ref = create_resource(getval("resourcetype", 1), $status, $userref); } $path_parts = pathinfo($_FILES['userfile']['name']); $extension = strtolower($path_parts['extension']); $filepath = get_resource_path($ref, true, "", true, $extension); $collection = getvalescaped('collection', "", true); $result = move_uploaded_file($_FILES['userfile']['tmp_name'], $filepath); $wait = sql_query("update resource set file_extension='{$extension}',preview_extension='jpg',file_modified=now() ,has_image=0 where ref='{$ref}'"); # Store original filename in field, if set global $filename_field; if (isset($filename_field)) { $wait = update_field($ref, $filename_field, $_FILES['userfile']['name']); } // extract metadata $wait = extract_exif_comment($ref, $extension); $resource = get_resource_data($ref); //create previews if ($camera_autorotation) { AutoRotateImage($filepath); } $wait = create_previews($ref, false, $extension); // add resource to collection if ($collection != "") { $collection_exists = sql_value("select name value from collection where ref='" . escape_check($collection) . "'", ""); if ($collection_exists != "") { if (!add_resource_to_collection($ref, $collection)) { header("HTTP/1.0 403 Forbidden."); echo "HTTP/1.0 403 Forbidden. Collection is not writable by this user.\n"; exit; }
function ProcessFolder($folder) { global $lang, $syncdir, $nogo, $staticsync_max_files, $count, $done, $modtimes, $lastsync, $ffmpeg_preview_extension, $staticsync_autotheme, $staticsync_folder_structure, $staticsync_extension_mapping_default, $staticsync_extension_mapping, $staticsync_mapped_category_tree, $staticsync_title_includes_path, $staticsync_ingest, $staticsync_mapfolders, $staticsync_alternatives_suffix, $theme_category_levels, $staticsync_defaultstate; $collection = 0; echo "Processing Folder: $folder" . PHP_EOL; # List all files in this folder. $dh = opendir($folder); while (($file = readdir($dh)) !== false) { if ( $file == '.' || $file == '..') { continue; } $filetype = filetype($folder . "/" . $file); $fullpath = $folder . "/" . $file; $shortpath = str_replace($syncdir . "/", '', $fullpath); # Work out extension $extension = explode(".", $file); if(count($extension)>1) { $extension = trim(strtolower($extension[count($extension)-1])); } else { //No extension $extension=""; } if ($staticsync_mapped_category_tree) { $path_parts = explode("/", $shortpath); array_pop($path_parts); touch_category_tree_level($path_parts); } # -----FOLDERS------------- if ((($filetype == "dir") || $filetype == "link") && (strpos($nogo, "[$file]") === false) && (strpos($file, $staticsync_alternatives_suffix) === false)) { # Recurse ProcessFolder($folder . "/" . $file); } # -------FILES--------------- if (($filetype == "file") && (substr($file,0,1) != ".") && (strtolower($file) != "thumbs.db")) { /* Below Code Adapted from CMay's bug report */ global $banned_extensions; # Check to see if extension is banned, do not add if it is banned if(array_search($extension, $banned_extensions)){continue;} /* Above Code Adapted from CMay's bug report */ $count++; if ($count > $staticsync_max_files) { return(true); } # Already exists? if (!isset($done[$shortpath])) { echo "Processing file: $fullpath" . PHP_EOL; if ($collection == 0 && $staticsync_autotheme) { # Make a new collection for this folder. $e = explode("/", $shortpath); $theme = ucwords($e[0]); $themesql = "theme='" . ucwords(escape_check($e[0])) . "'"; $themecolumns = "theme"; $themevalues = "'" . ucwords(escape_check($e[0])) . "'"; if ($staticsync_folder_structure) { for ($x=0;$x<count($e)-1;$x++) { if ($x != 0) { $themeindex = $x+1; if ($themeindex >$theme_category_levels) { $theme_category_levels = $themeindex; if ($x == count($e)-2) { echo PHP_EOL . PHP_EOL . "UPDATE THEME_CATEGORY_LEVELS TO $themeindex IN CONFIG!!!!" . PHP_EOL . PHP_EOL; } } $th_name = ucwords(escape_check($e[$x])); $themesql .= " AND theme{$themeindex} = '$th_name'"; $themevalues .= ",'$th_name'"; $themecolumns .= ",theme{$themeindex}"; } } } $name = (count($e) == 1) ? '' : $e[count($e)-2]; echo "Collection $name, theme=$theme" . PHP_EOL; $escaped_name = escape_check($name); $collection = sql_value("SELECT ref value FROM collection WHERE name='$escaped_name' AND $themesql", 0); if ($collection == 0) { sql_query("INSERT INTO collection (name,created,public,$themecolumns,allow_changes) VALUES ('$escaped_name', NOW(), 1, $themevalues, 0)"); $collection = sql_insert_id(); } } # Work out a resource type based on the extension. $type = $staticsync_extension_mapping_default; reset($staticsync_extension_mapping); foreach ($staticsync_extension_mapping as $rt => $extensions) { if (in_array($extension,$extensions)) { $type = $rt; } } $modified_type = hook('modify_type', 'staticsync', array( $type )); if (is_numeric($modified_type)) { $type = $modified_type; } # Formulate a title if ($staticsync_title_includes_path) { $title_find = array('/', '_', ".$extension" ); $title_repl = array(' - ', ' ', ''); $title = ucfirst(str_ireplace($title_find, $title_repl, $shortpath)); } else { $title = str_ireplace(".$extension", '', $file); } $modified_title = hook('modify_title', 'staticsync', array( $title )); if ($modified_title !== false) { $title = $modified_title; } # Import this file $r = import_resource($shortpath, $type, $title, $staticsync_ingest); if ($r !== false) { # Add to mapped category tree (if configured) if (isset($staticsync_mapped_category_tree)) { $basepath = ''; # Save tree position to category tree field # For each node level, expand it back to the root so the full path is stored. for ($n=0;$n<count($path_parts);$n++) { if ($basepath != '') { $basepath .= "~"; } $basepath .= $path_parts[$n]; $path_parts[$n] = $basepath; } update_field($r, $staticsync_mapped_category_tree, "," . join(",", $path_parts)); } # default access level. This may be overridden by metadata mapping. $accessval = 0; # StaticSync path / metadata mapping # Extract metadata from the file path as per $staticsync_mapfolders in config.php if (isset($staticsync_mapfolders)) { foreach ($staticsync_mapfolders as $mapfolder) { $match = $mapfolder["match"]; $field = $mapfolder["field"]; $level = $mapfolder["level"]; if (strpos("/" . $shortpath, $match) !== false) { # Match. Extract metadata. $path_parts = explode("/", $shortpath); if ($level < count($path_parts)) { // special cases first. if ($field == 'access') { # access level is a special case # first determine if the value matches a defined access level $value = $path_parts[$level-1]; for ($n=0; $n<3; $n++){ # if we get an exact match or a match except for case if ($value == $lang["access" . $n] || strtoupper($value) == strtoupper($lang['access' . $n])) { $accessval = $n; echo "Will set access level to " . $lang['access' . $n] . " ($n)" . PHP_EOL; } } } else { # Save the value print_r($path_parts); $value = $path_parts[$level-1]; update_field ($r, $field, $value); echo " - Extracted metadata from path: $value" . PHP_EOL; } } } } } # update access level sql_query("UPDATE resource SET access = '$accessval',archive='$staticsync_defaultstate' WHERE ref = '$r'"); # Add any alternative files $altpath = $fullpath . $staticsync_alternatives_suffix; if ($staticsync_ingest && file_exists($altpath)) { $adh = opendir($altpath); while (($altfile = readdir($adh)) !== false) { $filetype = filetype($altpath . "/" . $altfile); if (($filetype == "file") && (substr($file,0,1) != ".") && (strtolower($file) != "thumbs.db")) { # Create alternative file # Find extension $ext = explode(".", $altfile); $ext = $ext[count($ext)-1]; $description = str_replace("?", strtoupper($ext), $lang["originalfileoftype"]); $file_size = filesize_unlimited($altpath . "/" . $altfile); $aref = add_alternative_file($r, $altfile, $description, $altfile, $ext, $file_size); $path = get_resource_path($r, true, '', true, $ext, -1, 1, false, '', $aref); rename($altpath . "/" . $altfile,$path); # Move alternative file } } } # Add to collection if ($staticsync_autotheme) { $test = ''; $test = sql_query("SELECT * FROM collection_resource WHERE collection='$collection' AND resource='$r'"); if (count($test) == 0) { sql_query("INSERT INTO collection_resource (collection, resource, date_added) VALUES ('$collection', '$r', NOW())"); } } } else { # Import failed - file still being uploaded? echo " *** Skipping file - it was not possible to move the file (still being imported/uploaded?)" . PHP_EOL; } } else { # check modified date and update previews if necessary $filemod = filemtime($fullpath); if (array_key_exists($shortpath,$modtimes) && ($filemod > strtotime($modtimes[$shortpath]))) { # File has been modified since we last created previews. Create again. $rd = sql_query("SELECT ref, has_image, file_modified, file_extension FROM resource WHERE file_path='" . escape_check($shortpath) . "'"); if (count($rd) > 0) { $rd = $rd[0]; $rref = $rd["ref"]; echo "Resource $rref has changed, regenerating previews: $fullpath" . PHP_EOL; extract_exif_comment($rref,$rd["file_extension"]); # extract text from documents (e.g. PDF, DOC). global $extracted_text_field; if (isset($extracted_text_field)) { if (isset($unoconv_path) && in_array($extension,$unoconv_extensions)){ // omit, since the unoconv process will do it during preview creation below } else { extract_text($rref,$extension); } } # Store original filename in field, if set global $filename_field; if (isset($filename_field)) { update_field($rref,$filename_field,$file); } create_previews($rref, false, $rd["file_extension"], false, false, -1, false, $staticsync_ingest); sql_query("UPDATE resource SET file_modified=NOW() WHERE ref='$rref'"); } } } } } }
error_alert($error); exit; } # Check edit permission. if (!get_edit_access($ref, $resource["archive"], false, $resource)) { # The user is not allowed to edit this resource or the resource doesn't exist. $error = $lang['error-permissiondenied']; error_alert($error); exit; } if (getval("regen", "") != "") { sql_query("update resource set preview_attempts=0 WHERE ref='" . $ref . "'"); create_previews($ref, false, $resource["file_extension"]); } if (getval("regenexif", "") != "") { extract_exif_comment($ref); } # Establish if this is a metadata template resource, so we can switch off certain unnecessary features $is_template = isset($metadata_template_resource_type) && $resource["resource_type"] == $metadata_template_resource_type; hook("editbeforeheader"); # ----------------------------------- # PERFORM SAVE # ----------------------------------- if (getval("autosave", "") != "" || getval("tweak", "") == "" && getval("submitted", "") != "" && getval("resetform", "") == "" && getval("copyfromsubmit", "") == "") { if ($embedded_data_user_select && getval("exif_option", "") == "custom" || isset($embedded_data_user_select_fields)) { $exif_override = false; foreach ($_POST as $postname => $postvar) { if (strpos($postname, "exif_option_") !== false) { $uploadparams .= "&" . urlencode($postname) . "=" . urlencode($postvar); $exif_override = true; }
function ProcessFolder($folder) { #echo "<br>processing folder $folder"; global $syncdir,$nogo,$max,$count,$done,$modtimes,$lastsync, $ffmpeg_preview_extension, $staticsync_autotheme, $staticsync_folder_structure,$staticsync_extension_mapping_default, $staticsync_extension_mapping, $staticsync_mapped_category_tree,$staticsync_title_includes_path, $staticsync_ingest, $staticsync_mapfolders,$staticsync_alternatives_suffix; $collection=0; echo "Processing Folder: $folder\n"; # List all files in this folder. $dh=opendir($folder); while (($file = readdir($dh)) !== false) { $filetype=filetype($folder . "/" . $file); $fullpath=$folder . "/" . $file; $shortpath=str_replace($syncdir . "/","",$fullpath); # Work out extension $extension=explode(".",$file);$extension=trim(strtolower($extension[count($extension)-1])); if ($staticsync_mapped_category_tree) { $path_parts=explode("/",$shortpath); array_pop($path_parts); touch_category_tree_level($path_parts); } # -----FOLDERS------------- if ((($filetype=="dir") || $filetype=="link") && ($file!=".") && ($file!="..") && (strpos($nogo,"[" . $file . "]")===false) && strpos($file,$staticsync_alternatives_suffix)===false) { # Recurse #echo "\n$file : " . filemtime($folder . "/" . $file) . " > " . $lastsync; if (true || (strlen($lastsync)=="") || (filemtime($folder . "/" . $file)>($lastsync-26000))) { ProcessFolder($folder . "/" . $file); } } # -------FILES--------------- if (($filetype=="file") && (substr($file,0,1)!=".") && (strtolower($file)!="thumbs.db")) { # Already exists? if (!in_array($shortpath,$done)) { $count++;if ($count>$max) {return(true);} echo "Processing file: $fullpath\n"; if ($collection==0 && $staticsync_autotheme) { # Make a new collection for this folder. $e=explode("/",$shortpath); $theme=ucwords($e[0]); $themesql="theme='".ucwords(escape_check($e[0]))."'"; $themecolumns="theme"; $themevalues="'".ucwords(escape_check($e[0]))."'"; if ($staticsync_folder_structure){ for ($x=0;$x<count($e)-1;$x++){ if ($x==0){} else {$themeindex=$x+1; global $theme_category_levels; if ($themeindex>$theme_category_levels){ $theme_category_levels=$themeindex; if ($x==count($e)-2){echo "\n\nUPDATE THEME_CATEGORY_LEVELS TO $themeindex IN CONFIG!!!!\n\n";} } $themesql.=" and theme".$themeindex."='".ucwords(escape_check($e[$x]))."'"; $themevalues.=",'".ucwords(escape_check($e[$x]))."'"; $themecolumns.=",theme".$themeindex; } } } $name=(count($e)==1?"":$e[count($e)-2]); echo "\nCollection $name, theme=$theme"; $collection=sql_value("select ref value from collection where name='" . escape_check($name) . "' and " . $themesql ,0); if ($collection==0){ sql_query("insert into collection (name,created,public,$themecolumns,allow_changes) values ('" . escape_check($name) . "',now(),1,".$themevalues.",0)"); $collection=sql_insert_id(); } } # Work out a resource type based on the extension. $type=$staticsync_extension_mapping_default; reset ($staticsync_extension_mapping); foreach ($staticsync_extension_mapping as $rt=>$extensions) { if (in_array($extension,$extensions)) {$type=$rt;} } # Formulate a title if ($staticsync_title_includes_path) { $title=str_ireplace("." . $extension,"",str_replace("/"," - ",$shortpath)); $title=ucfirst(str_replace("_"," ",$title)); } else { $title=str_ireplace("." . $extension,"",$file); } # Import this file $r=import_resource($shortpath,$type,$title,$staticsync_ingest); if ($r!==false) { # Add to mapped category tree (if configured) if (isset($staticsync_mapped_category_tree)) { $basepath=""; # Save tree position to category tree field # For each node level, expand it back to the root so the full path is stored. for ($n=0;$n<count($path_parts);$n++) { if ($basepath!="") {$basepath.="~";} $basepath.=$path_parts[$n]; $path_parts[$n]=$basepath; } update_field ($r,$staticsync_mapped_category_tree,"," . join(",",$path_parts)); #echo "update_field($r,$staticsync_mapped_category_tree," . "," . join(",",$path_parts) . ");\n"; } // default access level. This may be overridden by metadata mapping. $accessval = 0; # StaticSync path / metadata mapping # Extract metadata from the file path as per $staticsync_mapfolders in config.php if (isset($staticsync_mapfolders)) { foreach ($staticsync_mapfolders as $mapfolder) { $match=$mapfolder["match"]; $field=$mapfolder["field"]; $level=$mapfolder["level"]; global $lang; if (strpos("/" . $shortpath,$match)!==false) { # Match. Extract metadata. $path_parts=explode("/",$shortpath); if ($level<count($path_parts)) { // special cases first. if ($field == 'access') { // access level is a special case // first determine if the value matches a defined access level $value = $path_parts[$level-1]; for ($n=0; $n<3; $n++){ // if we get an exact match or a match except for case if ($value == $lang["access" . $n] || strtoupper($value) == strtoupper($lang['access' . $n])){ $accessval = $n; echo "Will set access level to " . $lang['access' . $n] . " ($n)\n"; } } } else { # Save the value print_r($path_parts); $value=$path_parts[$level-1]; update_field ($r,$field,$value); echo " - Extracted metadata from path: $value\n"; } } } } } // update access level sql_query("update resource set access = '$accessval' where ref = '$r'"); # Add any alternative files $altpath=$fullpath . $staticsync_alternatives_suffix; if ($staticsync_ingest && file_exists($altpath)) { $adh=opendir($altpath); while (($altfile = readdir($adh)) !== false) { $filetype=filetype($altpath . "/" . $altfile); if (($filetype=="file") && (substr($file,0,1)!=".") && (strtolower($file)!="thumbs.db")) { # Create alternative file global $lang; # Find extension $ext=explode(".",$altfile);$ext=$ext[count($ext)-1]; $aref = add_alternative_file($r, $altfile, str_replace("?",strtoupper($ext),$lang["originalfileoftype"]), $altfile, $ext, filesize_unlimited($altpath . "/" . $altfile)); $path=get_resource_path($r, true, "", true, $ext, -1, 1, false, "", $aref); rename ($altpath . "/" . $altfile,$path); # Move alternative file } } } # Add to collection if ($staticsync_autotheme) { $test=""; $test=sql_query("select * from collection_resource where collection='$collection' and resource='$r'"); if (count($test)==0){ sql_query("insert into collection_resource(collection,resource,date_added) values ('$collection','$r',now())"); } } } else { # Import failed - file still being uploaded? echo " *** Skipping file - it was not possible to move the file (still being imported/uploaded?) \n"; } } else { # check modified date and update previews if necessary $filemod=filemtime($fullpath); if (array_key_exists($shortpath,$modtimes) && ($filemod>strtotime($modtimes[$shortpath]))) { # File has been modified since we last created previews. Create again. $rd=sql_query("select ref,has_image,file_modified,file_extension from resource where file_path='" . (escape_check($shortpath)) . "'"); if (count($rd)>0) { $rd=$rd[0]; $rref=$rd["ref"]; echo "Resource $rref has changed, regenerating previews: $fullpath\n"; extract_exif_comment($rref,$rd["file_extension"]); # extract text from documents (e.g. PDF, DOC). global $extracted_text_field; if (isset($extracted_text_field)) { if (isset($unoconv_path) && in_array($extension,$unoconv_extensions)){ // omit, since the unoconv process will do it during preview creation below } else { extract_text($rref,$extension); } } # Store original filename in field, if set global $filename_field; if (isset($filename_field)) { update_field($rref,$filename_field,$file); } create_previews($rref,false,$rd["file_extension"]); sql_query("update resource set file_modified=now() where ref='$rref'"); } } } } } }
update_field($r,$filename_field,$file['filename']); update_field($r,$checkmail_subject_field,$subject); if ($body_html!='' && $checkmail_html){ update_field($r,$checkmail_body_field,$body_html); } else { update_field($r,$checkmail_body_field,$body); } echo "Updating Metadata \r\n"; # Move the file $destination=get_resource_path($r,true,"",true,$file['extension']); $result=rename($temp_dir."/".$file['filename'],$destination); echo "Moving file to filestore \r\n"; chmod($destination,0777); # get file metadata extract_exif_comment($r,$file['extension']); echo "Extracting Metadata... \r\n"; # Ensure folder is created, then create previews. get_resource_path($r,false,"pre",true,$file['extension']); if ($build_collection){ # Add Resource to Collection echo "Adding Resource $r to Collection $collection \r\n"; add_resource_to_collection($r,$collection,true); } # Generate previews/thumbnails (if configured i.e if not completed by offline process 'create_previews.php') global $enable_thumbnail_creation_on_upload; if ($enable_thumbnail_creation_on_upload) { create_previews($r,false,$file['extension']); echo "Creating Previews... \r\n";
function upload_file($ref, $no_exif = false, $revert = false, $autorotate = false) { hook("beforeuploadfile", "", array($ref)); hook("clearaltfiles", "", array($ref)); // optional: clear alternative files before uploading new resource # revert is mainly for metadata reversion, removing all metadata and simulating a reupload of the file from scratch. hook("removeannotations", "", array($ref)); $exiftool_fullpath = get_utility_path("exiftool"); # Process file upload for resource $ref if ($revert == true) { global $filename_field; $original_filename = get_data_by_field($ref, $filename_field); # Field 8 is used in a special way for staticsync, don't overwrite. $test_for_staticsync = get_resource_data($ref); if ($test_for_staticsync['file_path'] != "") { $staticsync_mod = " and resource_type_field != 8"; } else { $staticsync_mod = ""; } sql_query("delete from resource_data where resource={$ref} {$staticsync_mod}"); sql_query("delete from resource_keyword where resource={$ref} {$staticsync_mod}"); #clear 'joined' display fields which are based on metadata that is being deleted in a revert (original filename is reinserted later) $display_fields = get_resource_table_joins(); if ($staticsync_mod != "") { $display_fields_new = array(); for ($n = 0; $n < count($display_fields); $n++) { if ($display_fields[$n] != 8) { $display_fields_new[] = $display_fields[$n]; } } $display_fields = $display_fields_new; } $clear_fields = ""; for ($x = 0; $x < count($display_fields); $x++) { $clear_fields .= "field" . $display_fields[$x] . "=''"; if ($x < count($display_fields) - 1) { $clear_fields .= ","; } } sql_query("update resource set " . $clear_fields . " where ref={$ref}"); #also add the ref back into keywords: add_keyword_mappings($ref, $ref, -1); $extension = sql_value("select file_extension value from resource where ref={$ref}", ""); $filename = get_resource_path($ref, true, "", false, $extension); $processfile['tmp_name'] = $filename; } else { # Work out which file has been posted if (isset($_FILES['userfile'])) { $processfile = $_FILES['userfile']; } elseif (isset($_FILES['Filedata'])) { $processfile = $_FILES['Filedata']; } # Java upload (at least) needs this # Plupload needs this if (isset($_REQUEST['name'])) { $filename = $_REQUEST['name']; } else { $filename = $processfile['name']; } global $filename_field; if ($no_exif && isset($filename_field)) { $user_set_filename = get_data_by_field($ref, $filename_field); if (trim($user_set_filename) != '') { // Get extension of file just in case the user didn't provide one $path_parts = pathinfo($filename); $original_extension = $path_parts['extension']; $filename = $user_set_filename; // If the user filename doesn't have an extension add the original one $path_parts = pathinfo($filename); if (!isset($path_parts['extension'])) { $filename .= '.' . $original_extension; } } } } # Work out extension if (!isset($extension)) { # first try to get it from the filename $extension = explode(".", $filename); if (count($extension) > 1) { $extension = escape_check(trim(strtolower($extension[count($extension) - 1]))); } else { if ($exiftool_fullpath != false) { $file_type_by_exiftool = run_command($exiftool_fullpath . " -filetype -s -s -s " . escapeshellarg($processfile['tmp_name'])); if (strlen($file_type_by_exiftool) > 0) { $extension = str_replace(" ", "_", trim(strtolower($file_type_by_exiftool))); $filename = $filename; } else { return false; } } else { return false; } } } # Banned extension? global $banned_extensions; if (in_array($extension, $banned_extensions)) { return false; } $status = "Please provide a file name."; $filepath = get_resource_path($ref, true, "", true, $extension); if (!$revert) { # Remove existing file, if present hook("beforeremoveexistingfile", "", array("resourceId" => $ref)); $old_extension = sql_value("select file_extension value from resource where ref='{$ref}'", ""); if ($old_extension != "") { $old_path = get_resource_path($ref, true, "", true, $old_extension); if (file_exists($old_path)) { unlink($old_path); } } // also remove any existing extracted icc profiles $icc_path = get_resource_path($ref, true, "", true, $extension . '.icc'); if (file_exists($icc_path)) { unlink($icc_path); } global $pdf_pages; $iccx = 0; // if there is a -0.icc page, run through and delete as many as necessary. $finished = false; $badicc_path = str_replace(".icc", "-{$iccx}.icc", $icc_path); while (!$finished) { if (file_exists($badicc_path)) { unlink($badicc_path); $iccx++; $badicc_path = str_replace(".icc", "-{$iccx}.icc", $icc_path); } else { $finished = true; } } $iccx = 0; } if (!$revert) { if ($filename != "") { global $jupload_alternative_upload_location, $plupload_upload_location; if (isset($plupload_upload_location)) { # PLUpload - file was sent chunked and reassembled - use the reassembled file location $result = rename($plupload_upload_location, $filepath); } elseif (isset($jupload_alternative_upload_location)) { # JUpload - file was sent chunked and reassembled - use the reassembled file location $result = rename($jupload_alternative_upload_location, $filepath); } else { # Standard upload. if (!$revert) { $result = move_uploaded_file($processfile['tmp_name'], $filepath); } else { $result = true; } } if ($result == false) { $status = "File upload error. Please check the size of the file you are trying to upload."; return false; } else { global $camera_autorotation; global $ffmpeg_audio_extensions; if ($camera_autorotation) { if ($autorotate && !in_array($extension, $ffmpeg_audio_extensions)) { AutoRotateImage($filepath); } } chmod($filepath, 0777); global $icc_extraction; global $ffmpeg_supported_extensions; if ($icc_extraction && $extension != "pdf" && !in_array($extension, $ffmpeg_supported_extensions)) { extract_icc_profile($ref, $extension); } $status = "Your file has been uploaded."; } } } # Store extension in the database and update file modified time. if ($revert) { $has_image = ""; } else { $has_image = ",has_image=0"; } sql_query("update resource set file_extension='{$extension}',preview_extension='jpg',file_modified=now() {$has_image} where ref='{$ref}'"); # delete existing resource_dimensions sql_query("delete from resource_dimensions where resource='{$ref}'"); # get file metadata if (!$no_exif) { extract_exif_comment($ref, $extension); } else { global $merge_filename_with_title, $lang; if ($merge_filename_with_title) { $merge_filename_with_title_option = urlencode(getval('merge_filename_with_title_option', '')); $merge_filename_with_title_include_extensions = urlencode(getval('merge_filename_with_title_include_extensions', '')); $merge_filename_with_title_spacer = urlencode(getval('merge_filename_with_title_spacer', '')); $original_filename = ''; if (isset($_REQUEST['name'])) { $original_filename = $_REQUEST['name']; } else { $original_filename = $processfile['name']; } if ($merge_filename_with_title_include_extensions == 'yes') { $merged_filename = $original_filename; } else { $merged_filename = strip_extension($original_filename); } // Get title field: $resource = get_resource_data($ref); $read_from = get_exiftool_fields($resource['resource_type']); for ($i = 0; $i < count($read_from); $i++) { if ($read_from[$i]['name'] == 'title') { $oldval = get_data_by_field($ref, $read_from[$i]['ref']); if (strpos($oldval, $merged_filename) !== FALSE) { continue; } switch ($merge_filename_with_title_option) { case $lang['merge_filename_title_do_not_use']: // Do nothing since the user doesn't want to use this feature break; case $lang['merge_filename_title_replace']: $newval = $merged_filename; break; case $lang['merge_filename_title_prefix']: $newval = $merged_filename . $merge_filename_with_title_spacer . $oldval; if ($oldval == '') { $newval = $merged_filename; } break; case $lang['merge_filename_title_suffix']: $newval = $oldval . $merge_filename_with_title_spacer . $merged_filename; if ($oldval == '') { $newval = $merged_filename; } break; default: // Do nothing break; } update_field($ref, $read_from[$i]['ref'], $newval); } } } } # extract text from documents (e.g. PDF, DOC). global $extracted_text_field; if (isset($extracted_text_field) && !$no_exif) { if (isset($unoconv_path) && in_array($extension, $unoconv_extensions)) { // omit, since the unoconv process will do it during preview creation below } else { extract_text($ref, $extension); } } # Store original filename in field, if set global $filename_field, $amended_filename; if (isset($filename_field)) { if (isset($amended_filename)) { $filename = $amended_filename; } } if (!$revert) { update_field($ref, $filename_field, $filename); } else { update_field($ref, $filename_field, $original_filename); } if (!$revert) { # Clear any existing FLV file or multi-page previews. global $pdf_pages; for ($n = 2; $n <= $pdf_pages; $n++) { # Remove preview page. $path = get_resource_path($ref, true, "scr", false, "jpg", -1, $n, false); if (file_exists($path)) { unlink($path); } # Also try the watermarked version. $path = get_resource_path($ref, true, "scr", false, "jpg", -1, $n, true); if (file_exists($path)) { unlink($path); } } # Remove any FLV video preview (except if the actual resource is an FLV file). global $ffmpeg_preview_extension; if ($extension != $ffmpeg_preview_extension) { $path = get_resource_path($ref, true, "", false, $ffmpeg_preview_extension); if (file_exists($path)) { unlink($path); } } # Remove any FLV preview-only file $path = get_resource_path($ref, true, "pre", false, $ffmpeg_preview_extension); if (file_exists($path)) { unlink($path); } # Remove any MP3 (except if the actual resource is an MP3 file). if ($extension != "mp3") { $path = get_resource_path($ref, true, "", false, "mp3"); if (file_exists($path)) { unlink($path); } } # Create previews global $enable_thumbnail_creation_on_upload; if ($enable_thumbnail_creation_on_upload) { create_previews($ref, false, $extension); } else { # Offline thumbnail generation is being used. Set 'has_image' to zero so the offline create_previews.php script picks this up. sql_query("update resource set has_image=0 where ref='{$ref}'"); } } # Update file dimensions get_original_imagesize($ref, $filepath, $extension); hook("Uploadfilesuccess", "", array("resourceId" => $ref)); # Update disk usage update_disk_usage($ref); # Log this activity. $log_ref = resource_log($ref, "u", 0); hook("upload_image_after_log_write", "", array($ref, $log_ref)); return $status; }
} // Test if thumbnail creation is allowed during upload # Store original filename in field, if set if (isset($filename_field)) { $filename = $uploadfiles[$n]; if ($use_local) { $filename = mb_basename($filename); } update_field($ref,$filename_field, $filename); } # get file metadata if (getval("no_exif","")=="") {extract_exif_comment($ref,$extension);} # extract text from documents (e.g. PDF, DOC). global $extracted_text_field; if (isset($extracted_text_field) && !$no_exif) {extract_text($ref,$extension);} $done++; # Add to collection? if ($collection!="") { $refs[] = $ref; } # Log this daily_stat("Resource upload",$ref);
// Update metadata fields // HTML OPTIONS update_field($r, $filename_field, $file['filename']); update_field($r, $checkmail_subject_field, $subject); if ($body_html != '' && $checkmail_html) { update_field($r, $checkmail_body_field, $body_html); } else { update_field($r, $checkmail_body_field, $body); } echo "Updating Metadata \r\n"; # Move the file $destination = get_resource_path($r, true, "", true, $file['extension']); $result = rename($temp_dir . "/" . $file['filename'], $destination); echo "Moving file to filestore \r\n"; chmod($destination, 0777); # get file metadata extract_exif_comment($r, $file['extension']); echo "Extracting Metadata... \r\n"; # Ensure folder is created, then create previews. get_resource_path($r, false, "pre", true, $file['extension']); if ($build_collection) { # Add Resource to Collection echo "Adding Resource {$r} to Collection {$collection} \r\n"; add_resource_to_collection($r, $collection, true); } # Generate previews/thumbnails (if configured i.e if not completed by offline process 'create_previews.php') global $enable_thumbnail_creation_on_upload; if ($enable_thumbnail_creation_on_upload) { create_previews($r, false, $file['extension']); echo "Creating Previews... \r\n"; } if (!$build_collection && $checkmail_confirm) {