dddaf654b215bb7f8dc322e52af30da1ec394a0d
[mir.git] / source / mir / misc / StringUtil.java
1 /*
2  * put your module comment here
3  */
4
5
6 package  mir.misc;
7
8 import  java.io.*;
9 import  java.lang.*;
10 import  java.util.*;
11 import  gnu.regexp.*;
12
13 /**
14  * Statische Hilfsmethoden zur Stringbehandlung
15  *
16  * @version 29.6.99
17  * @author RK
18  */
19 public final class StringUtil {
20
21   /**
22    * Wandelt Datum in einen 8-ziffrigen String um (yyyymmdd)
23    * @param theDate
24    * @return 8-ziffriger String (yyyymmdd)
25    */
26
27   public static final String date2webdbDate (GregorianCalendar theDate) {
28     StringBuffer webdbDate = new StringBuffer();
29     webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
30     webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
31     webdbDate.append(pad2(theDate.get(Calendar.DATE)));
32     return  webdbDate.toString();
33   }
34
35   /**
36    * Wandelt Calendar in einen 12-ziffrigen String um (yyyymmddhhmm)
37    * @param theDate
38    * @return 12-ziffriger String (yyyymmdd)
39    */
40
41   public static final String date2webdbDateTime (GregorianCalendar theDate) {
42     StringBuffer webdbDate = new StringBuffer();
43     webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
44     webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
45     webdbDate.append(pad2(theDate.get(Calendar.DATE)));
46     webdbDate.append(pad2(theDate.get(Calendar.HOUR)));
47     webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
48     return  webdbDate.toString();
49   }
50
51   /**
52    * wandelt Calendar in dd.mm.yyyy / hh.mm um
53    * @param theDate
54    * @return String mit (dd.mm.yyyy / hh.mm um)
55    */
56   public static String date2readableDateTime (GregorianCalendar theDate) {
57     String readable = "";
58     int hour;
59     readable += pad2(theDate.get(Calendar.DATE));
60     readable += "." + pad2(theDate.get(Calendar.MONTH) + 1);
61     readable += "." + String.valueOf(theDate.get(Calendar.YEAR));
62     hour = theDate.get(Calendar.HOUR);
63     if (theDate.get(Calendar.AM_PM) == Calendar.PM)
64       hour += 12;
65     readable += " / " + pad2(hour);
66     readable += ":" + pad2(theDate.get(Calendar.MINUTE));
67     return  readable;
68   }
69
70   /**
71    * wandelt eine Datum in einen 8-buchstabigen String, der durch <code>/</code>
72    * getrennt ist.
73    *
74    * @param webdbDate
75    * @return String mit <code>/yyyy/mm/dd</code>
76    */
77   public static final String webdbDate2path (String webdbDate) {
78     StringBuffer path = new StringBuffer();
79     path.append("/").append(webdbDate.substring(0, 4));
80     path.append("/").append(webdbDate.substring(4, 6));
81     path.append("/");
82     //who did this?
83     //path.append("/").append(webdbDate.substring(6, 8));
84     return  path.toString();
85   }
86
87   /**
88    * wandelt Calendar in dd.mm.yyyy um
89    *
90    * @param theDate
91    * @return String mit  <code>dd.mm.yyyy</code>
92    */
93   public static final String webdbDate2readableDate (String webdbDate) {
94     String date = "";
95     date += webdbDate.substring(6, 8);
96     date += "." + webdbDate.substring(4, 6);
97     date += "." + webdbDate.substring(0, 4);
98     return  date;
99   }
100
101
102   /**
103    * converts string from format: yyyy-mm-dd__hh:mm:ss.d
104    * to dd.mm.yyyy hh:mm
105    */
106   public static String dateToReadableDate(String date) {
107     StringBuffer returnDate = new StringBuffer();
108     if (date!=null) {
109
110       returnDate.append(date.substring(8,10)).append('.');
111       returnDate.append(date.substring(5,7)).append('.');
112       returnDate.append(date.substring(0,4)).append(' ');
113       returnDate.append(date.substring(11,16));
114     }
115     return returnDate.toString();
116   }
117
118   /**
119    * converts string from format: yyyy-mm-dd__hh:mm:ss.d
120    * to yyyy
121    */
122   public static String dateToYear (String date) {
123     StringBuffer returnDate = new StringBuffer();
124     if (date!=null) {
125
126       returnDate.append(date.substring(0,4));
127     }
128     return returnDate.toString();
129   }
130
131   /**
132    * converts string from format: yyyy-mm-dd__hh:mm:ss.d
133    * to [m]m
134    */
135   public static String dateToMonth (String date) {
136     StringBuffer returnDate = new StringBuffer();
137     if (date!=null) {
138                   if (!date.substring(5,6).equalsIgnoreCase("0")) returnDate.append(date.substring(5,7));
139       else returnDate.append(date.substring(6,7));
140     }
141     return returnDate.toString();
142   }
143
144   /**
145    * converts string from format: yyyy-mm-dd__hh:mm:ss.d
146    * to [d]d
147    */
148   public static String dateToDayOfMonth (String date) {
149     StringBuffer returnDate = new StringBuffer();
150     if (date!=null) {
151                   if (!date.substring(8,9).equalsIgnoreCase("0")) returnDate.append(date.substring(8,10));
152       else returnDate.append(date.substring(9,10));
153     }
154     return returnDate.toString();
155   }
156
157   /**
158    * converts string from format: yyyy-mm-dd__hh:mm:ss.d
159    * to hh:mm
160    */
161   public static String dateToTime (String date) {
162     StringBuffer returnDate = new StringBuffer();
163     if (date!=null) {
164       returnDate.append(date.substring(11,16));
165     }
166     return returnDate.toString();
167   }
168
169
170   /**
171    * schließt einen String in Anführungsszeichen ein, falls er Leerzeichen o.ä. enthält
172    *
173    * @return gequoteter String
174    */
175    public static String quoteIfNecessary(String s) {
176     for (int i = 0; i < s.length(); i++)
177       if (!(Character.isLetterOrDigit(s.charAt(i)) || s.charAt(i) == '.'))
178         return quote(s, '"');
179     return s;
180   }
181
182    /**
183    * schließt <code>s</code> in <code>'</code> ein und setzt Backslashes vor
184    * "gefährliche" Zeichen innerhalb des Strings
185    * Quotes special SQL-characters in <code>s</code>
186    *
187    * @return geqoteter String
188    */
189   public static String quote(String s)
190   {
191     //String s2 = quote(s, '\'');
192
193     //Quickhack
194     //Because of '?-Bug in Postgresql-JDBC-Driver
195     StringBuffer temp = new StringBuffer();
196     for(int i=0;i<s.length();i++){
197       if(s.charAt(i)=='\''){
198         temp.append("&acute;");
199       } else {
200         temp.append(s.charAt(i));
201       }
202     }
203     String s2 = temp.toString();
204     //Quickhack end
205
206     s2 = quote(s2, '\"');
207     return s2;
208   }
209
210   /**
211    * schließt <code>s</code> in <code>'</code> ein und setzt Backslashes vor
212    * "gefährliche" Zeichen innerhalb des Strings
213    *
214    * @param s String, der gequoted werden soll
215    * @param quoteChar zu quotendes Zeichen
216    * @return gequoteter String
217    */
218   public static String quote(String s, char quoteChar)
219   {
220     StringBuffer buf = new StringBuffer(s.length());
221     int pos = 0;
222     while (pos < s.length()) {
223       int i = s.indexOf(quoteChar, pos);
224       if (i < 0) i = s.length();
225       buf.append(s.substring(pos, i));
226       pos = i;
227       if (pos < s.length()) {
228         buf.append('\\');
229         buf.append(quoteChar);
230         pos++;
231       }
232     }
233     return buf.toString();
234   }
235
236   /**
237    * replaces dangerous characters in <code>s</code>
238    *
239    */
240
241   public static String unquote(String s)
242   {
243     char quoteChar='\'';
244     StringBuffer buf = new StringBuffer(s.length());
245     int pos = 0;
246     String searchString = "\\"+quoteChar;
247     while (pos < s.length()) {
248       int i = s.indexOf(searchString, pos);
249       if (i < 0) i = s.length();
250       buf.append(s.substring(pos, i));
251       pos = i+1;
252     }
253     return buf.toString();
254   }
255
256   /**
257    * Wandelet String in byte[] um.
258    * @param s
259    * @return byte[] des String
260    */
261
262   public static byte[] stringToBytes(String s) {
263     String crlf = System.getProperty("line.separator");
264     if (!crlf.equals("\n"))
265       s = replace(s, "\n", crlf);
266     // byte[] buf = new byte[s.length()];
267     byte[] buf = s.getBytes();
268     return buf;
269   }
270
271     /**
272    * Ersetzt in String <code>s</code> das <code>pattern</code> durch <code>substitute</code>
273    * @param s
274    * @param pattern
275    * @param substitute
276    * @return String mit den Ersetzungen
277    */
278   public static String replace(String s, String pattern, String substitute) {
279     int i = 0, pLen = pattern.length(), sLen = substitute.length();
280     StringBuffer buf = new StringBuffer(s.length());
281     while (true) {
282       int j = s.indexOf(pattern, i);
283       if (j < 0) {
284         buf.append(s.substring(i));
285         break;
286       } else {
287         buf.append(s.substring(i, j));
288         buf.append(substitute);
289         i = j+pLen;
290       }
291     }
292     return buf.toString();
293   }
294
295   /**
296    * Ersetzt in String <code>s</code> das Regexp <code>pattern</code> durch <code>substitute</code>
297    * @param s
298    * @param pattern
299    * @param substitute
300    * @return String mit den Ersetzungen
301    */
302   public static String regexpReplace(String haystack, String pattern, String substitute) {
303     try {
304       RE regex = new RE(pattern);
305       return regex.substituteAll(haystack,substitute);
306     } catch(REException ex){
307       return null;
308     }
309   }
310
311
312
313
314   /**
315    * Fügt einen Separator an den Pfad an
316    * @param path
317    * @return Pfad mit Separator am Ende
318    */
319   public static final String addSeparator (String path) {
320     return  path.length() == 0 || path.endsWith(File.separator) ? path : path
321         + File.separatorChar;
322   }
323
324   /**
325    * Fügt ein <code>/</code> ans ende des Strings and
326    * @param path
327    * @return Pfad mit <code>/</code> am Ende
328    */
329   public static final String addSlash (String path) {
330     return  path.length() == 0 || path.endsWith("/") ? path : path + '/';
331   }
332
333   /**
334    * Löscht <code>/</code> am Ende des Strings, falls vorhanden
335    * @param path
336    * @return String ohne <code>/</code> am Ende
337    */
338   public static final String removeSlash (String path) {
339     return  path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length()
340         - 1) : path;
341   }
342
343   /**
344    * Checks to see if the path is absolute by looking for a leading file
345    * separater
346    * @todo deal with windows drive letters.
347    * @param path
348    * @return
349    */
350   public static boolean isAbsolutePath (String path) {
351     return  path.startsWith(File.separator);
352   }
353
354   /**
355    * Löscht Slash am Anfang des Strings
356    * @param path
357    * @return
358    */
359   public static String removeFirstSlash (String path) {
360     return  path.startsWith("/") ? path.substring(1) : path;
361   }
362
363   /**
364    * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
365    * @return zwistellige Zahl
366    */
367   public static String pad2 (int number) {
368     return  number < 10 ? "0" + number : String.valueOf(number);
369   }
370
371   /**
372    * formatiert eine Zahl (0-999) dreistellig (z.B. 7 -> 007)
373    *
374    * @return 3-stellige Zahl
375    */
376   public static String pad3 (int number) {
377     return  number < 10 ? "00" + number : number < 100 ? "0" + number : String.valueOf(number);
378   }
379
380   /**
381    * Konvertiert Unix-Linefeeds in Win-Linefeeds
382    * @param s
383    * @return Konvertierter String
384    */
385   public static String unixLineFeedsToWin(String s) {
386     int i = -1;
387     while (true) {
388       i = s.indexOf('\n', i+1);
389       if (i < 0) break;
390       if ((i == 0 || s.charAt(i-1) != '\r') &&
391         (i == s.length()-1 || s.charAt(i+1) != '\r')) {
392         s = s.substring(0, i)+'\r'+s.substring(i);
393         i++;
394       }
395     }
396     return s;
397   }
398
399
400   /**
401    * verwandelt einen String in eine gültige Url, konvertiert Sonderzeichen
402    * und Spaces werden zu Underscores
403    *
404    * @return gültige Url
405    */
406   public static String convert2url(String s) {
407     s = toLowerCase(s);
408     StringBuffer buf = new StringBuffer();
409     for(int i = 0; i < s.length(); i++ ) {
410         switch( s.charAt( i ) ) {
411         case 'ö':
412       buf.append( "oe" ); break;
413         case 'ä':
414       buf.append( "ae" ); break;
415         case 'ü':
416       buf.append( "ue" ); break;
417         case 'ã':
418       buf.append( "a" ); break;
419         case '´':
420         case '.':
421       buf.append( "_" ); break;
422         case ' ':
423       if( buf.charAt( buf.length() - 1 ) != '_' ) {
424           buf.append( "_" );
425       }
426       break;
427         default:
428       buf.append( s.charAt( i ) );
429         }
430     }
431     return buf.toString();
432   }
433
434   /**
435    * wandelt Sonderzeichen in Quotes um
436    *
437    * @return Kovertierter String
438    */
439   public static String encodeHtml(String s) {
440     StringBuffer buf = new StringBuffer();
441     for(int i=0;i < s.length(); i++ ) {
442
443       /** @todo looks inefficient */
444       if (s.charAt(i)=='&') {
445         // convert html to xml-parsable representation
446         if( s.indexOf( "&ouml;", i ) == i ) {
447           buf.append( "&#246;" ); i += 5;
448           continue;
449         }
450         if( s.indexOf( "&auml;", i ) == i ) {
451           buf.append( "&#228;" ); i += 5;
452           continue;
453         }
454         if( s.indexOf( "&uuml;", i ) == i ) {
455           buf.append( "&#252;" ); i += 5;
456           continue;
457         }
458         if( s.indexOf( "&Ouml;", i ) == i ) {
459           buf.append( "&#214;" ); i += 5;
460           continue;
461         }
462         if( s.indexOf( "&Auml;", i ) == i ) {
463           buf.append( "&#196;" ); i += 5;
464           continue;
465         }
466         if( s.indexOf( "&Uuml;", i ) == i ) {
467           buf.append( "&#220;" ); i += 5;
468           continue;
469         }
470         if( s.indexOf( "&szlig;", i ) == i ) {
471           buf.append( "&#223;" ); i += 6;
472           continue;
473         }
474
475         /** @todo should only escape outside of tags */
476
477         if( s.indexOf( "&quot;", i ) == i ) {
478           buf.append( "&#223;" ); i += 5;
479           continue;
480         }
481         if( s.indexOf( "&ndash;", i ) == i ) {
482           buf.append( "&#8211;" ); i += 6;
483           continue;
484         }
485         if( s.indexOf( "&mdash;", i ) == i ) {
486           buf.append( "&#8212;" ); i += 6;
487           continue;
488         }
489         if( s.indexOf( "&ldquo;", i ) == i ) {
490           buf.append( "&#8220;" ); i += 6;
491           continue;
492         }
493         if( s.indexOf( "&rdquo;", i ) == i ) {
494           buf.append( "&#8221;" ); i += 6;
495           continue;
496         }
497         if( s.indexOf( "&bdquo;", i ) == i ) {
498           buf.append( "&#8222;" ); i += 6;
499           continue;
500         }
501
502         //looks pretty stupid
503         if( s.indexOf( "&lt;", i ) == i ) {
504           buf.append( "&lt;" ); i += 3;
505           continue;
506         }
507         if( s.indexOf( "&gt;", i ) == i ) {
508           buf.append( "&gt;" ); i += 3;
509           continue;
510         }
511         if( s.indexOf( "&acute;", i ) == i ) {
512           buf.append( "&acute;" ); i += 6;
513           continue;
514         }
515         if( s.indexOf( "&nbsp;", i ) == i ) {
516           buf.append( "&nbsp;" ); i += 5;
517           continue;
518         }
519         //has to be the last
520         //if( s.indexOf( "&", i ) == i ) {
521         //  buf.append( "&#38;" ); i += 0;
522         //  continue;
523         //}
524       }
525       // convert umlauts an other special charakters
526       switch( s.charAt(i) ) {
527         case 'ö': buf.append( "&#246;" ); break;
528         case 'ä': buf.append( "&#228;" ); break;
529         case 'ü': buf.append( "&#252;" ); break;
530         case 'Ö': buf.append( "&#214;" ); break;
531         case 'Ä': buf.append( "&#196;" ); break;
532         case 'Ü': buf.append( "&#220;" ); break;
533         case 'ß': buf.append( "&#223;" ); break;
534         case 'é': buf.append( "&#233;" ); break;
535         case 'è': buf.append( "&#232;" ); break;
536         case 'á': buf.append( "&#225;" ); break;
537         case 'à': buf.append( "&#224;" ); break;
538         case 'â': buf.append( "&#226;" ); break;
539         case 'ã': buf.append( "&#227;" ); break;
540         case '¬': buf.append( "&#172;" ); break;
541         case '¹': buf.append( "&#185;" ); break;
542         case '²': buf.append( "&#178;" ); break;
543         case '³': buf.append( "&#179;" ); break;
544         case '¼': buf.append( "&#188;" ); break;
545         case '½': buf.append( "&#189;" ); break;
546         case '¾': buf.append( "&#190;" ); break;
547         case '¶': buf.append( "&#182;" ); break;
548         case 'æ': buf.append( "&#230;" ); break;
549         case 'ð': buf.append( "&#240;" ); break;
550         case '|': buf.append( "&#166;" ); break;
551         case '·': buf.append( "&#183;" ); break;
552         case '°': buf.append( "&#176;" ); break;
553         case '§': buf.append( "&#167;" ); break;
554         case 'ø': buf.append( "&#248;" ); break;
555         case 'ç': buf.append( "&#231;" ); break;
556         case '¤': buf.append( "&#164;" ); break;
557         case 'ª': buf.append( "&#170;" ); break;
558         case 'Ç': buf.append( "&#199;" ); break;
559         case 'Ã': buf.append( "&#195;" ); break;
560         case 'Â': buf.append( "&#194;" ); break;
561         case 'Æ': buf.append( "&#198;" ); break;
562         case '©': buf.append( "&#169;" ); break;
563         case '®': buf.append( "&#174;" ); break;
564         case '¥': buf.append( "&#165;" ); break;
565         case 'Þ': buf.append( "&#254;" ); break;
566         case '¯': buf.append( "&#175;" ); break;
567         case 'Ð': buf.append( "&#208;" ); break;
568         case 'º': buf.append( "&#186;" ); break;
569         case '¡': buf.append( "&#161;" ); break;
570         case '£': buf.append( "&#163;" ); break;
571         case '±': buf.append( "&#177;" ); break;
572         case '¿': buf.append( "&#191;" ); break;
573         case 'Ø': buf.append( "&#216;" ); break;
574         case 'Á': buf.append( "&#192;" ); break;
575         case 'À': buf.append( "&#193;" ); break;
576         case 'É': buf.append( "&#200;" ); break;
577         case 'È': buf.append( "&#201;" ); break;
578         case 'ù': buf.append( "&#250;" ); break;
579         case 'ñ': buf.append( "&#241;" ); break;
580         case 'Ñ': buf.append( "&#209;" ); break;
581         case 'µ': buf.append( "&#181;" ); break;
582         case 'Í': buf.append( "&#204;" ); break;
583         case 'Ì': buf.append( "&#205;" ); break;
584         case 'í': buf.append( "&#236;" ); break;
585         case 'ì': buf.append( "&#237;" ); break;
586         case 'î': buf.append( "&#238;" ); break;
587         case 'Î': buf.append( "&#206;" ); break;
588         case 'ó': buf.append( "&#243;" ); break;
589         case 'Ó': buf.append( "&#210;" ); break;
590         case 'ò': buf.append( "&#206;" ); break;
591         case 'Ò': buf.append( "&#211;" ); break;
592         case 'ô': buf.append( "&#244;" ); break;
593         case 'Ô': buf.append( "&#212;" ); break;
594         case 'õ': buf.append( "&#245;" ); break;
595         case 'Õ': buf.append( "&#213;" ); break;
596         case 'ý': buf.append( "&#253;" ); break;
597         case 'Ý': buf.append( "&#221;" ); break;
598         case 'û': buf.append( "&#251;" ); break;
599         case 'Û': buf.append( "&#219;" ); break;
600         case 'ú': buf.append( "&#249;" ); break;
601         case 'Ú': buf.append( "&#217;" ); break;
602         case 'Ù': buf.append( "&#218;" ); break;
603         case 'Ê': buf.append( "&#202;" ); break;
604         case 'ê': buf.append( "&#234;" ); break;
605         case 'å': buf.append( "&#229;" ); break;
606         case 'Å': buf.append( "&#197;" ); break;
607         case 'ë': buf.append( "&#235;" ); break;
608         case 'Ë': buf.append( "&#203;" ); break;
609         case 'ÿ': buf.append( "&#255;" ); break;
610         case 'ï': buf.append( "&#239;" ); break;
611         case 'Ï': buf.append( "&#207;" ); break;
612         case '«': buf.append( "&#171;" ); break;
613         case '»': buf.append( "&#187;" ); break;
614         case '\'': buf.append( "&acute;" ); break;
615         case '\"': buf.append( "&quot;" ); break;
616         //case '\u8211': buf.append( "&#8211;" ); break;
617         //case '\u8212': buf.append( "&#8212;" ); break;
618         //case '\u8220': buf.append( "&#8220;" ); break;
619         //case '\u8221': buf.append( "&#8221;" ); break;
620         //case '\u8222': buf.append( "&#8222;" ); break;
621         //case '\"': buf.append( "&#34;" ); break;
622         default: buf.append( s.charAt(i) );
623       }
624
625     }
626     return buf.toString();
627   }
628
629
630   public static String decodeHTMLinTags(String s){
631     StringBuffer buffer = new StringBuffer();
632     boolean start = false;
633     boolean stop = false;
634     int startIndex = 0;
635     int stopIndex = 0;
636     int temp = 0;
637
638     for(int i=0;i<s.length();i++){
639       if(s.charAt(i)=='<'){
640         start = true;
641         startIndex = i;
642       } else if(s.charAt(i)=='>'){
643         stop = true;
644         stopIndex = i;
645
646         if(start && stop){
647           buffer.append(s.substring(temp,startIndex));
648           buffer.append(replaceQuot(s.substring(startIndex,stopIndex+1)));
649           i= temp= stopIndex+1;
650           start= stop= false;
651         }
652       }
653     }
654     if(stopIndex>0){
655       buffer.append(s.substring(stopIndex+1));
656       return buffer.toString();
657     } else {
658       return s;
659     }
660   }
661
662   public static String replaceQuot(String s) {
663     StringBuffer buffer = new StringBuffer();
664     for(int j = 0; j < s.length();j++){
665       if(s.charAt(j)=='&'){
666         if(s.indexOf( "&quot;",j) == j) {
667           buffer.append( "\"" );
668           j += 5;
669         }//if
670       } else {
671         buffer.append(s.charAt(j));
672       }//else
673     }//for
674     return buffer.toString();
675   }
676
677   /** wandelt Quotes in Sonderzeichen um
678    */
679   /**
680   public static String decodeHtml(String s) {
681     StringBuffer buf = new StringBuffer();
682     for(int i=0;i < s.length(); i++ ) {
683       if( s.indexOf( "&ouml;", i ) == i ) {
684         buf.append( "ö" ); i += 5;
685         continue;
686       }
687       if( s.indexOf( "&auml;", i ) == i ) {
688         buf.append( "ä" ); i += 5;
689         continue;
690       }
691       if( s.indexOf( "&uuml;", i ) == i ) {
692         buf.append( "ü" ); i += 5;
693         continue;
694       }
695       if( s.indexOf( "&Ouml;", i ) == i ) {
696         buf.append( "Ö" ); i += 5;
697         continue;
698       }
699       if( s.indexOf( "&Auml;", i ) == i ) {
700         buf.append( "Ä" ); i += 5;
701         continue;
702       }
703       if( s.indexOf( "&Uuml;", i ) == i ) {
704         buf.append( "Ü" ); i += 5;
705         continue;
706       }
707       if( s.indexOf( "&szlig;", i ) == i ) {
708         buf.append( "ß" ); i += 6;
709         continue;
710       }
711       if( s.indexOf( "&quot;", i ) == i ) {
712         buf.append( "\"" ); i += 5;
713         continue;
714       }
715       buf.append( s.charAt(i) );
716     }
717     return buf.toString();
718   }
719    */
720
721   /**
722    * schnellere Variante der String.toLowerCase()-Routine
723    *
724    * @return String in Kleinbuchsten
725    */
726   public static String toLowerCase(String s) {
727     int l = s.length();
728     char[] a = new char[l];
729     for (int i = 0; i < l; i++)
730       a[i] = Character.toLowerCase(s.charAt(i));
731     return new String(a);
732   }
733
734     /**
735    * Findet <code>element</code> im String-Array <code>array</code>
736    * @param array
737    * @param element
738    * @return Fundstelle als int oder -1
739    */
740   public static int indexOf(String[] array, String element) {
741     if (array != null)
742       for (int i = 0; i < array.length; i++)
743         if (array[i].equals(element))
744           return i;
745     return -1;
746   }
747
748   /**
749    * Testet auf Vorkommen von <code>element</code> in <code>array</code>
750    * @param array String-Array
751    * @param element
752    * @return true wenn <code>element</code> vorkommt, sonst false
753    */
754   public static boolean contains(String[] array, String element) {
755     return indexOf(array, element) >= 0;
756   }
757
758     /**
759    * Ermittelt CRC-Prüfsumme von String <code>s</code>
760    * @param s
761    * @return CRC-Prüfsumme
762    */
763   public static int getCRC(String s) {
764     int h = 0;
765     char val[] = s.toCharArray();
766     int len = val.length;
767
768     for (int i = 0 ; i < len; i++) {
769       h &= 0x7fffffff;
770       h = (((h >> 30) | (h << 1)) ^ (val[i]+i));
771     }
772
773     return (h << 8) | (len & 0xff);
774   }
775
776     /**
777    * Liefert Default-Wert def zurück, wenn String <code>s</code>
778    * kein Integer ist.
779    *
780    * @param s
781    * @param def
782    * @return geparster int aus s oder def
783    */
784   public static int parseInt(String s, int def) {
785     if (s == null) return def;
786     try {
787       return Integer.parseInt(s);
788     } catch (NumberFormatException e) {
789       return def;
790     }
791   }
792
793   /**
794    * Liefert Defaultwert def zurück, wenn s nicht zu einem float geparsed werden kann.
795    * @param s
796    * @param def
797    * @return geparster float oder def
798    */
799   public static float parseFloat(String s, float def) {
800     if (s == null) return def;
801     try {
802       return new Float(s).floatValue();
803     } catch (NumberFormatException e) {
804       return def;
805     }
806   }
807
808     /**
809    * Findet Ende eines Satzes in String <code>text</code>
810    * @param text
811    * @param startIndex
812    * @return index des Satzendes, oder -1
813    */
814   public static int findEndOfSentence(String text, int startIndex) {
815      while (true) {
816        int i = text.indexOf('.', startIndex);
817        if (i < 0) return -1;
818        if (i > 0 && !Character.isDigit(text.charAt(i-1)) &&
819           (i+1 >= text.length()
820           || text.charAt(i+1) == ' '
821           || text.charAt(i+1) == '\n'
822           || text.charAt(i+1) == '\t'))
823           return i+1;
824        startIndex = i+1;
825      }
826   }
827
828     /**
829    * Findet Wortende in String <code>text</code> ab <code>startIndex</code>
830    * @param text
831    * @param startIndex
832    * @return Index des Wortendes, oder -1
833    */
834   public static int findEndOfWord(String text, int startIndex) {
835     int i = text.indexOf(' ', startIndex),
836       j = text.indexOf('\n', startIndex);
837     if (i < 0) i = text.length();
838     if (j < 0) j = text.length();
839     return Math.min(i, j);
840   }
841
842    /**
843    * This routine makes html links (href) out of text browseable urls
844    * @param text
845    * @return Konvertierter String
846    */
847   public static String makeLinks(String text) {
848     int i = 0;
849     StringBuffer buf = new StringBuffer(text.length());
850     while (true) {
851       int j = text.indexOf("http://", i);
852       if (j < 0) {
853         buf.append(text.substring(i));
854         break;
855       } else {
856         buf.append(text.substring(i, j));
857         int k = findEndOfWord(text,j+7);
858         String url="";
859         if (k<0)  url = text.substring(j);
860         else    url = text.substring(j,k);
861
862         buf.append("<a href=\042"+url+"\042>"+url+"</a>");
863         //System.out.println("url mark: " + url);
864         i = j+url.length();
865       }
866     }
867     return buf.toString();
868
869   }
870
871
872   /**
873    *  convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
874    *  in den html-tag <p>
875    *  nur sinnvoll, wenn text nicht im html-format eingegeben
876    */
877   public static String convertNewline2P(String haystack) {
878     try {
879       RE regex = new RE("(<br>\r?\n<br>){1,}");
880       return regex.substituteAll(haystack,"\n</p><p>");
881     } catch(REException ex){
882       return null;
883     }
884   }
885
886   /**
887    *  convertNewline2Break ist eine regex-routine zum umwandeln von 1 newline (\n)
888    *  in den html-tag <br>
889    *  nur sinnvoll, wenn text nicht im html-format eingegeben
890    */
891   public static String convertNewline2Break(String haystack) {
892     try {
893       RE regex = new RE("(\r?\n){1}");
894       return regex.substituteAll(haystack,"$0<br>");
895     } catch(REException ex){
896       return null;
897     }
898   }
899
900   /**
901    *  createMailLinks wandelt text im email-adressenformat
902    *  in einen klickbaren link um
903    *  nur sinnvoll, wenn text nicht im html-format eingegeben
904    */
905   public static String createMailLinks(String haystack) {
906     try {
907       RE regex = new RE("([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+).([a-zA-Z0-9_.-]+)");
908       return regex.substituteAll(haystack,"<a href=\"mailto:$0\">$0</a>");
909     } catch(REException ex){
910       return null;
911     }
912   }
913
914
915   /**
916    *  createMailLinks wandelt text im email-adressenformat
917    *  in einen klickbaren link um
918    *  nur sinnvoll, wenn text nicht im html-format eingegeben
919    */
920   public static String createMailLinks(String haystack, String imageRoot, String mailImage) {
921     try {
922       RE regex = new RE("([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+).([a-zA-Z0-9_.-]+)");
923       return regex.substituteAll(haystack,"<img src=\""+imageRoot+"/"+mailImage+"\" border=\"0\"/>&#160;<a href=\"mailto:$0\">$0</a>");
924     } catch(REException ex){
925       return null;
926     }
927   }
928
929
930   /**
931    *  createURLLinks wandelt text im url-format
932    *  in einen klickbaren link um
933    *  nur sinnvoll, wenn text nicht im html-format eingegeben
934    */
935   public static String createURLLinks(String haystack) {
936     try {
937
938       //dieser Ausdruck brauch dringend fachliche Beratung
939       //RE regex = new RE("((https://)|(http://)|(ftp://))+([a-zA-Z0-9_-]+).([a-zA-Z0-9_:-]+)/([^ \t\r\n<>)]+[^ \t\r\n,<>])");
940       RE regex = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
941       return regex.substituteAll(haystack,"<a href=\"$0\">$0</a>");
942     } catch(REException ex){
943       return null;
944     }
945   }
946
947   /**
948    * this routine takes text in url format and makes
949    * a clickaeble "<href>" link removing any "illegal" html tags
950    * @param haystack, the url
951    * @param title, the href link text
952    * @param imagRoot, the place to find icons
953    * @param extImage, the url of the icon to show next to the link
954    * @return a String containing the url
955    */
956   public static String createURLLinks(String haystack, String title, String imageRoot,String extImage) {
957     try {
958       //dieser Ausdruck brauch dringend fachliche Beratung
959       RE regex = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
960
961       if (title == null) {
962         return regex.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">$0</a>");
963       } else {
964         title = removeHTMLTags(title);
965         return regex.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">"+title+"</a>");
966       }
967     } catch(REException ex){
968       return null;
969     }
970   }
971
972   /**
973    * this routine takes text in url format and makes
974    * a clickaeble "<href>" link removing any "illegal" html tags
975    * @param haystack, the url
976    * @param imageRoot, the place to find icons
977    * @param extImage, the url of the icon to show next to the link
978    * @param intImage, unused
979    * @return a String containing the url
980    */
981   public static String createURLLinks(String haystack, String title, String imageRoot,String extImage,String intImage) {
982     return createURLLinks(haystack, title, imageRoot, extImage);
983   }
984
985   /**
986    * this routine takes text in url format and makes
987    * an image link removing any "illegal" html tags
988    * @param haystack, the url
989    * @param title, the image alt text, can be null
990    * @param height, height of the image
991    * @param width, width of the image
992    * @return a String containing the url
993    */
994   public static String createIMGLinks(String haystack, String title, String height,String width) {
995     try {
996       //dieser Ausdruck brauch dringend fachliche Beratung
997       RE regex = new RE("((https://)|(http://)|(ftp://))+([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>]+[^ \t\r\n.,<>])");
998       if (title != null) {
999         title = removeHTMLTags(title);
1000         return regex.substituteAll(haystack,"<img hspace=\"10\" vspace=\"6\" align=\"left\" src=\"$0\" width=\""+width+"\" height=\""+height+"\" alt=\""+title+"\"/>&#160;<br><i>"+title+"</i>");
1001       } else {
1002         return regex.substituteAll(haystack,"<img hspace=\"10\" vspace=\"6\" align=\"left\" src=\"$0\" width=\""+width+"\" height=\""+height+"\" alt=\"\"/>&#160;");
1003       }
1004     } catch(REException ex){
1005       return null;
1006     }
1007   }
1008
1009
1010
1011    /**
1012    *  deleteForbiddenTags
1013    *  this method deletes all <script>, <body> and <head>-tags
1014    */
1015   public static String deleteForbiddenTags(String haystack) {
1016     try {
1017       RE regex = new RE("<[ \t\r\n](.*?)script(.*?)/script(.*?)>",RE.REG_ICASE);
1018       haystack = regex.substituteAll(haystack,"");
1019       regex = new RE("<head>(.*?)</head>");
1020       haystack = regex.substituteAll(haystack,"");
1021       regex = new RE("<[ \t\r\n/]*body(.*?)>");
1022       haystack = regex.substituteAll(haystack,"");
1023       return haystack;
1024     } catch(REException ex){
1025       return null;
1026     }
1027   }
1028
1029     /**
1030      * this method deletes all html tags
1031      *
1032      */
1033
1034     public static String removeHTMLTags(String haystack){
1035 try {
1036       RE regex = new RE("<[^>]*>",RE.REG_ICASE);
1037       haystack = regex.substituteAll(haystack,"");
1038
1039       return haystack;
1040     } catch(REException ex){
1041       return null;
1042     }
1043
1044
1045     }
1046
1047     /**
1048      * this method deletes all but the approved tags html tags
1049      * it also deletes approved tags which contain malicious-looking attributes and doesn't work at all
1050      */
1051
1052
1053     public static String approveHTMLTags(String haystack){
1054   try {
1055       String approvedTags="a|img|h1|h2|h3|h4|h5|h6|br|b|i|strong|p";
1056       String badAttributes="onAbort|onBlur|onChange|onClick|onDblClick|onDragDrop|onError|onFocus|onKeyDown|onKeyPress|onKeyUp|onLoad|onMouseDown|onMouseMove|onMouseOut|onMouseOver|onMouseUp|onMove|onReset|onResize|onSelect|onSubmit|onUnload";
1057       String approvedProtocols="rtsp|http|ftp|https|freenet|mailto";
1058
1059       // kill all the bad tags that have attributes
1060       String s = "<\\s*/?\\s*(?!(("+approvedTags+")\\s))\\w+\\s[^>]*>";
1061       RE regex = new RE(s,RE.REG_ICASE);
1062       haystack = regex.substituteAll(haystack,"");
1063
1064       // kill all the bad tags that are attributeless
1065       regex = new RE("<\\s*/?\\s*(?!(("+approvedTags+")\\s*>))\\w+\\s*>",RE.REG_ICASE);
1066       haystack = regex.substituteAll(haystack,"");
1067
1068       // kill all the tags which have a javascript attribute like onLoad
1069       regex = new RE("<[^>]*("+badAttributes+")[^>]*>",RE.REG_ICASE);
1070       haystack = regex.substituteAll(haystack,"");
1071
1072       // kill all the tags which include a url to an unacceptable protocol
1073       regex = new RE("<\\s*a\\s+[^>]*href=(?!(\'|\")?("+approvedProtocols+"))[^>]*>",RE.REG_ICASE);
1074       haystack = regex.substituteAll(haystack,"");
1075
1076       return haystack;
1077     } catch(REException ex){
1078       ex.printStackTrace();
1079       return null;
1080     }
1081
1082
1083     }
1084
1085
1086   /**
1087    *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
1088    *  htmlcodierten string auf und returnt einen htmlcodierten String
1089    */
1090   public static String createHTML(String content){
1091     content=convertNewline2Break(content);
1092     content=convertNewline2P(content);
1093     content=createMailLinks(content);
1094     content=createURLLinks(content);
1095     return content;
1096   }
1097
1098   /**
1099    *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
1100    *  htmlcodierten string auf und returnt einen htmlcodierten String
1101    */
1102   public static String createHTML(String content,String producerDocRoot,String mailImage,String extImage,String intImage){
1103     content=convertNewline2Break(content);
1104     content=convertNewline2P(content);
1105     content=createMailLinks(content,producerDocRoot,mailImage);
1106     content=createURLLinks(content,null,producerDocRoot,extImage,intImage);
1107     return content;
1108   }
1109
1110 }
1111