Blob Blame History Raw
From d4b95f3ed4b8a0f47dab35a2560d76bb66117277 Mon Sep 17 00:00:00 2001
From: Ruben <ruben@rubenkerkhof.com>
Date: Sun, 17 Oct 2010 17:50:39 +0200
Subject: [PATCH 12/14] 30_utf8-support.diff from Debian

---
 README.txt         |  240 ++++++++++++++++++++++++++--------------------------
 ajaxterm.1         |    2 +
 ajaxterm.html      |    1 +
 ajaxterm.js        |   13 +++-
 ajaxterm.py        |   81 ++++++++----------
 configure.makefile |    2 +-
 utf8-escape.js     |   80 +++++++++++++++++
 7 files changed, 251 insertions(+), 168 deletions(-)
 create mode 100644 utf8-escape.js

diff --git a/README.txt b/README.txt
index 4b0ae99..05ae97f 100644
--- a/README.txt
+++ b/README.txt
@@ -1,120 +1,120 @@
-= [http://antony.lesuisse.org/qweb/trac/wiki/AjaxTerm Ajaxterm] =
-
-Ajaxterm is a web based terminal. It was totally inspired and works almost
-exactly like http://anyterm.org/ except it's much easier to install (see
-comparaison with anyterm below).
-
-Ajaxterm written in python (and some AJAX javascript for client side) and depends only on python2.3 or better.[[BR]]
-Ajaxterm is '''very simple to install''' on Linux, MacOS X, FreeBSD, Solaris, cygwin and any Unix that runs python2.3.[[BR]]
-Ajaxterm was written by Antony Lesuisse (email: al AT udev.org), License Public Domain.
-
-Use the [/qweb/forum/viewforum.php?id=2 Forum], if you have any question or remark.
-
-== News ==
-
- * 2006-10-29: v0.10 allow space in login, cgi launch fix, redhat init
- * 2006-07-12: v0.9 change uid, daemon fix (Daniel Fischer)
- * 2006-07-04: v0.8 add login support to ssh (Sven Geggus), change max width to 256
- * 2006-05-31: v0.7 minor fixes, daemon option
- * 2006-05-23: v0.6 Applied debian and gentoo patches, renamed to Ajaxterm, default port 8022
-
-== Download and Install ==
-
- * Release: [/qweb/files/Ajaxterm-0.10.tar.gz Ajaxterm-0.10.tar.gz]
- * Browse src: [/qweb/trac/browser/trunk/ajaxterm/ ajaxterm/]
-
-To install Ajaxterm issue the following commands:
-{{{
-wget http://antony.lesuisse.org/qweb/files/Ajaxterm-0.10.tar.gz
-tar zxvf Ajaxterm-0.10.tar.gz
-cd Ajaxterm-0.10
-./ajaxterm.py
-}}}
-Then point your browser to this URL : http://localhost:8022/
-
-== Screenshot ==
-
-{{{
-#!html
-<center><img src="/qweb/trac/attachment/wiki/AjaxTerm/scr.png?format=raw" alt="ajaxterm screenshot" style=""/></center>
-}}}
-
-== Documentation and Caveats ==
-
- * Ajaxterm only support latin1, if you use Ubuntu or any LANG==en_US.UTF-8 distribution don't forget to "unset LANG".
-
- * If run as root ajaxterm will run /bin/login, otherwise it will run ssh
-   localhost. To use an other command use the -c option.
-
- * By default Ajaxterm only listen at 127.0.0.1:8022. For remote access, it is
-   strongly recommended to use '''https SSL/TLS''', and that is simple to
-   configure if you use the apache web server using mod_proxy.[[BR]][[BR]]
-   Using ssl will also speed up ajaxterm (probably because of keepalive).[[BR]][[BR]]
-   Here is an configuration example:
-
-{{{
-    Listen 443
-    NameVirtualHost *:443
-
-    <VirtualHost *:443>
-       ServerName localhost
-       SSLEngine On
-       SSLCertificateKeyFile ssl/apache.pem
-       SSLCertificateFile ssl/apache.pem
-
-       ProxyRequests Off
-       <Proxy *>
-               Order deny,allow
-               Allow from all
-       </Proxy>
-       ProxyPass /ajaxterm/ http://localhost:8022/
-       ProxyPassReverse /ajaxterm/ http://localhost:8022/
-    </VirtualHost>
-}}}
-
- * Using GET HTTP request seems to speed up ajaxterm, just click on GET in the
-   interface, but be warned that your keystrokes might be loggued (by apache or
-   any proxy). I usually enable it after the login.
-
- * Ajaxterm commandline usage:
-
-{{{
-usage: ajaxterm.py [options]
-
-options:
-  -h, --help            show this help message and exit
-  -pPORT, --port=PORT   Set the TCP port (default: 8022)
-  -cCMD, --command=CMD  set the command (default: /bin/login or ssh localhost)
-  -l, --log             log requests to stderr (default: quiet mode)
-  -d, --daemon          run as daemon in the background
-  -PPIDFILE, --pidfile=PIDFILE
-                        set the pidfile (default: /var/run/ajaxterm.pid)
-  -iINDEX_FILE, --index=INDEX_FILE
-                        default index file (default: ajaxterm.html)
-  -uUID, --uid=UID      Set the daemon's user id
-}}}
-
- * Ajaxterm was first written as a demo for qweb (my web framework), but
-   actually doesn't use many features of qweb.
-
- * Compared to anyterm:
-   * There are no partial updates, ajaxterm updates either all the screen or
-     nothing. That make the code simpler and I also think it's faster. HTTP
-     replies are always gzencoded. When used in 80x25 mode, almost all of
-     them are below the 1500 bytes (size of an ethernet frame) and we just
-     replace the screen with the reply (no javascript string handling).
-   * Ajaxterm polls the server for updates with an exponentially growing
-     timeout when the screen hasn't changed. The timeout is also resetted as
-     soon as a key is pressed. Anyterm blocks on a pending request and use a
-     parallel connection for keypresses. The anyterm approch is better
-     when there aren't any keypress.
-
- * Ajaxterm files are released in the Public Domain, (except [http://sarissa.sourceforge.net/doc/ sarissa*] which are LGPL).
-
-== TODO ==
-
- * insert mode ESC [ 4 h
- * change size x,y from gui (sending signal)
- * vt102 graphic codepage
- * use innerHTML or prototype instead of sarissa
-
+= [http://antony.lesuisse.org/qweb/trac/wiki/AjaxTerm Ajaxterm] =
+
+Ajaxterm is a web based terminal. It was totally inspired and works almost
+exactly like http://anyterm.org/ except it's much easier to install (see
+comparaison with anyterm below).
+
+Ajaxterm written in python (and some AJAX javascript for client side) and depends only on python2.3 or better.[[BR]]
+Ajaxterm is '''very simple to install''' on Linux, MacOS X, FreeBSD, Solaris, cygwin and any Unix that runs python2.3.[[BR]]
+Ajaxterm was written by Antony Lesuisse (email: al AT udev.org), License Public Domain.
+
+Use the [/qweb/forum/viewforum.php?id=2 Forum], if you have any question or remark.
+
+== News ==
+
+ * 2006-10-29: v0.10 allow space in login, cgi launch fix, redhat init
+ * 2006-07-12: v0.9 change uid, daemon fix (Daniel Fischer)
+ * 2006-07-04: v0.8 add login support to ssh (Sven Geggus), change max width to 256
+ * 2006-05-31: v0.7 minor fixes, daemon option
+ * 2006-05-23: v0.6 Applied debian and gentoo patches, renamed to Ajaxterm, default port 8022
+
+== Download and Install ==
+
+ * Release: [/qweb/files/Ajaxterm-0.10.tar.gz Ajaxterm-0.10.tar.gz]
+ * Browse src: [/qweb/trac/browser/trunk/ajaxterm/ ajaxterm/]
+
+To install Ajaxterm issue the following commands:
+{{{
+wget http://antony.lesuisse.org/qweb/files/Ajaxterm-0.10.tar.gz
+tar zxvf Ajaxterm-0.10.tar.gz
+cd Ajaxterm-0.10
+./ajaxterm.py
+}}}
+Then point your browser to this URL : http://localhost:8022/
+
+== Screenshot ==
+
+{{{
+#!html
+<center><img src="/qweb/trac/attachment/wiki/AjaxTerm/scr.png?format=raw" alt="ajaxterm screenshot" style=""/></center>
+}}}
+
+== Documentation and Caveats ==
+
+ * Ajaxterm only support utf8.
+
+ * If run as root ajaxterm will run /bin/login, otherwise it will run ssh
+   localhost. To use an other command use the -c option.
+
+ * By default Ajaxterm only listen at 127.0.0.1:8022. For remote access, it is
+   strongly recommended to use '''https SSL/TLS''', and that is simple to
+   configure if you use the apache web server using mod_proxy.[[BR]][[BR]]
+   Using ssl will also speed up ajaxterm (probably because of keepalive).[[BR]][[BR]]
+   Here is an configuration example:
+
+{{{
+    Listen 443
+    NameVirtualHost *:443
+
+    <VirtualHost *:443>
+       ServerName localhost
+       SSLEngine On
+       SSLCertificateKeyFile ssl/apache.pem
+       SSLCertificateFile ssl/apache.pem
+
+       ProxyRequests Off
+       <Proxy *>
+               Order deny,allow
+               Allow from all
+       </Proxy>
+       ProxyPass /ajaxterm/ http://localhost:8022/
+       ProxyPassReverse /ajaxterm/ http://localhost:8022/
+    </VirtualHost>
+}}}
+
+ * Using GET HTTP request seems to speed up ajaxterm, just click on GET in the
+   interface, but be warned that your keystrokes might be loggued (by apache or
+   any proxy). I usually enable it after the login.
+
+ * Ajaxterm commandline usage:
+
+{{{
+usage: ajaxterm.py [options]
+
+options:
+  -h, --help            show this help message and exit
+  -pPORT, --port=PORT   Set the TCP port (default: 8022)
+  -cCMD, --command=CMD  set the command (default: /bin/login or ssh localhost)
+  -l, --log             log requests to stderr (default: quiet mode)
+  -d, --daemon          run as daemon in the background
+  -PPIDFILE, --pidfile=PIDFILE
+                        set the pidfile (default: /var/run/ajaxterm.pid)
+  -iINDEX_FILE, --index=INDEX_FILE
+                        default index file (default: ajaxterm.html)
+  -uUID, --uid=UID      Set the daemon's user id
+}}}
+
+ * Ajaxterm was first written as a demo for qweb (my web framework), but
+   actually doesn't use many features of qweb.
+
+ * Compared to anyterm:
+   * There are no partial updates, ajaxterm updates either all the screen or
+     nothing. That make the code simpler and I also think it's faster. HTTP
+     replies are always gzencoded. When used in 80x25 mode, almost all of
+     them are below the 1500 bytes (size of an ethernet frame) and we just
+     replace the screen with the reply (no javascript string handling).
+   * Ajaxterm polls the server for updates with an exponentially growing
+     timeout when the screen hasn't changed. The timeout is also resetted as
+     soon as a key is pressed. Anyterm blocks on a pending request and use a
+     parallel connection for keypresses. The anyterm approch is better
+     when there aren't any keypress.
+
+ * Ajaxterm files are released in the Public Domain, (except [http://sarissa.sourceforge.net/doc/ sarissa*] which are LGPL).
+
+== TODO ==
+
+ * insert mode ESC [ 4 h
+ * change size x,y from gui (sending signal)
+ * vt102 graphic codepage
+ * use innerHTML or prototype instead of sarissa
+
diff --git a/ajaxterm.1 b/ajaxterm.1
index 8d0a942..29d8250 100644
--- a/ajaxterm.1
+++ b/ajaxterm.1
@@ -20,6 +20,8 @@ A summary of the options supported by \fBajaxterm\fR is included below.
 .SH AUTHOR
 Antony Lesuisse <al@udev.org>
 
+Adopted to UTF-8 by Sergej Pupykin <ps@lx-ltd.ru>
+
 This manual page was written for the Debian system by
 Julien Valroff <julien@kirya.net> (but may be used by others).
 
diff --git a/ajaxterm.html b/ajaxterm.html
index 095e7d6..2cc48ef 100644
--- a/ajaxterm.html
+++ b/ajaxterm.html
@@ -8,6 +8,7 @@
 	<script type="text/javascript" src="sarissa_dhtml.js"></script>
 	<script type="text/javascript" src="ajaxterm.js"></script>
 	<script type="text/javascript" src="ajaxterm_config.js"></script>
+	<script type="text/javascript" src="utf8-escape.js"></script>
 	<script type="text/javascript">
 	window.onload=function() {
 		t=ajaxterm.Terminal("term",width,height);
diff --git a/ajaxterm.js b/ajaxterm.js
index 2579a8f..b976a96 100644
--- a/ajaxterm.js
+++ b/ajaxterm.js
@@ -142,7 +142,16 @@ ajaxterm.Terminal_ctor=function(id,width,height) {
 				if (r.readyState==4) {
 					if(r.status==200) {
 						window.clearTimeout(error_timeout);
-						de=r.responseXML.documentElement;
+						if(ie)
+						{
+						    var responseXMLdoc = new ActiveXObject("Microsoft.XMLDOM");
+						    responseXMLdoc.loadXML(r.responseText);
+						    de = responseXMLdoc.documentElement;
+						}
+						else
+						{
+						    de=r.responseXML.documentElement;
+						}
 						if(de.tagName=="pre") {
 							if(ie) {
 								Sarissa.updateContentFromNode(de, dterm);
@@ -250,7 +259,7 @@ ajaxterm.Terminal_ctor=function(id,width,height) {
 			if(k=="+") {
 				queue("%2B");
 			} else {
-				queue(escape(k));
+				queue(utf8Escape(k));
 			}
 		}
 		ev.cancelBubble=true;
diff --git a/ajaxterm.py b/ajaxterm.py
index 8695590..92bf67e 100755
--- a/ajaxterm.py
+++ b/ajaxterm.py
@@ -21,7 +21,9 @@ os.chdir(os.path.normpath(os.path.dirname(__file__)))
 # Optional: Add QWeb in sys path
 sys.path[0:0]=glob.glob('../../python')
 
-import qweb
+import qweb, codecs
+utf8decoder = codecs.getincrementaldecoder('utf8')()
+
 from socket import gethostname
 
 
@@ -92,31 +94,14 @@ class Terminal:
 		for i in [i[4] for i in dir(self) if i.startswith('csi_') and len(i)==5]:
 			if not self.csi_seq.has_key(i):
 				self.csi_seq[i]=(getattr(self,'csi_'+i),[1])
-		# Init 0-256 to latin1 and html translation table
-		self.trl1=""
-		for i in range(256):
-			if i<32:
-				self.trl1+=" "
-			elif i<127 or i>160:
-				self.trl1+=chr(i)
-			else:
-				self.trl1+="?"
-		self.trhtml=""
-		for i in range(256):
-			if i==0x0a or (i>32 and i<127) or i>160:
-				self.trhtml+=chr(i)
-			elif i<=32:
-				self.trhtml+="\xa0"
-			else:
-				self.trhtml+="?"
-	def reset(self,s=""):
-		self.scr=array.array('i',[0x000700]*(self.width*self.height))
+	def reset(self,s=u""):
+		self.scr=array.array('l',[0x07000000]*(self.width*self.height))
 		self.st=0
 		self.sb=self.height-1
 		self.cx_bak=self.cx=0
 		self.cy_bak=self.cy=0
 		self.cl=0
-		self.sgr=0x000700
+		self.sgr=0x07000000
 		self.buf=""
 		self.outbuf=""
 		self.last_html=""
@@ -127,7 +112,7 @@ class Terminal:
 		self.scr[pos:pos+len(s)]=s
 	def zero(self,y1,x1,y2,x2):
 		w=self.width*(y2-y1)+x2-x1+1
-		z=array.array('i',[0x000700]*w)
+		z=array.array('l',[0x07000000]*w)
 		self.scr[self.width*y1+x1:self.width*y2+x2+1]=z
 	def scroll_up(self,y1,y2):
 		self.poke(y1,0,self.peek(y1+1,0,y2,self.width))
@@ -280,17 +265,17 @@ class Terminal:
 	def csi_m(self,l):
 		for i in l:
 			if i==0 or i==39 or i==49 or i==27:
-				self.sgr=0x000700
+				self.sgr=0x07000000
 			elif i==1:
-				self.sgr=(self.sgr|0x000800)
+				self.sgr=(self.sgr|0x08000000)
 			elif i==7:
-				self.sgr=0x070000
+				self.sgr=0x70000000
 			elif i>=30 and i<=37:
 				c=i-30
-				self.sgr=(self.sgr&0xff08ff)|(c<<8)
+				self.sgr=(self.sgr&0xf8ffffff)|(c<<24)
 			elif i>=40 and i<=47:
 				c=i-40
-				self.sgr=(self.sgr&0x00ffff)|(c<<16)
+				self.sgr=(self.sgr&0x0fffffff)|(c<<28)
 #			else:
 #				print "CSI sgr ignore",l,i
 #		print 'sgr: %r %x'%(l,self.sgr)
@@ -320,12 +305,12 @@ class Terminal:
 					break
 #		if self.buf=='': print "ESC %r\n"%e
 	def write(self,s):
-		for i in s:
+		for i in utf8decoder.decode(s):
 			if len(self.buf) or (i in self.esc_seq):
-				self.buf+=i
+				self.buf+=chr(ord(i)&255)
 				self.escape()
 			elif i == '\x1b':
-				self.buf+=i
+				self.buf+=chr(ord(i)&255)
 			else:
 				self.echo(i)
 	def read(self):
@@ -333,35 +318,41 @@ class Terminal:
 		self.outbuf=""
 		return b
 	def dump(self):
-		r=''
+		r=u''
 		for i in self.scr:
-			r+=chr(i&255)
+			r+=unichr(i&0xFFFFFF)
 		return r
-	def dumplatin1(self):
-		return self.dump().translate(self.trl1)
+	def dumputf8(self):
+		return self.dump().encode('utf8')
 	def dumphtml(self,color=1):
 		h=self.height
 		w=self.width
 		r=""
-		span=""
+		span=u""
 		span_bg,span_fg=-1,-1
 		for i in range(h*w):
-			q,c=divmod(self.scr[i],256)
+			q,c=divmod(self.scr[i],256*256*256)
 			if color:
-				bg,fg=divmod(q,256)
+				bg,fg=divmod(q,16)
+				bg &= 0x7
 			else:
 				bg,fg=0,7
 			if i==self.cy*w+self.cx:
 				bg,fg=1,7
 			if (bg!=span_bg or fg!=span_fg or i==h*w-1):
 				if len(span):
-					r+='<span class="f%d b%d">%s</span>'%(span_fg,span_bg,cgi.escape(span.translate(self.trhtml)))
-				span=""
+					r+='<span class="f%d b%d">%s</span>'%(span_fg,span_bg,cgi.escape(span.replace(u' ',u'\xa0').encode('utf8')))
+				span=u""
 				span_bg,span_fg=bg,fg
-			span+=chr(c)
+			if c == 0:
+				span+=u' '
+			elif c > 0x10000:
+				span+=u'?'
+			else:
+				span+=unichr(c&0xFFFF)
 			if i%w==w-1:
-				span+='\n'
-		r='<?xml version="1.0" encoding="ISO-8859-1"?><pre class="term">%s</pre>'%r
+				span+=u'\n'
+		r='<?xml version="1.0" encoding="utf8"?><pre class="term">%s</pre>'%r
 		if self.last_html==r:
 			return '<?xml version="1.0"?><idem></idem>'
 		else:
@@ -369,8 +360,8 @@ class Terminal:
 #			print self
 			return r
 	def __repr__(self):
-		d=self.dumplatin1()
-		r=""
+		d=self.dumputf8()
+		r=u""
 		for i in range(self.height):
 			r+="|%s|\n"%d[self.width*i:self.width*(i+1)]
 		return r
@@ -432,7 +423,7 @@ class Multiplex:
 			elif os.getuid()==0:
 				cmd=['/bin/login']
 			else:
-				sys.stdout.write(gethostname() + " login: ")
+				sys.stdout.write(gethostname() + u" login: ")
 				login=sys.stdin.readline().strip()
 				if re.match('^[0-9A-Za-z-_. ]+$',login):
 					cmd=['ssh']
diff --git a/configure.makefile b/configure.makefile
index a30dc23..c866804 100644
--- a/configure.makefile
+++ b/configure.makefile
@@ -5,7 +5,7 @@ install:
 	install -d "%(bin)s"
 	install -d "%(lib)s"
 	install ajaxterm.bin "%(bin)s/ajaxterm"
-	install -m 644 ajaxterm.css ajaxterm.html ajaxterm.js qweb.py sarissa.js sarissa_dhtml.js "%(lib)s"
+	install -m 644 ajaxterm.css ajaxterm.html ajaxterm.js qweb.py sarissa.js sarissa_dhtml.js utf8-escape.js "%(lib)s"
 	install -m 644 ajaxterm.conf "%(etc)s"
 	install -m 755 ajaxterm.py "%(lib)s"
 	ln -s /etc/ajaxterm.conf "%(lib)s"/ajaxterm_config.js
diff --git a/utf8-escape.js b/utf8-escape.js
new file mode 100644
index 0000000..dfb8cb3
--- /dev/null
+++ b/utf8-escape.js
@@ -0,0 +1,80 @@
+var char2hex = new Array(
+    "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",
+    "%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",
+    "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",
+    "%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",
+    "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
+    "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",
+    "%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",
+    "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",
+    "%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",
+    "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",
+    "%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",
+    "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",
+    "%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",
+    "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",
+    "%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",
+    "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",
+    "%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",
+    "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",
+    "%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",
+    "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
+    "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",
+    "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",
+    "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",
+    "%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",
+    "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",
+    "%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",
+    "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",
+    "%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",
+    "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",
+    "%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",
+    "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
+    "%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"
+  );
+
+function utf8Escape(s)
+{
+  var sbuf = "";
+  var i;
+
+  var len = s.length;
+  for (i = 0; i < len; i++)
+  {
+    var ch = s.charCodeAt(i);
+    if( (65 <= ch && ch <= 90) ||
+        (97 <= ch && ch <= 122) ||
+        (48 <= ch && ch <= 57) )
+    {
+      sbuf += String.fromCharCode(ch);
+    }
+    else if (ch == 32)
+    {
+      sbuf += '+';
+    }
+    else if (ch == 45 || ch == 95
+             || ch == 46 || ch == 33
+             || ch == 126 || ch == 42
+             || ch == 39 || ch == 40
+             || ch == 41)
+    {
+      sbuf += char2hex[ch];
+    }
+    else if (ch <= 0x007F)
+    {
+      sbuf += char2hex[ch];
+    }
+    else if (ch <= 0x07FF)
+    {
+       sbuf += char2hex[0xc0 | (ch >> 6)];
+       sbuf += char2hex[0x80 | (ch & 0x3F)];
+    }
+    else
+    {
+       sbuf += char2hex[0xe0 | (ch >> 12)];
+       sbuf += char2hex[0x80 | ((ch >> 6) & 0x3F)];
+       sbuf += char2hex[0x80 | (ch & 0x3F)];
+    }
+  }
+  return sbuf;
+}
-- 
1.7.3.1