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