You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lenya.apache.org by so...@apache.org on 2007/09/21 12:37:48 UTC

svn commit: r578051 [16/31] - in /lenya/branches/revolution/1.3.x/src: java/org/apache/lenya/cms/content/flat/ webapp/lenya/modules/xinha/ webapp/lenya/modules/xinha/contrib/ webapp/lenya/modules/xinha/examples/ webapp/lenya/modules/xinha/images/ webap...

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HorizontalRule/popups/edit_horizontal_rule.html
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HorizontalRule/popups/edit_horizontal_rule.html?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HorizontalRule/popups/edit_horizontal_rule.html (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HorizontalRule/popups/edit_horizontal_rule.html Fri Sep 21 03:36:30 2007
@@ -0,0 +1,141 @@
+<!DOCTYPE html
+     PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>Insert/Edit Horizontal Rule</title>
+  <link rel="stylesheet" type="text/css" href="../../../popups/popup.css" />
+  <script type="text/javascript" src="../../../popups/popup.js"></script>
+  <script type="text/javascript" src="../../../modules/ColorPicker/ColorPicker.js"></script>
+<script type="text/javascript">
+editor = window.opener.editor;
+
+function Init() {
+	__dlg_translate("HorizontalRule");
+	__dlg_init(null,{width:320,height:290});
+	var params = window.dialogArguments;
+	if(params) {
+		document.getElementById("f_size").value = params.f_size;
+		document.getElementById("f_width").value = params.f_width;
+		document.getElementById("f_widthUnit").value = params.f_widthUnit;
+		document.getElementById("f_align").value = params.f_align;
+		document.getElementById("f_color").value = params.f_color;
+		document.getElementById("hrpv").style.backgroundColor = params.f_color;
+		document.getElementById("f_noshade").checked = params.f_noshade;
+	}
+	
+	var colpick = document.getElementById('hrpv');
+	var f_color = document.getElementById('f_color');
+	var colPicker = new Xinha.colorPicker({cellsize:'5px',callback:selectColor});
+	colpick.onclick = function() { colPicker.open('top,left',colpick, f_color.value ); }
+	
+	document.getElementById("f_width").focus();
+}
+
+function onOK() {
+  var fields = ["f_size", "f_width", "f_widthUnit", "f_align", "f_color", "f_noshade"];
+  var param = {};
+  for (var i in fields) {
+    var id = fields[i];
+	var el = document.getElementById(id);
+    param[id] = (el.type == "checkbox") ? el.checked : el.value;
+  }
+  __dlg_close(param);
+  return false;
+}
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+}
+
+function selectColor(color) {
+	document.getElementById('hrpv').style.backgroundColor = color;
+	document.getElementById('f_color').value = color;
+}
+window.onload = Init;
+</script>
+
+<style type="text/css">
+.buttonColor {
+  padding: 1px;
+  cursor: default;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.buttonColor-hilite {
+  border-color: #000;
+}
+
+.buttonColor .chooser {
+  height: 0.6em;
+  border: 1px solid;
+  padding: 0px 1em;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+
+.buttonColor .nocolor {
+  padding: 0px;
+  height: 0.6em;
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+.buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }
+</style>
+
+</head>
+
+<body class="dialog">
+<div class="title">Horizontal Rule</div>
+<form action="" method="get">
+  <fieldset>
+  <legend>Layout</legend>
+    <div class="fr">Width:</div>
+    <input style="margin-right: 0.5em;" name="f_width" id="f_width" size="5" type="text" />
+    <select style="margin-right: 0.5em;" name="f_widthUnit" id="f_widthUnit">
+      <option value="%">percent</option>
+      <option value="px">pixels</option>
+    </select>
+	<br />
+    <div class="fr">Height:</div>
+    <input style="margin-right: 0.5em;" name="f_size" id="f_size" size="5" type="text" /> <span>pixels</span>
+	<br />
+    <div class="fr">Alignment:</div>
+    <select name="f_align" id="f_align">
+      <option value="left">Left</option>
+      <option value="center">Center</option>
+      <option value="right">Right</option>
+    </select>
+
+  </fieldset>
+  <fieldset>
+  <legend>Style</legend>
+    <div class="fr">Color:</div>
+    <table cellpadding="2" cellspacing="0" id="hrbtn" class="buttonColor">
+    <tr>
+      <td class="chooser" id="hrpv"
+          onmouseover="document.getElementById('hrbtn').style.borderColor='black'"
+          onmouseout="document.getElementById('hrbtn').style.borderColor='ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight'"
+          >&nbsp;</td>
+      <td class="nocolor" id="hrclr"
+          onmouseover="document.getElementById('hrclr').style.color='#f00'"
+          onmouseout="document.getElementById('hrclr').style.color='#000'"
+          onclick="document.getElementById('f_color').value='';	document.getElementById('hrpv').style.backgroundColor=''">&#x00d7;</td>
+    </tr>
+    </table>
+    <br />
+    <div class="fr"> </div>
+    <input type="hidden" name="f_color" id="f_color" />
+    <input type="checkbox" name="f_noshade" id="f_noshade" value="noshade" />
+    <span>No shading</span>
+    <br />
+  </fieldset>
+<div id="buttons">
+  <button type="submit" name="ok" onclick="return onOK();">OK</button>
+  <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+</form>
+</body>
+</html>
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/Entities.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/Entities.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/Entities.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/Entities.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,204 @@
+{
+"&iexcl;" : "¡",
+"&cent;" : "¢",
+"&pound;" : "£",
+"&curren;" : "¤",
+"&yen;" : "Â¥",
+"&brvbar;" : "¦",
+"&sect;" : "§",
+"&uml;" : "¨",
+"&copy;" : "©",
+"&ordf;" : "ª",
+"&laquo;" : "«",
+"&not;" : "¬",
+"&reg;" : "®",
+"&macr;" : "¯",
+"&deg;" : "°",
+"&plusmn;" : "±",
+"&sup2;" : "²",
+"&sup3;" : "³",
+"&acute;" : "´",
+"&micro;" : "µ",
+"&para;" : "¶",
+"&middot;" : "·",
+"&cedil;" : "¸",
+"&sup1;" : "¹",
+"&ordm;" : "º",
+"&raquo;" : "»",
+"&frac14;" : "¼",
+"&frac12;" : "½",
+"&frac34;" : "¾",
+"&iquest;" : "¿",
+"&Agrave;" : "À",
+"&Aacute;" : "Á",
+"&Acirc;" : "Â",
+"&Atilde;" : "Ã",
+"&Auml;" : "Ä",
+"&Aring;" : "Å",
+"&AElig;" : "Æ",
+"&Ccedil;" : "Ç",
+"&Egrave;" : "È",
+"&Eacute;" : "É",
+"&Ecirc;" : "Ê",
+"&Euml;" : "Ë",
+"&Igrave;" : "Ì",
+"&Iacute;" : "Í",
+"&Icirc;" : "Î",
+"&Iuml;" : "Ï",
+"&ETH;" : "Ð",
+"&Ntilde;" : "Ñ",
+"&Ograve;" : "Ò",
+"&Oacute;" : "Ó",
+"&Ocirc;" : "Ô",
+"&Otilde;" : "Õ",
+"&Ouml;" : "Ö",
+"&times;" : "×",
+"&Oslash;" : "Ø",
+"&Ugrave;" : "Ù",
+"&Uacute;" : "Ú",
+"&Ucirc;" : "Û",
+"&Uuml;" : "Ü",
+"&Yacute;" : "Ý",
+"&THORN;" : "Þ",
+"&szlig;" : "ß",
+"&agrave;" : "à",
+"&aacute;" : "á",
+"&acirc;" : "â",
+"&atilde;" : "ã",
+"&auml;" : "ä",
+"&aring;" : "Ã¥",
+"&aelig;" : "æ",
+"&ccedil;" : "ç",
+"&egrave;" : "è",
+"&eacute;" : "é",
+"&ecirc;" : "ê",
+"&euml;" : "ë",
+"&igrave;" : "ì",
+"&iacute;" : "í",
+"&icirc;" : "î",
+"&iuml;" : "ï",
+"&eth;" : "ð",
+"&ntilde;" : "ñ",
+"&ograve;" : "ò",
+"&oacute;" : "ó",
+"&oacute;" : "ó",
+"&ocirc;" : "ô",
+"&otilde;" : "õ",
+"&ouml;" : "ö",
+"&divide;" : "÷",
+"&oslash;" : "ø",
+"&ugrave;" : "ù",
+"&uacute;" : "ú",
+"&ucirc;" : "û",
+"&uuml;" : "ü",
+"&yacute;" : "ý",
+"&thorn;" : "þ",
+"&yuml;" : "ÿ",
+"&fnof;" : "ƒ",
+"&Alpha;" : "Α",
+"&Beta;" : "Β",
+"&Gamma;" : "Γ",
+"&Delta;" : "Δ",
+"&Epsilon;" : "Ε",
+"&Zeta;" : "Ζ",
+"&Eta;" : "Η",
+"&Theta;" : "Θ",
+"&Iota;" : "Ι",
+"&Kappa;" : "Κ",
+"&Lambda;" : "Λ",
+"&Mu;" : "Μ",
+"&Nu;" : "Ν",
+"&Xi;" : "Ξ",
+"&Omicron;" : "Ο ",
+"&Pi;" : "Π",
+"&Rho;" : "Ρ",
+"&Sigma;" : "Σ",
+"&Tau;" : "Τ",
+"&Upsilon;" : "Î¥",
+"&Phi;" : "Φ",
+"&Chi;" : "Χ",
+"&Psi;" : "Ψ",
+"&Omega;" : "Ω",
+"&alpha;" : "α",
+"&beta;" : "β",
+"&gamma;" : "γ",
+"&delta;" : "δ",
+"&epsilon;" : "ε",
+"&zeta;" : "ζ",
+"&eta;" : "η",
+"&theta;" : "θ",
+"&iota;" : "ι",
+"&kappa;" : "κ",
+"&lambda;" : "λ",
+"&mu;" : "μ",
+"&nu;" : "ν",
+"&xi;" : "ξ",
+"&omicron;" : "ο",
+"&pi;" : "π",
+"&rho;" : "ρ",
+"&sigmaf;" : "ς",
+"&sigma;" : "σ",
+"&tau;" : "τ",
+"&upsilon;" : "υ",
+"&phi;" : "φ",
+"&omega;" : "ω",
+"&bull;" : "•",
+"&hellip;" : "…",
+"&prime;" : "′",
+"&Prime;" : "″",
+"&oline;" : "‾",
+"&frasl;" : "⁄",
+"&trade;" : "™",
+"&larr;" : "←",
+"&uarr;" : "↑",
+"&rarr;" : "→",
+"&darr;" : "↓",
+"&harr;" : "↔",
+"&rArr;" : "⇒",
+"&part;" : "∂",
+"&prod;" : "∏",
+"&sum;" : "∑",
+"&minus;" : "−",
+"&radic;" : "√",
+"&infin;" : "∞",
+"&cap;" : "∩",
+"&int;" : "∫",
+"&asymp;" : "≈",
+"&ne;" : "≠",
+"&equiv;" : "≡",
+"&le;" : "≤",
+"&ge;" : "≥",
+"&loz;" : "◊",
+"&spades;" : "♠",
+"&clubs;" : "♣",
+"&hearts;" : "♥",
+"&diams;" : "♦",
+"&OElig;" : "Œ",
+"&oelig;" : "œ",
+"&Scaron;" : "Å ",
+"&scaron;" : "Å¡",
+"&Yuml;" : "Ÿ",
+"&circ;" : "ˆ",
+"&tilde;" : "˜",
+"&ndash;" : "–",
+"&mdash;" : "—",
+"&lsquo;" : "‘",
+"&rsquo;" : "’",
+"&sbquo;" : "‚",
+"&ldquo;" : "“",
+"&rdquo;" : "”",
+"&bdquo;" : "„",
+"&dagger;" : "†",
+"&Dagger;" : "‡",
+"&permil;" : "‰",
+"&lsaquo;" : "‹",
+"&rsaquo;" : "›",
+"&euro;" : "€",
+
+	// \x22 means '"' -- we use hex reprezentation so that we don't disturb
+	// JS compressors (well, at least mine fails.. ;)
+	
+	"&nbsp;" : "\xA0",
+	"&#8804;" : String.fromCharCode(0x2264), 
+	"&#8805;" : String.fromCharCode(0x2265)
+}

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/html-entities.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/html-entities.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/html-entities.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/html-entities.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,51 @@
+/*------------------------------------------*\
+HtmlEntities for Xinha
+____________________
+
+Intended to faciliate the use of special characters with ISO 8 bit encodings.
+
+Using the conversion map provided by mharrisonline in ticket #127
+
+If you want to adjust the list, e.g. to except the characters that are available in the used charset,
+edit Entities.js. 
+You may save it under a different name using the xinha_config.HtmlEntities.EntitiesFile variable
+
+ISO-8859-1 preset is default, set
+  
+  xinha_config.HtmlEntities.Encoding = null;
+
+if you want all special characters to be converted or want to load a custom file 
+\*------------------------------------------*/
+
+function HtmlEntities(editor) {
+	this.editor = editor;
+}
+
+HtmlEntities._pluginInfo = {
+  name          : "HtmlEntities",
+  version       : "1.0",
+  developer     : "Raimund Meyer",
+  developer_url : "http://rheinauf.de",
+  c_owner       : "Xinha community",
+  sponsor       : "",
+  sponsor_url   : "",
+  license       : "Creative Commons Attribution-ShareAlike License"
+}
+Xinha.Config.prototype.HtmlEntities =
+{
+	Encoding     : 'iso-8859-1',
+	EntitiesFile : _editor_url + "plugins/HtmlEntities/Entities.js"
+}
+HtmlEntities.prototype.onGenerate = function() {
+    var e = this.editor;
+    var url = (e.config.HtmlEntities.Encoding) ?  _editor_url + "plugins/HtmlEntities/"+e.config.HtmlEntities.Encoding+".js" : e.config.HtmlEntities.EntitiesFile;
+    var callback = function (getback) {
+    	var specialReplacements = e.config.specialReplacements;
+    	eval("var replacements =" + getback);
+    	for (var i in  replacements)
+		{
+			specialReplacements[i] =  replacements[i];	
+		}
+    }
+    Xinha._getback(url,callback);
+}

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/iso-8859-1.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/iso-8859-1.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/iso-8859-1.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlEntities/iso-8859-1.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,109 @@
+{
+"&fnof;" : "ƒ",
+"&Alpha;" : "Α",
+"&Beta;" : "Β",
+"&Gamma;" : "Γ",
+"&Delta;" : "Δ",
+"&Epsilon;" : "Ε",
+"&Zeta;" : "Ζ",
+"&Eta;" : "Η",
+"&Theta;" : "Θ",
+"&Iota;" : "Ι",
+"&Kappa;" : "Κ",
+"&Lambda;" : "Λ",
+"&Mu;" : "Μ",
+"&Nu;" : "Ν",
+"&Xi;" : "Ξ",
+"&Omicron;" : "Ο ",
+"&Pi;" : "Π",
+"&Rho;" : "Ρ",
+"&Sigma;" : "Σ",
+"&Tau;" : "Τ",
+"&Upsilon;" : "Î¥",
+"&Phi;" : "Φ",
+"&Chi;" : "Χ",
+"&Psi;" : "Ψ",
+"&Omega;" : "Ω",
+"&alpha;" : "α",
+"&beta;" : "β",
+"&gamma;" : "γ",
+"&delta;" : "δ",
+"&epsilon;" : "ε",
+"&zeta;" : "ζ",
+"&eta;" : "η",
+"&theta;" : "θ",
+"&iota;" : "ι",
+"&kappa;" : "κ",
+"&lambda;" : "λ",
+"&mu;" : "μ",
+"&nu;" : "ν",
+"&xi;" : "ξ",
+"&omicron;" : "ο",
+"&pi;" : "π",
+"&rho;" : "ρ",
+"&sigmaf;" : "ς",
+"&sigma;" : "σ",
+"&tau;" : "τ",
+"&upsilon;" : "υ",
+"&phi;" : "φ",
+"&omega;" : "ω",
+"&bull;" : "•",
+"&hellip;" : "…",
+"&prime;" : "′",
+"&Prime;" : "″",
+"&oline;" : "‾",
+"&frasl;" : "⁄",
+"&trade;" : "™",
+"&larr;" : "←",
+"&uarr;" : "↑",
+"&rarr;" : "→",
+"&darr;" : "↓",
+"&harr;" : "↔",
+"&rArr;" : "⇒",
+"&part;" : "∂",
+"&prod;" : "∏",
+"&sum;" : "∑",
+"&minus;" : "−",
+"&radic;" : "√",
+"&infin;" : "∞",
+"&cap;" : "∩",
+"&int;" : "∫",
+"&asymp;" : "≈",
+"&ne;" : "≠",
+"&equiv;" : "≡",
+"&le;" : "≤",
+"&ge;" : "≥",
+"&loz;" : "◊",
+"&spades;" : "♠",
+"&clubs;" : "♣",
+"&hearts;" : "♥",
+"&diams;" : "♦",
+"&OElig;" : "Œ",
+"&oelig;" : "œ",
+"&Scaron;" : "Å ",
+"&scaron;" : "Å¡",
+"&Yuml;" : "Ÿ",
+"&circ;" : "ˆ",
+"&tilde;" : "˜",
+"&ndash;" : "–",
+"&mdash;" : "—",
+"&lsquo;" : "‘",
+"&rsquo;" : "’",
+"&sbquo;" : "‚",
+"&ldquo;" : "“",
+"&rdquo;" : "”",
+"&bdquo;" : "„",
+"&dagger;" : "†",
+"&Dagger;" : "‡",
+"&permil;" : "‰",
+"&lsaquo;" : "‹",
+"&rsaquo;" : "›",
+"&euro;" : "€",
+
+	// \x22 means '"' -- we use hex reprezentation so that we don't disturb
+	// JS compressors (well, at least mine fails.. ;)
+	
+	"&nbsp;" : "\xA0",
+	"&#8804;" : String.fromCharCode(0x2264), 
+	"&#8805;" : String.fromCharCode(0x2265)
+}

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/README
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/README?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/README (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/README Fri Sep 21 03:36:30 2007
@@ -0,0 +1,104 @@
+// Plugin for htmlArea to run code through the server's HTML Tidy
+// By Adam Wright, for The University of Western Australia
+//
+//   Email:      zeno@ucc.gu.uwa.edu.au
+//   Homepage:   http://blog.hipikat.org/
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// Version: 0.5
+// Released to the outside world: 04/03/04
+
+
+HtmlTidy is a plugin for the popular cross-browser TTY WYSIWYG editor,
+htmlArea (http://www.interactivetools.com/products/htmlarea/). HtmlTidy
+basically queries HTML Tidy (http://tidy.sourceforge.net/) on the
+server side, getting it to make-html-nice, instead of relying on masses
+of javascript, which the client would have to download.
+
+Hi, this is a quick explanation of how to install HtmlTidy. Much better
+documentation is probably required, and you're welcome to write it :)
+
+
+* The HtmlTidy directory you should have found this file in should
+  include the following:
+
+  - README
+        This file, providing help installing the plugin.
+
+  - html-tidy-config.cfg
+        This file contains the configuration options HTML Tidy uses to
+        clean html, and can be modified to suit your organizations
+        requirements.
+
+  - html-tidy-logic.php
+        This is the php script, which is queried with dirty html and is
+        responsible for invoking HTML Tidy, getting nice new html and
+        returning it to the client.
+
+  - html-tidy.js
+        The main htmlArea plugin, providing functionality to tidy html
+        through the htmlArea interface.
+
+  - htmlarea.js.onmode_event.diff
+        At the time of publishing, an extra event handler was required
+        inside the main htmlarea.js file. htmlarea.js may be patched
+        against this file to make the changes reuquired, but be aware
+        that the event handler may either now be in the core or
+        htmlarea.js may have changed enough to invalidate the patch.
+	
+	UPDATE: now it exists in the official htmlarea.js; applying
+	this patch is thus no longer necessary.
+
+  - img/html-tidy.gif
+        The HtmlTidy icon, for the htmlArea toolbar. Created by Dan
+        Petty for The University of Western Australia.
+
+  - lang/en.js
+        English language file. Add your own language files here and
+        please contribute back into the htmlArea community!
+
+  The HtmlArea directory should be extracted to your htmlarea/plugins/
+  directory.
+
+
+* Make sure the onMode event handler mentioned above, regarding
+  htmlarea.js.onmode_event.diff, exists in your htmlarea.js
+
+
+* html-tidy-logic.php should be executable, and your web server should
+  be configured to execute php scripts in the directory
+  html-tidy-logic.php exists in.
+
+
+* HTML Tidy needs to be installed on your server, and 'tidy' should be
+  an alias to it, lying in the PATH known to the user executing such
+  web scripts.
+
+
+* In your htmlArea configuration, do something like this:
+
+    HTMLArea.loadPlugin("HtmlTidy");
+
+    editor = new HTMLArea("doc");
+    editor.registerPlugin("HtmlTidy");
+
+
+* Then, in your htmlArea toolbar configuration, use:
+
+    - "HT-html-tidy"
+        This will create the 'tidy broom' icon on the toolbar, which
+        will attempt to tidy html source when clicked, and;
+
+    - "HT-auto-tidy"
+        This will create an "Auto Tidy" / "Don't Tidy" dropdown, to
+        select whether the source should be tidied automatically when
+        entering source view. On by default, if you'd like it otherwise
+        you can do so programatically after generating the toolbar :)
+        (Or just hack it to be otherwise...)
+    
+
+Thank you.
+
+Any bugs you find can be emailed to zeno@ucc.gu.uwa.edu.au

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-config.cfg
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-config.cfg?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-config.cfg (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-config.cfg Fri Sep 21 03:36:30 2007
@@ -0,0 +1,29 @@
+// Default configuration file for the htmlArea, HtmlTidy plugin
+// By Adam Wright, for The University of Western Australia
+//
+// Evertything you always wanted to know about HTML Tidy *
+// can be found at http://tidy.sourceforge.net/, and a
+// quick reference to the configuration options exists at
+// http://tidy.sourceforge.net/docs/quickref.html
+//
+// * But were afraid to ask
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+
+word-2000: yes
+clean: yes
+drop-font-tags: no
+doctype: auto
+drop-empty-paras: yes
+drop-proprietary-attributes: yes
+enclose-block-text: yes
+enclose-text: yes
+escape-cdata: yes
+logical-emphasis: yes
+indent: auto
+indent-spaces: 2
+break-before-br: yes
+output-xhtml: yes
+
+force-output: yes

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-logic.php
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-logic.php?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-logic.php (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy-logic.php Fri Sep 21 03:36:30 2007
@@ -0,0 +1,79 @@
+<?php 
+##
+##  Plugin for htmlArea, to run code through the server's HTML Tidy
+##   By Adam Wright, for The University of Western Australia
+##    This is the server-side script, which dirty code is run through.
+##
+##  Distributed under the same terms as HTMLArea itself.
+##  This notice MUST stay intact for use (see license.txt).
+##
+
+	// Get the original source
+	$source = $_POST['htisource_name'];
+	$source = stripslashes($source);
+  $cwd = str_replace("\\","/",getcwd())."/";
+  
+	// Open a tidy process - I hope it's installed!
+	$descriptorspec = array(
+		0 => array("pipe", "r"),
+		1 => array("pipe", "w")
+	);
+	$process = @proc_open("tidy -utf8 -config {$cwd}html-tidy-config.cfg", $descriptorspec, $pipes);
+
+
+	// Make sure the program started and we got the hooks...
+	// Either way, get some source code into $source
+	if (is_resource($process)) {
+
+		// Feed untidy source into the stdin
+		fwrite($pipes[0], $source);
+		fclose($pipes[0]);
+
+		// Read clean source out to the browser
+		while (!feof($pipes[1])) {
+			//echo fgets($pipes[1], 1024);
+			$newsrc .= fgets($pipes[1], 1024);
+		}
+		fclose($pipes[1]);
+
+		// Clean up after ourselves
+		proc_close($process);
+
+	} else {
+    /* Use tidy if it's available from PECL */
+    if( function_exists('tidy_parse_string') )
+    {
+      $tempsrc = tidy_parse_string($source);
+      tidy_clean_repair();
+      $newsrc = tidy_get_output();
+    }
+    else
+    {
+      // Better give them back what they came with, so they don't lose it all...
+      $newsrc = "<body>\n" .$source. "\n</body>";
+    }
+	}
+
+	// Split our source into an array by lines
+	$srcLines = preg_split("/\n/",$newsrc,-1,PREG_SPLIT_NO_EMPTY);
+
+	// Get only the lines between the body tags
+	$startLn = 0;
+	while ( strpos( $srcLines[$startLn++], '<body' ) === false && $startLn < sizeof($srcLines) );
+	$endLn = $startLn;
+	while ( strpos( $srcLines[$endLn++], '</body' ) === false && $endLn < sizeof($srcLines) );
+
+	$srcLines = array_slice( $srcLines, $startLn, ($endLn - $startLn - 1) );
+
+	// Create a set of javascript code to compile a new source string
+	foreach ($srcLines as $line) {
+		$jsMakeSrc .= "\tns += '" . str_replace("'","\'",$line) . "\\n';\n";
+	}
+if(!sizeof($srcLines)) {
+    echo "alert(HTMLArea._lc('Tidy failed.  Check your HTML for syntax errors.', 'HtmlTidy'));\n";
+} else {
+?>
+var ns="";
+<?php echo $jsMakeSrc; ?>
+editor.setHTML(ns);
+<? } ?>
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/html-tidy.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,105 @@
+// Plugin for htmlArea to run code through the server's HTML Tidy
+// By Adam Wright, for The University of Western Australia
+//
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+
+function HtmlTidy(editor) {
+	this.editor = editor;
+
+	var cfg = editor.config;
+	var bl = HtmlTidy.btnList;
+	var self = this;
+
+	this.onMode = this.__onMode;
+
+	// register the toolbar buttons provided by this plugin
+	var toolbar = [];
+	for (var i = 0; i < bl.length; ++i) {
+		var btn = bl[i];
+		if (btn == "html-tidy") {
+			var id = "HT-html-tidy";
+			cfg.registerButton(id, this._lc("HTML Tidy"), editor.imgURL(btn[0] + ".gif", "HtmlTidy"), true,
+					   function(editor, id) {
+						   // dispatch button press event
+						   self.buttonPress(editor, id);
+					   }, btn[1]);
+			toolbar.push(id);
+		} else if (btn == "html-auto-tidy") {
+            var btnTxt = [this._lc("Auto-Tidy"), this._lc("Don't Tidy")];
+            var optionItems = new Object();
+            optionItems[btnTxt[0]] = "auto";
+            optionItems[btnTxt[1]] = "noauto";
+			var ht_class = {
+				id	: "HT-auto-tidy",
+				options	: optionItems,
+				action	: function (editor) { self.__onSelect(editor, this); },
+				refresh	: function (editor) { },
+				context	: "body"
+			};
+			cfg.registerDropdown(ht_class);
+		}
+	}
+
+	for (var i in toolbar) {
+		cfg.toolbar[0].push(toolbar[i]);
+	}
+}
+
+HtmlTidy._pluginInfo = {
+	name          : "HtmlTidy",
+	version       : "1.0",
+	developer     : "Adam Wright",
+	developer_url : "http://blog.hipikat.org/",
+	sponsor       : "The University of Western Australia",
+	sponsor_url   : "http://www.uwa.edu.au/",
+	license       : "htmlArea"
+};
+
+HtmlTidy.prototype._lc = function(string) {
+    return HTMLArea._lc(string, 'HtmlTidy');
+};
+
+HtmlTidy.prototype.__onSelect = function(editor, obj) {
+	// Get the toolbar element object
+	var elem = editor._toolbarObjects[obj.id].element;
+
+	// Set our onMode event appropriately
+	if (elem.value == "auto")
+		this.onMode = this.__onMode;
+	else
+		this.onMode = null;
+};
+
+HtmlTidy.prototype.__onMode = function(mode) {
+	if ( mode == "textmode" ) {
+		this.buttonPress(this.editor, "HT-html-tidy");
+	}
+};
+
+HtmlTidy.btnList = [
+		    null, // separator
+		    ["html-tidy"],
+		    ["html-auto-tidy"]
+];
+
+HtmlTidy.prototype.buttonPress = function(editor, id) {
+
+	switch (id)
+  {
+    case "HT-html-tidy":
+    {
+      var oldhtml = editor.getHTML();
+      if(oldhtml=="") break; //don't clean empty text
+      // Ask the server for some nice new html, based on the old...
+      HTMLArea._postback(_editor_url + 'plugins/HtmlTidy/html-tidy-logic.php', {'htisource_name' : oldhtml},
+                            function(javascriptResponse) { eval(javascriptResponse) });
+    }
+		break;
+	}
+};
+
+HtmlTidy.prototype.processTidied = function(newSrc) {
+	editor = this.editor;
+	editor.setHTML(newSrc);
+};
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/img/html-tidy.gif
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/img/html-tidy.gif?rev=578051&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/img/html-tidy.gif
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/de.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/de.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/de.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/de.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,7 @@
+// I18N constants
+// LANG: "de", ENCODING: UTF-8
+// Author: Raimund Meyer ray@ray-of-light.org
+{
+  "HTML Tidy": "HTML Tidy",
+	"Tidy failed.  Check your HTML for syntax errors.": "Tidy fehlgeschlagen. Prüfen Sie den HTML Code nach Syntax-Fehlern."  
+};

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/fr.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/fr.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/fr.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/fr.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,8 @@
+// I18N constants
+// LANG: "fr", ENCODING: UTF-8
+{
+  "HTML Tidy": "HTML Tidy",
+  "Auto-Tidy": "Tidy automatique",
+  "Don't Tidy": "Tidy non utilisé",
+  "Tidy failed.  Check your HTML for syntax errors.": "Tidy a échoué. Vérifiez votre HTML for des erreurs de syntaxe"
+};
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/ja.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/ja.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/ja.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/ja.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,8 @@
+// I18N constants
+// LANG: "ja", ENCODING: UTF-8
+{
+  "HTML Tidy": "HTML Tidy",
+  "Auto-Tidy": "自動適正化",
+  "Don't Tidy": "適正化しない",
+  "Tidy failed.  Check your HTML for syntax errors.":"適正化に失敗しました。HTMLの文法エラーを確認してください。"
+};
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nb.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nb.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nb.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nb.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,7 @@
+// I18N constants
+// LANG: "nb", ENCODING: UTF-8
+// translated: Kim Steinhaug, http://www.steinhaug.com/, kim@steinhaug.com
+{
+  "HTML Tidy": "HTML Tidy",
+  "Tidy failed.  Check your HTML for syntax errors.": "Tidy feilet. Sjekk HTML koden for syntaksfeil."
+};
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nl.js
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nl.js?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nl.js (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/HtmlTidy/lang/nl.js Fri Sep 21 03:36:30 2007
@@ -0,0 +1,5 @@
+// I18N constants
+// LANG: "nl", ENCODING: UTF-8
+{
+  "HT-html-tidy": "HTML opschonen"
+};
\ No newline at end of file

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/Files.php
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/Files.php?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/Files.php (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/Files.php Fri Sep 21 03:36:30 2007
@@ -0,0 +1,333 @@
+<?php
+/**
+ * File Utilities.
+ * @author $Author: ray $
+ * @version $Id: Files.php 709 2007-01-30 23:22:04Z ray $
+ * @package ImageManager
+ */
+
+define('FILE_ERROR_NO_SOURCE', 100);
+define('FILE_ERROR_COPY_FAILED', 101);
+define('FILE_ERROR_DST_DIR_FAILED', 102);
+define('FILE_COPY_OK', 103);
+define('FILE_ERROR_DST_DIR_EXIST', 104);
+
+/**
+ * File Utilities
+ * @author $Author: ray $
+ * @version $Id: Files.php 709 2007-01-30 23:22:04Z ray $
+ * @package ImageManager
+ * @subpackage files
+ */
+class Files 
+{
+	
+	/**
+	 * Copy a file from source to destination. If unique == true, then if
+	 * the destination exists, it will be renamed by appending an increamenting 
+	 * counting number.
+	 * @param string $source where the file is from, full path to the files required
+	 * @param string $destination_file name of the new file, just the filename
+	 * @param string $destination_dir where the files, just the destination dir,
+	 * e.g., /www/html/gallery/
+	 * @param boolean $unique create unique destination file if true.
+	 * @return string the new copied filename, else error if anything goes bad.
+	 */
+	function copyFile($source, $destination_dir, $destination_file, $unique=true) 
+	{
+		if(!(file_exists($source) && is_file($source))) 
+			return FILE_ERROR_NO_SOURCE;
+
+		$destination_dir = Files::fixPath($destination_dir);
+
+		if(!is_dir($destination_dir)) 
+			Return FILE_ERROR_DST_DIR_FAILED;
+
+		$filename = Files::escape($destination_file);
+
+		if($unique) 
+		{
+			$dotIndex = strrpos($destination_file, '.');
+			$ext = '';
+			if(is_int($dotIndex)) 
+			{
+				$ext = substr($destination_file, $dotIndex);
+				$base = substr($destination_file, 0, $dotIndex);
+			}
+			$counter = 0;
+			while(is_file($destination_dir.$filename)) 
+			{
+				$counter++;
+				$filename = $base.'_'.$counter.$ext;
+			}
+		}
+
+		if (!copy($source, $destination_dir.$filename))
+			return FILE_ERROR_COPY_FAILED;
+		
+		//verify that it copied, new file must exists
+		if (is_file($destination_dir.$filename))
+			Return $filename;
+		else
+			return FILE_ERROR_COPY_FAILED;
+	}
+
+	/**
+	 * Create a new folder.
+	 * @param string $newFolder specifiy the full path of the new folder.
+	 * @return boolean true if the new folder is created, false otherwise.
+	 */
+	function createFolder($newFolder) 
+	{
+		mkdir ($newFolder, 0777);
+		return chmod($newFolder, 0777);
+	}
+
+
+	/**
+	 * Escape the filenames, any non-word characters will be
+	 * replaced by an underscore.
+	 * @param string $filename the orginal filename
+	 * @return string the escaped safe filename
+	 */
+	function escape($filename)
+	{
+		Return preg_replace('/[^\w\._]/', '_', $filename);
+	}
+
+	/**
+	 * Delete a file.
+	 * @param string $file file to be deleted
+	 * @return boolean true if deleted, false otherwise.
+	 */
+	function delFile($file) 
+	{
+		if(is_file($file)) 
+			Return unlink($file);
+		else
+			Return false;
+	}
+
+	/**
+	 * Delete folder(s), can delete recursively.
+	 * @param string $folder the folder to be deleted.
+	 * @param boolean $recursive if true, all files and sub-directories
+	 * are delete. If false, tries to delete the folder, can throw
+	 * error if the directory is not empty.
+	 * @return boolean true if deleted.
+	 */
+	function delFolder($folder, $recursive=false) 
+	{
+		$deleted = true;
+		if($recursive) 
+		{
+			$d = dir($folder);
+			while (false !== ($entry = $d->read())) 
+			{
+				if ($entry != '.' && $entry != '..')
+				{
+					$obj = Files::fixPath($folder).$entry;
+					//var_dump($obj);
+					if (is_file($obj))
+					{
+						$deleted &= Files::delFile($obj);					
+					}
+					else if(is_dir($obj))
+					{
+						$deleted &= Files::delFolder($obj, $recursive);
+					}
+					
+				}
+			}
+			$d->close();
+
+		}
+
+		//$folder= $folder.'/thumbs';
+		//var_dump($folder);
+		if(is_dir($folder)) 
+			$deleted &= rmdir($folder);
+		else
+			$deleted &= false;
+
+		Return $deleted;
+	}
+
+	/**
+	 * Append a / to the path if required.
+	 * @param string $path the path
+	 * @return string path with trailing /
+	 */
+	function fixPath($path) 
+	{
+		//append a slash to the path if it doesn't exists.
+		if(!(substr($path,-1) == '/'))
+			$path .= '/';
+		Return $path;
+	}
+
+	/**
+	 * Concat two paths together. Basically $pathA+$pathB
+	 * @param string $pathA path one
+	 * @param string $pathB path two
+	 * @return string a trailing slash combinded path.
+	 */
+	function makePath($pathA, $pathB) 
+	{
+		$pathA = Files::fixPath($pathA);
+		if(substr($pathB,0,1)=='/')
+			$pathB = substr($pathB,1);
+		Return Files::fixPath($pathA.$pathB);
+	}
+
+	/**
+	 * Similar to makePath, but the second parameter
+	 * is not only a path, it may contain say a file ending.
+	 * @param string $pathA the leading path
+	 * @param string $pathB the ending path with file
+	 * @return string combined file path.
+	 */
+	function makeFile($pathA, $pathB) 
+	{		
+		$pathA = Files::fixPath($pathA);
+		if(substr($pathB,0,1)=='/')
+			$pathB = substr($pathB,1);
+		
+		Return $pathA.$pathB;
+	}
+
+	
+	/**
+	 * Format the file size, limits to Mb.
+	 * @param int $size the raw filesize
+	 * @return string formated file size.
+	 */
+	function formatSize($size) 
+	{
+		if($size < 1024) 
+			return $size.' bytes';	
+		else if($size >= 1024 && $size < 1024*1024) 
+			return sprintf('%01.2f',$size/1024.0).' KB';
+		else
+			return sprintf('%01.2f',$size/(1024.0*1024)).' MB';
+	}
+
+	/**
+	 * Returns size of a directory, with all file & subdirectory
+	 * sizes added up
+	 * @param string dir path
+	 * @return int
+	 */
+	function dirSize($dirName = '.')
+	{
+		$dir  = dir($dirName);
+		$size = 0;
+
+		while ($file = $dir->read()) {
+			if ($file != '.' && $file != '..')
+			{
+				if (is_dir("$dirName$file"))
+				{
+					$size += Files::dirSize($dirName . '/' . $file);
+				}
+				else
+				{
+					$size += filesize($dirName . '/' . $file);
+				}
+			}
+		}
+		$dir->close();
+		return $size;
+	}
+	
+	/**
+	 * Renames file, preserving its directory and extension
+	 * @param string $oldPath path to the old existing file
+	 * @param string new filename (just the name, without path or extension)
+	 * @author Krzysztof Kotowicz <ko...@webworkers.pl>
+	 */
+	function renameFile($oldPath, $newName) {
+
+		if(!(file_exists($oldPath) && is_file($oldPath)))
+			return FILE_ERROR_NO_SOURCE;
+
+		$oldFileParts = pathinfo($oldPath);
+
+		$newPath = $oldFileParts['dirname'] . '/'
+				   . $newName
+				   . (!empty($oldFileParts['extension']) ? '.' . $oldFileParts['extension'] : '');
+
+		if (file_exists($newPath))
+			return false;
+
+		if (!rename($oldPath, $newPath))
+			return FILE_ERROR_COPY_FAILED;
+
+	}
+	
+	function rename ($oldPath,$newPath)
+	{
+		if(!(is_dir($oldPath) || is_file($oldPath)))
+			return FILE_ERROR_NO_SOURCE;
+		
+		if (file_exists($newPath))
+			return FILE_ERROR_DST_DIR_EXIST;
+
+		$ret = rename($oldPath, $newPath);
+		if (!$ret)
+			return FILE_ERROR_COPY_FAILED;
+		else return FILE_COPY_OK;
+	}
+	
+		/**
+	 * copy a directory and all subdirectories and files (recursive)
+	 * @author SBoisvert at Don'tSpamMe dot Bryxal dot ca (adapted from php.net)
+	 * @author Raimund Meyer
+	 * @param string base path
+	 * @param string source directory
+	 * @param string destination directory
+	 * @param bool   overwrite existing files
+	 *  
+	 * @return mixed bool true on pass, number on fail
+	 */
+  	function copyDir($basePath, $source, $dest, $overwrite = false)
+	{
+		if(!is_dir($basePath . $dest))
+		{
+			if (!@mkdir($basePath . $dest)) return FILE_ERROR_DST_DIR_FAILED;	
+		}
+		if($handle = opendir($basePath . $source))
+		{        // if the folder exploration is sucsessful, continue
+			while( ($file = readdir($handle)) !== false)
+			{ // as long as storing the next file to $file is successful, continue
+				if($file != '.' && $file != '..')
+				{
+					$path = $source . '/' . $file;
+					if(is_file($basePath . $path))
+					{
+						/*if(!is_file($basePath . $dest . '/' . $file) || $overwrite)
+						{
+							if(!@copy($basePath . $path, $basePath . $dest . '/' . $file))
+							{
+							  return FILE_ERROR_COPY_FAILED;
+							}
+						}*/
+						Files::copyFile($basePath . $path, $basePath . $dest . '/', $file, true);
+					} 
+					elseif(is_dir($basePath . $path))
+					{
+						if(!is_dir($basePath . $dest . '/' . $file))
+						{
+							mkdir($basePath . $dest . '/' . $file); // make subdirectory before subdirectory is copied
+							Files::copyDir($basePath, $path, $dest . '/' . $file, $overwrite); //recurse!
+						}
+					}
+				}
+			}
+			closedir($handle);
+		}
+		return true;
+	}
+}
+
+?>

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/GD.php
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/GD.php?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/GD.php (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/GD.php Fri Sep 21 03:36:30 2007
@@ -0,0 +1,503 @@
+<?php
+/***********************************************************************
+** Title.........:  GD Driver
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <we...@zhuo.org>
+** Filename......:  GD.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+**/
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <pe...@mapledesign.co.uk>                      |
+// |          Alan Knowles <al...@akbkhome.com>                            |
+// +----------------------------------------------------------------------+
+//
+//    Usage :
+//    $img    = new Image_Transform_GD();
+//    $angle  = -78;
+//    $img->load('magick.png');
+//
+//    if($img->rotate($angle,array('autoresize'=>true,'color_mask'=>array(255,0,0)))){
+//        $img->addText(array('text'=>"Rotation $angle",'x'=>0,'y'=>100,'font'=>'/usr/share/fonts/default/TrueType/cogb____.ttf'));
+//        $img->display();
+//    } else {
+//        echo "Error";
+//    }
+//
+//
+// $Id: GD.php 709 2007-01-30 23:22:04Z ray $
+//
+// Image Transformation interface using the GD library
+//
+
+require_once "../ImageManager/Classes/Transform.php";
+
+Class Image_Transform_Driver_GD extends Image_Transform
+{
+    /**
+     * Holds the image file for manipulation
+     */
+    var $imageHandle = '';
+
+    /**
+     * Holds the original image file
+     */
+    var $old_image = '';
+
+    /**
+     * Check settings
+     *
+     * @return mixed true or  or a PEAR error object on error
+     *
+     * @see PEAR::isError()
+     */
+    function Image_Transform_GD()
+    {
+        return;
+    } // End function Image
+
+    /**
+     * Load image
+     *
+     * @param string filename
+     *
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function load($image)
+    {
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+        $this->image = $image;
+        $this->_get_image_details($image);
+        $functionName = 'ImageCreateFrom' . $this->type;
+		if(function_exists($functionName))
+		{
+			$this->imageHandle = $functionName($this->image);
+		}
+    } // End load
+
+    /**
+     * addText
+     *
+     * @param   array   options     Array contains options
+     *                              array(
+     *                                  'text'  The string to draw
+     *                                  'x'     Horizontal position
+     *                                  'y'     Vertical Position
+     *                                  'Color' Font color
+     *                                  'font'  Font to be used
+     *                                  'size'  Size of the fonts in pixel
+     *                                  'resize_first'  Tell if the image has to be resized
+     *                                                  before drawing the text
+     *                              )
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function addText($params)
+    {
+        $default_params = array(
+                                'text' => 'This is Text',
+                                'x' => 10,
+                                'y' => 20,
+                                'color' => array(255,0,0),
+                                'font' => 'Arial.ttf',
+                                'size' => '12',
+                                'angle' => 0,
+                                'resize_first' => false // Carry out the scaling of the image before annotation?  Not used for GD
+                                );
+        $params = array_merge($default_params, $params);
+        extract($params);
+
+        if( !is_array($color) ){
+            if ($color[0]=='#'){
+                $this->colorhex2colorarray( $color );
+            } else {
+                include_once('Image/Transform/Driver/ColorsDefs.php');
+                $color = isset($colornames[$color])?$colornames[$color]:false;
+            }
+        }
+
+        $c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);
+
+        if ('ttf' == substr($font, -3)) {
+            ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
+        } else {
+            ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
+        }
+        return true;
+    } // End addText
+
+
+    /**
+     * Rotate image by the given angle
+     * Uses a fast rotation algorythm for custom angles
+     * or lines copy for multiple of 90 degrees
+     *
+     * @param int       $angle      Rotation angle
+     * @param array     $options    array(  'autoresize'=>true|false,
+     *                                      'color_mask'=>array(r,g,b), named color or #rrggbb
+     *                                   )
+     * @author Pierre-Alain Joye
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function rotate($angle, $options=null)
+    {
+        if(function_exists('imagerotate')) {
+            $white = imagecolorallocate ($this->imageHandle, 255, 255, 255);
+			$this->imageHandle = imagerotate($this->imageHandle, $angle, $white);
+            return true;
+        }
+
+        if ( $options==null ){
+            $autoresize = true;
+            $color_mask = array(255,255,0);
+        } else {
+            extract( $options );
+        }
+
+        while ($angle <= -45) {
+            $angle  += 360;
+        }
+        while ($angle > 270) {
+            $angle  -= 360;
+        }
+
+        $t      = deg2rad($angle);
+
+        if( !is_array($color_mask) ){
+            if ($color[0]=='#'){
+                $this->colorhex2colorarray( $color_mask );
+            } else {
+                include_once('Image/Transform/Driver/ColorDefs.php');
+                $color = isset($colornames[$color_mask])?$colornames[$color_mask]:false;
+            }
+        }
+
+        // Do not round it, too much lost of quality
+        $cosT   = cos($t);
+        $sinT   = sin($t);
+
+        $img    =& $this->imageHandle;
+
+        $width  = $max_x  = $this->img_x;
+        $height = $max_y  = $this->img_y;
+        $min_y  = 0;
+        $min_x  = 0;
+
+        $x1     = round($max_x/2,0);
+        $y1     = round($max_y/2,0);
+
+        if ( $autoresize ){
+            $t      = abs($t);
+            $a      = round($angle,0);
+            switch((int)($angle)){
+                case 0:
+                        $width2     = $width;
+                        $height2    = $height;
+                    break;
+                case 90:
+                        $width2     = $height;
+                        $height2    = $width;
+                    break;
+                case 180:
+                        $width2     = $width;
+                        $height2    = $height;
+                    break;
+                case 270:
+                        $width2     = $height;
+                        $height2    = $width;
+                    break;
+                default:
+                    $width2     = (int)(abs(sin($t) * $height + cos($t) * $width));
+                    $height2    = (int)(abs(cos($t) * $height+sin($t) * $width));
+            }
+
+            $width2     -= $width2%2;
+            $height2    -= $height2%2;
+
+            $d_width    = abs($width - $width2);
+            $d_height   = abs($height - $height2);
+            $x_offset   = $d_width/2;
+            $y_offset   = $d_height/2;
+            $min_x2     = -abs($x_offset);
+            $min_y2     = -abs($y_offset);
+            $max_x2     = $width2;
+            $max_y2     = $height2;
+        }
+
+        $img2   = @imagecreate($width2,$height2);
+
+        if ( !is_resource($img2) ){
+            return false;/*PEAR::raiseError('Cannot create buffer for the rotataion.',
+                                null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
+        }
+
+        $this->img_x = $width2;
+        $this->img_y = $height2;
+
+
+        imagepalettecopy($img2,$img);
+
+        $mask   = imagecolorresolve($img2,$color_mask[0],$color_mask[1],$color_mask[2]);
+
+        // use simple lines copy for axes angles
+        switch((int)($angle)){
+            case 0:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $min_x; $x < $max_x; $x++){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
+                    }
+                }
+                break;
+            case 90:
+                imagefill ($img2, 0, 0,$mask);
+                for ($x = $min_x; $x < $max_x; $x++){
+                    for ($y=$min_y; $y < $max_y; $y++) {
+                        $c  = imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$max_y-$y-1,$x,$c);
+                    }
+                }
+                break;
+            case 180:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $min_x; $x < $max_x; $x++){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2, $max_x2-$x-1, $max_y2-$y-1, $c);
+                    }
+                }
+                break;
+            case 270:
+                imagefill ($img2, 0, 0,$mask);
+                for ($y=0; $y < $max_y; $y++) {
+                    for ($x = $max_x; $x >= $min_x; $x--){
+                        $c  = @imagecolorat ( $img, $x, $y);
+                        imagesetpixel($img2,$y,$max_x-$x-1,$c);
+                    }
+                }
+                break;
+            // simple reverse rotation algo
+            default:
+                $i=0;
+                for ($y = $min_y2; $y < $max_y2; $y++){
+
+                    // Algebra :)
+                    $x2 = round((($min_x2-$x1) * $cosT) + (($y-$y1) * $sinT + $x1),0);
+                    $y2 = round((($y-$y1) * $cosT - ($min_x2-$x1) * $sinT + $y1),0);
+
+                    for ($x = $min_x2; $x < $max_x2; $x++){
+
+                        // Check if we are out of original bounces, if we are
+                        // use the default color mask
+                        if ( $x2>=0 && $x2<$max_x && $y2>=0 && $y2<$max_y ){
+                            $c  = imagecolorat ( $img, $x2, $y2);
+                        } else {
+                            $c  = $mask;
+                        }
+                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
+
+                        // round verboten!
+                        $x2  += $cosT;
+                        $y2  -= $sinT;
+                    }
+                }
+                break;
+        }
+        $this->old_image    = $this->imageHandle;
+        $this->imageHandle  =  $img2;
+        return true;
+    }
+
+
+   /**
+    * Resize Action
+    *
+    * For GD 2.01+ the new copyresampled function is used
+    * It uses a bicubic interpolation algorithm to get far
+    * better result.
+    *
+    * @param int  $new_x new width
+    * @param int  $new_y new height
+    *
+    * @return true on success or pear error
+    * @see PEAR::isError()
+    */
+    function _resize($new_x, $new_y) {
+        if ($this->resized === true) {
+            return false; /*PEAR::raiseError('You have already resized the image without saving it.  Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
+        }
+        if(function_exists('ImageCreateTrueColor')){
+            $new_img =ImageCreateTrueColor($new_x,$new_y);
+        } else {
+            $new_img =ImageCreate($new_x,$new_y);
+        }
+        if(function_exists('ImageCopyResampled')){
+            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
+        } else {
+            ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
+        }
+        $this->old_image = $this->imageHandle;
+        $this->imageHandle = $new_img;
+        $this->resized = true;
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+        return true;
+    }
+
+    /**
+     * Crop the image
+     *
+     * @param int $crop_x left column of the image
+     * @param int $crop_y top row of the image
+     * @param int $crop_width new cropped image width
+     * @param int $crop_height new cropped image height
+     */
+    function crop($new_x, $new_y, $new_width, $new_height) 
+    {
+        if(function_exists('ImageCreateTrueColor')){
+            $new_img =ImageCreateTrueColor($new_width,$new_height);
+        } else {
+            $new_img =ImageCreate($new_width,$new_height);
+        }
+        if(function_exists('ImageCopyResampled')){
+            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, $new_x, $new_y,$new_width,$new_height,$new_width,$new_height);
+        } else {
+            ImageCopyResized($new_img, $this->imageHandle, 0, 0, $new_x, $new_y, $new_width,$new_height,$new_width,$new_height);
+        }
+        $this->old_image = $this->imageHandle;
+        $this->imageHandle = $new_img;
+        $this->resized = true;
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+        return true;
+    }
+   
+    /**
+     * Flip the image horizontally or vertically
+     *
+     * @param boolean $horizontal true if horizontal flip, vertical otherwise
+     */
+    function flip($horizontal)
+    {
+        if(!$horizontal) {
+            $this->rotate(180);
+        }
+
+        $width = imagesx($this->imageHandle); 
+        $height = imagesy($this->imageHandle); 
+
+        for ($j = 0; $j < $height; $j++) { 
+                $left = 0; 
+                $right = $width-1; 
+
+
+                while ($left < $right) { 
+                    //echo " j:".$j." l:".$left." r:".$right."\n<br>";
+                    $t = imagecolorat($this->imageHandle, $left, $j); 
+                    imagesetpixel($this->imageHandle, $left, $j, imagecolorat($this->imageHandle, $right, $j)); 
+                    imagesetpixel($this->imageHandle, $right, $j, $t); 
+                    $left++; $right--; 
+                } 
+            
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Adjust the image gamma
+     *
+     * @param float $outputgamma
+     *
+     * @return none
+     */
+    function gamma($outputgamma=1.0) {
+        ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);
+    }
+
+    /**
+     * Save the image file
+     *
+     * @param string  $filename the name of the file to write to
+     * @param int     $quality  output DPI, default is 85
+     * @param string  $types    define the output format, default
+     *                          is the current used format
+     *
+     * @return none
+     */
+    function save($filename, $type = '', $quality = 85)
+    {
+		$type           = $type==''? $this->type : $type;
+		$functionName   = 'image' . $type;
+
+		if(function_exists($functionName))
+		{
+			$this->old_image = $this->imageHandle;
+			if($type=='jpeg')
+				$functionName($this->imageHandle, $filename, $quality);
+			else
+				$functionName($this->imageHandle, $filename);
+			$this->imageHandle = $this->old_image;
+			$this->resized = false;
+		}
+    } // End save
+
+
+    /**
+     * Display image without saving and lose changes
+     *
+     * @param string type (JPG,PNG...);
+     * @param int quality 75
+     *
+     * @return none
+     */
+    function display($type = '', $quality = 75)
+    {
+        if ($type != '') {
+            $this->type = $type;
+        }
+        $functionName = 'Image' . $this->type;
+		if(function_exists($functionName))
+		{
+			header('Content-type: image/' . strtolower($this->type));
+			$functionName($this->imageHandle, '', $quality);
+			$this->imageHandle = $this->old_image;
+			$this->resized = false;
+			ImageDestroy($this->old_image);
+			$this->free();
+		}
+    }
+
+    /**
+     * Destroy image handle
+     *
+     * @return none
+     */
+    function free()
+    {
+        if ($this->imageHandle){
+            ImageDestroy($this->imageHandle);
+        }
+    }
+
+} // End class ImageGD
+?>

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/IM.php
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/IM.php?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/IM.php (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/IM.php Fri Sep 21 03:36:30 2007
@@ -0,0 +1,235 @@
+<?php
+
+/***********************************************************************
+** Title.........:  ImageMagick Driver
+** Version.......:  1.0
+** Author........:  Xiang Wei ZHUO <we...@zhuo.org>
+** Filename......:  IM.php
+** Last changed..:  30 Aug 2003 
+** Notes.........:  Orginal is from PEAR
+**/
+
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.02 of the PHP license,      |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Peter Bowyer <pe...@mapledesign.co.uk>                      |
+// +----------------------------------------------------------------------+
+//
+// $Id: IM.php 709 2007-01-30 23:22:04Z ray $
+//
+// Image Transformation interface using command line ImageMagick
+//
+
+require_once "../ImageManager/Classes/Transform.php";
+
+Class Image_Transform_Driver_IM extends Image_Transform
+{
+    /**
+     * associative array commands to be executed
+     * @var array
+     */
+    var $command = array();
+
+    /**
+     *
+     *
+     */
+    function Image_Transform_Driver_IM()
+    {
+        return true;
+    } // End Image_IM
+
+    /**
+     * Load image
+     *
+     * @param string filename
+     *
+     * @return mixed none or a PEAR error object on error
+     * @see PEAR::isError()
+     */
+    function load($image)
+    {
+
+        $this->uid = md5($_SERVER['REMOTE_ADDR']);
+        /*if (!file_exists($image)) {
+            return PEAR::raiseError('The image file ' . $image . ' does\'t exist', true);
+        }*/
+        $this->image = $image;
+        $this->_get_image_details($image);
+    } // End load
+
+    /**
+     * Resize Action
+     *
+     * @param int   new_x   new width
+     * @param int   new_y   new height
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function _resize($new_x, $new_y)
+    {
+        /*if (isset($this->command['resize'])) {
+            return PEAR::raiseError("You cannot scale or resize an image more than once without calling save or display", true);
+        }*/
+        $this->command['resize'] = "-geometry ${new_x}x${new_y}!";
+
+        $this->new_x = $new_x;
+        $this->new_y = $new_y;
+    } // End resize
+
+    /**
+     * Crop the image
+     *
+     * @param int $crop_x left column of the image
+     * @param int $crop_y top row of the image
+     * @param int $crop_width new cropped image width
+     * @param int $crop_height new cropped image height
+     */
+    function crop($crop_x, $crop_y, $crop_width, $crop_height) 
+    {
+        $this->command['crop'] = "-crop {$crop_width}x{$crop_height}+{$crop_x}+{$crop_y}";
+    }
+
+    /**
+     * Flip the image horizontally or vertically
+     *
+     * @param boolean $horizontal true if horizontal flip, vertical otherwise
+     */
+    function flip($horizontal) 
+    {
+        if($horizontal)
+            $this->command['flop'] = "-flop";
+        else
+            $this->command['flip'] = "-flip";
+    }
+    /**
+     * rotate
+     *
+     * @param   int     angle   rotation angle
+     * @param   array   options no option allowed
+     *
+     */
+    function rotate($angle, $options=null)
+    {
+        if ('-' == $angle{0}) {
+            $angle = 360 - substr($angle, 1);
+        }
+         $this->command['rotate'] = "-rotate $angle";
+    } // End rotate
+
+    /**
+     * addText
+     *
+     * @param   array   options     Array contains options
+     *                              array(
+     *                                  'text'  The string to draw
+     *                                  'x'     Horizontal position
+     *                                  'y'     Vertical Position
+     *                                  'Color' Font color
+     *                                  'font'  Font to be used
+     *                                  'size'  Size of the fonts in pixel
+     *                                  'resize_first'  Tell if the image has to be resized
+     *                                                  before drawing the text
+     *                              )
+     *
+     * @return none
+     * @see PEAR::isError()
+     */
+    function addText($params)
+    {
+        $default_params = array(
+                                'text' => 'This is Text',
+                                'x' => 10,
+                                'y' => 20,
+                                'color' => 'red',
+                                'font' => 'Arial.ttf',
+                                'resize_first' => false // Carry out the scaling of the image before annotation?
+                                );
+         $params = array_merge($default_params, $params);
+         extract($params);
+         if (true === $resize_first) {
+             // Set the key so that this will be the last item in the array
+            $key = 'ztext';
+         } else {
+            $key = 'text';
+         }
+         $this->command[$key] = "-font $font -fill $color -draw 'text $x,$y \"$text\"'";
+         // Producing error: gs: not found gs: not found convert: Postscript delegate failed [No such file or directory].
+    } // End addText
+
+    /**
+     * Adjust the image gamma
+     *
+     * @param float $outputgamma
+     *
+     * @return none
+     */
+    function gamma($outputgamma=1.0) {
+        $this->command['gamma'] = "-gamma $outputgamma";
+    }
+
+    /**
+     * Save the image file
+     *
+     * @param string  $filename the name of the file to write to
+     * @param quality $quality  image dpi, default=75
+     * @param string  $type     (JPG,PNG...)
+     *
+     * @return none
+     */
+    function save($filename, $type='', $quality = 85)
+    {
+        $type == '' ? $this->type : $type;
+        $cmd = '' . IMAGE_TRANSFORM_LIB_PATH . 'convert ';
+		$cmd .= implode(' ', $this->command) . " -quality $quality ";
+		$cmd .= '"'.($this->image) . '" "' . ($filename) . '"';
+        
+        //$cmd = str_replace('/', '\\', $cmd);
+		//echo($cmd.'<br>');
+        exec($cmd,$retval);
+		//error_log('IM '.print_r($retval,true));
+    } // End save
+
+    /**
+     * Display image without saving and lose changes
+     *
+     * @param string type (JPG,PNG...);
+     * @param int quality 75
+     *
+     * @return none
+     */
+    function display($type = '', $quality = 75)
+    {
+        if ($type == '') {
+            header('Content-type: image/' . $this->type);
+            passthru(IMAGE_TRANSFORM_LIB_PATH . 'convert ' . implode(' ', $this->command) . " -quality $quality "  . escapeshellarg($this->image) . ' ' . strtoupper($this->type) . ":-");
+        } else {
+            header('Content-type: image/' . $type);
+            passthru(IMAGE_TRANSFORM_LIB_PATH . 'convert ' . implode(' ', $this->command) . " -quality $quality "  . escapeshellarg($this->image) . ' ' . strtoupper($type) . ":-");
+        }
+    }
+
+
+    /**
+     * Destroy image handle
+     *
+     * @return none
+     */
+    function free()
+    {
+        return true;
+    }
+
+} // End class ImageIM
+?>

Added: lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/ImageEditor.php
URL: http://svn.apache.org/viewvc/lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/ImageEditor.php?rev=578051&view=auto
==============================================================================
--- lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/ImageEditor.php (added)
+++ lenya/branches/revolution/1.3.x/src/webapp/lenya/modules/xinha/plugins/ImageManager/Classes/ImageEditor.php Fri Sep 21 03:36:30 2007
@@ -0,0 +1,449 @@
+<?php
+/**
+ * Image Editor. Editing tools, crop, rotate, scale and save.
+ * @author $Author: ray $
+ * @version $Id: ImageEditor.php 709 2007-01-30 23:22:04Z ray $
+ * @package ImageManager
+ */
+
+require_once('../ImageManager/Classes/Transform.php');
+
+/**
+ * Handles the basic image editing capbabilities.
+ * @author $Author: ray $
+ * @version $Id: ImageEditor.php 709 2007-01-30 23:22:04Z ray $
+ * @package ImageManager
+ * @subpackage Editor
+ */
+class ImageEditor 
+{
+	/**
+	 * ImageManager instance.
+	 */
+	var $manager;
+
+	/**
+	 * user based on IP address
+	 */
+	var $_uid;
+
+	/**
+	 * tmp file storage time.
+	 */
+	var $lapse_time =900; //15 mins
+
+	var $filesaved = 0;
+
+	/**
+	 * Create a new ImageEditor instance. Editing requires a 
+	 * tmp file, which is saved in the current directory where the
+	 * image is edited. The tmp file is assigned by md5 hash of the
+	 * user IP address. This hashed is used as an ID for cleaning up
+	 * the tmp files. In addition, any tmp files older than the
+	 * the specified period will be deleted.
+	 * @param ImageManager $manager the image manager, we need this
+	 * for some file and path handling functions.
+	 */
+	function ImageEditor($manager) 
+	{
+		$this->manager = $manager;
+		$this->_uid = md5($_SERVER['REMOTE_ADDR']);
+	}
+	
+	/**
+	 * Did we save a file?
+	 * @return int 1 if the file was saved sucessfully, 
+	 * 0 no save operation, -1 file save error.
+	 */
+	function isFileSaved() 
+	{
+		Return $this->filesaved;
+	}
+
+	/**
+	 * Process the image, if not action, just display the image.
+	 * @return array with image information, empty array if not an image.
+	 * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
+	 * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
+	 */
+	function processImage() 
+	{
+		if(isset($_GET['img']))
+			$relative = rawurldecode($_GET['img']);
+		else
+			Return array();
+		
+		//$relative = '/Series2004NoteFront.jpg';
+
+		$imgURL = $this->manager->getFileURL($relative);
+		$fullpath = $this->manager->getFullPath($relative);
+		
+		$imgInfo = @getImageSize($fullpath);
+		if(!is_array($imgInfo))
+			Return array();
+
+		$action = $this->getAction();
+
+		if(!is_null($action))
+		{
+			$image = $this->processAction($action, $relative, $fullpath);
+		}
+		else
+		{
+			$image['src'] = $imgURL;
+			$image['dimensions'] = $imgInfo[3];
+			$image['file'] = $relative;
+			$image['fullpath'] = $fullpath;
+		}
+
+		Return $image;
+	}
+
+	/**
+	 * Process the actions, crop, scale(resize), rotate, flip, and save.
+	 * When ever an action is performed, the result is save into a
+	 * temporary image file, see createUnique on the filename specs.
+	 * It does not return the saved file, alway returning the tmp file.
+	 * @param string $action, should be 'crop', 'scale', 'rotate','flip', or 'save'
+	 * @param string $relative the relative image filename
+	 * @param string $fullpath the fullpath to the image file
+	 * @return array with image information
+	 * <code>array('src'=>'url of the image', 'dimensions'=>'width="xx" height="yy"',
+	 * 'file'=>'image file, relative', 'fullpath'=>'full path to the image');</code>
+	 */
+	function processAction($action, $relative, $fullpath) 
+	{
+		$params = '';
+		
+		if(isset($_GET['params']))
+			$params = $_GET['params'];
+
+		$values =  explode(',',$params,4);
+		$saveFile = $this->getSaveFileName($values[0]);
+
+		$img = Image_Transform::factory(IMAGE_CLASS);
+		$img->load($fullpath);
+
+		switch ($action) 
+		{
+			case 'crop':
+				$img->crop(intval($values[0]),intval($values[1]),
+							intval($values[2]),intval($values[3]));
+			break;
+			case 'scale':
+				$img->resize(intval($values[0]),intval($values[1]));
+				break;
+			case 'rotate':
+				$img->rotate(floatval($values[0]));
+				break;
+			case 'flip':
+				if ($values[0] == 'hoz')
+					$img->flip(true);
+				else if($values[0] == 'ver') 
+					$img->flip(false);
+				break;
+			case 'save':
+				if(!is_null($saveFile))
+				{
+					$quality = intval($values[1]);
+		            if($quality <0) $quality = 85;
+					$newSaveFile = $this->makeRelative($relative, $saveFile);
+					$newSaveFile = $this->getUniqueFilename($newSaveFile);
+					
+					//get unique filename just returns the filename, so
+					//we need to make the relative path once more.
+					$newSaveFile = $this->makeRelative($relative, $newSaveFile);
+          $image['saveFile'] = $newSaveFile;
+					$newSaveFullpath = $this->manager->getFullPath($newSaveFile);
+					$img->save($newSaveFullpath, $values[0], $quality);
+					if(is_file($newSaveFullpath))
+						$this->filesaved = 1;
+					else
+						$this->filesaved = -1;
+				}
+				break;
+		}
+		
+		//create the tmp image file
+		$filename = $this->createUnique($fullpath);
+		$newRelative = $this->makeRelative($relative, $filename);
+		$newFullpath = $this->manager->getFullPath($newRelative);
+		$newURL = $this->manager->getFileURL($newRelative);
+		
+		//save the file.
+		$img->save($newFullpath);
+		$img->free();
+
+		//get the image information
+		$imgInfo = @getimagesize($newFullpath);
+
+		$image['src'] = $newURL;
+    $image['width'] = $imgInfo[0];
+    $image['height'] = $imgInfo[1];
+		$image['dimensions'] = $imgInfo[3];
+		$image['file'] = $newRelative;
+		$image['fullpath'] = $newFullpath;
+
+		Return $image;
+	
+	}
+
+	/**
+	 * Get the file name base on the save name
+	 * and the save type.
+	 * @param string $type image type, 'jpeg', 'png', or 'gif'
+	 * @return string the filename according to save type
+	 */
+	function getSaveFileName($type) 
+	{
+		if(!isset($_GET['file']))
+			Return null;
+
+		$filename = Files::escape(rawurldecode($_GET['file']));
+		$index = strrpos($filename,'.');
+		$base = substr($filename,0,$index);
+		$ext = strtolower(substr($filename,$index+1,strlen($filename)));
+
+		if($type == 'jpeg' && !($ext=='jpeg' || $ext=='jpg'))
+		{
+			Return $base.'.jpeg';
+		}
+		if($type=='png' && $ext != 'png')
+			Return $base.'.png';
+		if($type=='gif' && $ext != 'gif')
+			Return $base.'.gif';
+
+		Return $filename;
+	}
+
+	/**
+	 * Get the default save file name, used by editor.php.
+	 * @return string a suggestive filename, this should be unique
+	 */
+	function getDefaultSaveFile() 
+	{
+		if(isset($_GET['img']))
+			$relative = rawurldecode($_GET['img']);
+		else
+			Return null;
+
+		Return $this->getUniqueFilename($relative);
+	}
+
+	/**
+	 * Get a unique filename. If the file exists, the filename
+	 * base is appended with an increasing integer.
+	 * @param string $relative the relative filename to the base_dir
+	 * @return string a unique filename in the current path
+	 */
+	function getUniqueFilename($relative) 
+	{
+		$fullpath = $this->manager->getFullPath($relative);
+		
+		$pathinfo = pathinfo($fullpath);
+
+		$path = Files::fixPath($pathinfo['dirname']);
+		$file = Files::escape($pathinfo['basename']);
+		
+		$filename = $file;
+
+		$dotIndex = strrpos($file, '.');
+		$ext = '';
+
+		if(is_int($dotIndex)) 
+		{
+			$ext = substr($file, $dotIndex);
+			$base = substr($file, 0, $dotIndex);
+		}
+
+		$counter = 0;
+		while(is_file($path.$filename)) 
+		{
+			$counter++;
+			$filename = $base.'_'.$counter.$ext;
+		}
+		
+		Return $filename;
+		
+	}
+
+	/**
+	 * Specifiy the original relative path, a new filename
+	 * and return the new filename with relative path.
+	 * i.e. $pathA (-filename) + $file
+	 * @param string $pathA the relative file
+	 * @param string $file the new filename
+	 * @return string relative path with the new filename
+	 */
+	function makeRelative($pathA, $file) 
+	{
+		$index = strrpos($pathA,'/');
+		if(!is_int($index))
+			Return $file;
+
+		$path = substr($pathA, 0, $index);
+		Return Files::fixPath($path).$file;
+	}
+
+	/**
+	 * Get the action GET parameter
+	 * @return string action parameter
+	 */
+	function getAction() 
+	{
+		$action = null;
+		if(isset($_GET['action']))
+			$action = $_GET['action'];
+		Return $action;
+	}
+
+	/**
+	 * Generate a unique string based on md5(microtime()).
+	 * Well not so uniqe, as it is limited to 6 characters
+	 * @return string unique string.
+	 */
+    function uniqueStr()
+    {
+      return substr(md5(microtime()),0,6);
+    }
+
+	/**
+	 * Create unique tmp image file name.
+	 * The filename is based on the tmp file prefix
+	 * specified in config.inc.php plus 
+	 * the UID (basically a md5 of the remote IP)
+	 * and some random 6 character string.
+	 * This function also calls to clean up the tmp files.
+	 * @param string $file the fullpath to a file
+	 * @return string a unique filename for that path
+	 * NOTE: it only returns the filename, path no included.
+	 */
+	function createUnique($file) 
+	{
+		$pathinfo = pathinfo($file);
+		$path = Files::fixPath($pathinfo['dirname']);
+		$imgType = $this->getImageType($file);
+
+		$unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
+
+	   //make sure the the unique temp file does not exists
+        while (file_exists($path.$unique_str))
+        {
+            $unique_str = $this->manager->getTmpPrefix().$this->_uid.'_'.$this->uniqueStr().".".$imgType;
+        }
+
+		$this->cleanUp($path,$pathinfo['basename']);
+
+		Return $unique_str;
+	}
+
+	/**
+	 * Delete any tmp image files.
+	 * @param string $path the full path 
+	 * where the clean should take place.
+	 */
+	function cleanUp($path,$file) 
+	{
+		$path = Files::fixPath($path);
+
+		if(!is_dir($path))
+			Return false;
+
+		$d = @dir($path);
+		
+		$tmp = $this->manager->getTmpPrefix();
+		$tmpLen = strlen($tmp);
+
+		$prefix = $tmp.$this->_uid;
+		$len = strlen($prefix);
+
+		while (false !== ($entry = $d->read())) 
+		{
+			//echo $entry."<br>";
+			if(is_file($path.$entry) && $this->manager->isTmpFile($entry))
+			{
+				if(substr($entry,0,$len)==$prefix && $entry != $file)
+					Files::delFile($path.$entry);
+				else if(substr($entry,0,$tmpLen)==$tmp && $entry != $file)
+				{
+					if(filemtime($path.$entry)+$this->lapse_time < time())
+						Files::delFile($path.$entry);
+				}
+			}
+		}
+		$d->close();
+	}
+
+	/**
+	 * Get the image type base on an image file.
+	 * @param string $file the full path to the image file.
+	 * @return string of either 'gif', 'jpeg', 'png' or 'bmp'
+	 * otherwise it will return null.
+	 */
+	function getImageType($file) 
+	{
+		$imageInfo = @getImageSize($file);
+
+		if(!is_array($imageInfo))
+			Return null;
+
+		switch($imageInfo[2]) 
+		{
+			case 1:
+				Return 'gif';
+			case 2:
+				Return 'jpeg';
+			case 3:
+				Return 'png';
+			case 6:
+				Return 'bmp';
+		}
+
+		Return null;
+	}
+
+	/**
+	 * Check if the specified image can be edit by GD
+	 * mainly to check that GD can read and save GIFs
+	 * @return int 0 if it is not a GIF file, 1 is GIF is editable, -1 if not editable.
+	 */
+	function isGDEditable() 
+	{
+		if(isset($_GET['img']))
+			$relative = rawurldecode($_GET['img']);
+		else
+			Return 0;
+		if(IMAGE_CLASS != 'GD')
+			Return 0;
+
+		$fullpath = $this->manager->getFullPath($relative);
+
+		$type = $this->getImageType($fullpath);
+		if($type != 'gif')
+			Return 0;
+
+		if(function_exists('ImageCreateFrom'+$type)
+			&& function_exists('image'+$type))
+			Return 1;
+		else
+			Return -1;
+	}
+
+	/**
+	 * Check if GIF can be edit by GD.
+	 * @return int 0 if it is not using the GD library, 1 is GIF is editable, -1 if not editable.
+	 */
+	function isGDGIFAble() 
+	{
+		if(IMAGE_CLASS != 'GD')
+			Return 0;
+
+		if(function_exists('ImageCreateFromGif')
+			&& function_exists('imagegif'))
+			Return 1;
+		else
+			Return -1;
+	}
+}
+
+?>



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@lenya.apache.org
For additional commands, e-mail: commits-help@lenya.apache.org