use_exiftool = $use_exiftool_p; $this->use_exiv2 = $use_exiv2_p; $this->use_whole_desc = $use_whole_desc_p; $this->isMSWin = stristr(php_uname(), 'windows'); $this->eol = $this->isMSWin ? "\r\n" : "\n"; $this->useUTF8_txt = $useUTF8_txt; // encoding of the batch file $this->useUTF8_cp = false; // pb under windows xp for the author with this code page... } public function set_test_mode($test_mode, $test_img_id) { $this->isTest = $test_mode; $this->test_img_id = $test_img_id; } public function set_tool_pathes($exiftoolPath, $exiv2path) { if ($this->use_exiftool) { $this->exiftoolDefaultCmd = $this->init_exif_tool_cmd_name($exiftoolPath, "exiftool"); if ($this->useUTF8_txt) { $this->exiftoolDefaultCmd .= " -IPTC:CodedCharacterSet=UTF8"; } else { $this->exiftoolDefaultCmd .= " -L"; // convert to Latin1 internaly, see FAQ #10 at http://www.sno.phy.queensu.ca/~phil/exiftool/faq.html } $this->exiftoolDefaultCmd .= " -overwrite_original"; // no backup! } if ($this->use_exiv2) { $this->exiv2DefaultCmd = $this->init_exif_tool_cmd_name($exiv2path, "exiv2"); $this->exiv2DefaultCmd .= " -k"; // conserve original date } } private function init_exif_tool_cmd_name($toolPath, $toolName) { return (file_exists($toolPath) && strpos(strtolower($toolPath), strtolower($toolName)) !== false) ? "\"".realpath($toolPath)."\"" : $toolName; } public function image_properties_to_file($destPath) { $exiftoolScript = ""; $exiv2Script = ""; if ($this->use_exiftool) { $exiftoolScript = $destPath ."/writeTagsToIptcWithExifTool.cmd"; $fp_exiftool = $this->open_create_file($exiftoolScript); } if ($this->use_exiv2) { $exiv2Script = $destPath ."/writeTagsToIptcWithExiv2.cmd"; $fp_exiv2 = $this->open_create_file($exiv2Script); } $datas = $this->get_image_properties(); $this->nbfiles = 0; while ($row = mysql_fetch_row($datas)) // row to avoid conflict with name { $image_path = $row[5]; $has_high = $row[6] === 'true'; if ($this->isTest || file_exists($image_path)) { if ($this->use_exiftool) { $cmd = $this->convert_row_to_file_exiftool($row); $this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiftool); } if ($this->use_exiv2) { $cmd = $this->convert_row_to_file_exiv2($row); $this->write_exifCmd($cmd, $image_path, $has_high, $fp_exiv2); } } } if ($this->use_exiftool && isset($fp_exiftool)) { $this->close_file($fp_exiftool); } if ($this->use_exiv2 && isset($fp_exiv2)) { $this->close_file($fp_exiv2); } if ($this->use_exiftool && $this->use_exiv2) { $this->nbfiles = $this->nbfiles / 2; // each picture counted twice } return $this->nbfiles; // incremented by write_exifCmd } // IO function private function open_create_file($destPath) { // prepare output file if(file_exists($destPath)) { if (!$this->isMSWin) chmod($destPath, 0777); unlink($destPath); } touch($destPath); $fp = fopen($destPath,"w"); if ($this->isMSWin && isset($fp) ) { // the default command prompt is stupid and won't display the correct character set, so we need to change the code page if ($this->useUTF8_cp) { fwrite($fp, "chcp 65001".$this->eol); } // UTF-8, prevent cmd to work, see perhaps http://blogs.msdn.com/michkap/archive/2006/03/06/544251.aspx else { fwrite($fp, "chcp 1252".$this->eol); } // default Windows Latin1 } return $fp; } private function close_file($fp) { if (isset($fp)) { if ($this->nbfiles > 0) { fwrite($fp, $this->eol); } fclose($fp); } } // prepare data for script private function convert_row_to_file_exiv2($row) { if (!$this->use_exiv2) return "exiv2 shall not be used"; $name = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], true)), 256); $description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], true)), 2000); $author = $this->cutString($this->decode_html_string_to_unicode($row[2], true), 32); //$date_creation = $this->decode_html_string_to_unicode($row[3], true); $tags = $this->cutString($this->decode_html_string_to_unicode($row[4], true), 64); $image_path = $row[5]; $has_high = $row[6] === 'true'; $exiv2Cmd = $this->exiv2DefaultCmd; if (strlen($name) > 0) { $exiv2Cmd .= " -M\"set Iptc.Application2.Headline ".$name."\""; $exiv2Cmd .= " -M\"set Iptc.Application2.ObjectName ". $this->cutString($name, 64)."\""; } if (strlen($description) > 0) { $exiv2Cmd .= " -M\"set Iptc.Application2.Caption ".$description."\""; } if (strlen($author) > 0) { $exiv2Cmd .= " -M\"set Iptc.Application2.Writer ".$author."\""; } if (strlen($tags) > 0) { $exiv2Cmd .= " -M\"add Iptc.Application2.Keywords ".$tags."\""; } return $exiv2Cmd; } private function convert_row_to_file_exiftool($row) { if (!$this->use_exiftool) return "exiftool shall not be used"; $name = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[0], false)), 256); $description = $this->cutString($this->explode_description($this->decode_html_string_to_unicode($row[1], false)), 2000); $author = $this->cutString($this->decode_html_string_to_unicode($row[2], false), 32); //$date_creation = $this->decode_html_string_to_unicode($row[3], false); $tags = $this->cutString($this->decode_html_string_to_unicode($row[4], false), 64); $exiftoolCmd = $this->exiftoolDefaultCmd; // exiftool allow to set a field only if the field in the original file is empty // as explained here: http://www.cpanforum.com/posts/10765 if (strlen($name) > 0) { $exiftoolCmd .= " -IPTC:Headline-= -IPTC:Headline=\"".$name."\""; $exiftoolCmd .= " -IPTC:ObjectName-= -IPTC:ObjectName=\"".$this->cutString($name, 64)."\""; } if (strlen($description) > 0) { $exiftoolCmd .= " -IPTC:Caption-Abstract-= -IPTC:Caption-Abstract=\"".$description."\""; } if (strlen($author) > 0) { $exiftoolCmd .= " -IPTC:Writer-Editor-= -IPTC:Writer-Editor=\"".$author."\""; } if (strlen($tags) > 0) { // Keywords are overwritten, since they allow multiple entries, with "-=", given keywords will be added to the existing $exiftoolCmd .= " -IPTC:Keywords=\"".$tags."\""; } return $exiftoolCmd; } private function write_exifCmd($exifCmd, $image_path, $has_high, $fp) { $exifCmdN = $exifCmd ." "; $exifCmdN .= $this->isTest ? $image_path : realpath(PHPWG_ROOT_PATH.$image_path); $writeOK = fwrite($fp, $exifCmdN.$this->eol) !== FALSE; if ($writeOK) $this->nbfiles++; if ($has_high) { $imageHigh = dirname($image_path) . "/pwg_high/" . basename($image_path); if (file_exists($imageHigh)) { $this->write_exifCmd($exifCmd, $imageHigh, false, $fp); } } } // html function private function decode_html_string_to_unicode($string, $forceANSI) { if (isset($string) && strlen($string) > 0) { $txt_encoding = ($this->useUTF8_txt && !$forceANSI) ? 'UTF-8' : 'ISO-8859-15'; $string = html_entity_decode(trim($string), ENT_QUOTES, $txt_encoding); $string = stripslashes($string); } else $string = ""; return($string); } // remove end of line char from desc and keep if required only the current language private function explode_description($description) { if (!$this->use_whole_desc) { $description = $this->get_user_language_desc($description); } return str_replace( array( '
', '
', "\n", "\r" ), array('', '', '', ''), $description ); } private function cutString($description, $maxLen) { if (strlen($description) > $maxLen) { $description = substr($description, 0, $maxLen); } return $description; } // Traite les balises [lang=xx], copy&paste from ExtendedDescription plugin, main.inc.php private function get_user_language_desc($desc) { global $user; $user_lang = substr($user['language'], 0, 2); if (!substr_count(strtolower($desc), '[lang=' . $user_lang . ']')) { $user_lang = 'default'; } if (substr_count(strtolower($desc), '[lang=' . $user_lang . ']')) { // la balise avec la langue de l'utilisateur a été trouvée $patterns[] = '#(^|\[/lang\])(.*?)(\[lang=(' . $user_lang . '|all)\]|$)#is'; $replacements[] = ''; $patterns[] = '#\[lang=(' . $user_lang . '|all)\](.*?)\[/lang\]#is'; $replacements[] = '\\1'; } else { // la balise avec la langue de l'utilisateur n'a pas été trouvée // On prend tout ce qui est hors balise $patterns[] = '#\[lang=all\](.*?)\[/lang\]#is'; $replacements[] = '\\1'; $patterns[] = '#\[lang=.*\].*\[/lang\]#is'; $replacements[] = ''; } return preg_replace($patterns, $replacements, $desc); } // data access private function get_image_properties() { $query_path = $this->isTest ? 'img.file' : 'img.path'; $query_restriction = $this->isTest ? 'AND (img.id = '.$this->test_img_id.'))' : ')'; // get direct properties and tags, even if no tags, with either name, comment or tags not null // restritive query with image.ID for tests with copied images with file instead of path $img_query = 'SELECT img.name, img.comment, img.author, img.date_creation, GROUP_CONCAT(tags.name), '.$query_path.', has_high FROM '.IMAGES_TABLE.' AS img LEFT OUTER JOIN '.IMAGE_TAG_TABLE.' AS img_tag ON img_tag.image_id = img.id LEFT OUTER JOIN '.TAGS_TABLE.' AS tags ON tags.id = img_tag.tag_id WHERE ( ( LENGTH(img.name) > 0 OR LENGTH(img.comment) > 0 OR LENGTH(img.author) > 0 OR LENGTH(tags.name) > 0 ) '.$query_restriction.' GROUP BY img.id, img.name, img.comment, img.author, '.$query_path.', has_high ORDER BY img.id ASC; '; return pwg_query($img_query); } }