added numberformat helper. make webdbDate2readableDate use webdb_create instead....
[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  java.text.NumberFormat;
12 import  gnu.regexp.*;
13
14 /**
15  * Statische Hilfsmethoden zur Stringbehandlung
16  *
17  * @version $Revision: 1.23 $ $Date: 2002/06/28 20:39:37 $
18  * @author $Author: mh $
19  *
20  * $Log: StringUtil.java,v $
21  * Revision 1.23  2002/06/28 20:39:37  mh
22  * added numberformat helper. make webdbDate2readableDate use webdb_create instead. make the order and appearance of it more consistent. cvs macros. and finally code tidying
23  *
24  *
25  */
26 public final class StringUtil {
27
28         private static RE   re_newline2br, re_brbr2p, re_mail, re_url, re_tags;
29
30         private StringUtil() { }  // this avoids contruction
31
32         static {
33                 try {
34                         //precompile regex
35                         re_newline2br = new RE("(\r?\n){1}");
36                         re_brbr2p     = new RE("(<br>\r?\n<br>){1,}");
37                         re_mail       = new RE("([a-zA-Z0-9_.-]+)@([a-zA-Z0-9_-]+).([a-zA-Z0-9_.-]+)");
38                         re_url        = new RE("((https://)|(http://)|(ftp://)){1}([a-zA-Z0-9_-]+).([a-zA-Z0-9_.:-]+)/?([^ \t\r\n<>\\)\\]]+[^ \t\r\n.,<>\\)\\]])");
39                         re_tags       = new RE("<[^>]*>",RE.REG_ICASE);
40                 }
41                 catch (REException e){
42                         System.err.println("FATAL: StringUtil: could not precompile REGEX: "+e.toString());
43                 }
44         }
45
46   /**
47    * Formats a number with the specified minimum and maximum number of digits.
48    **/
49   public static synchronized String zeroPaddingNumber(long value, int minDigits,
50                                                       int maxDigits)
51   {
52     NumberFormat numberFormat = NumberFormat.getInstance();
53     numberFormat.setMinimumIntegerDigits(minDigits);
54     numberFormat.setMaximumIntegerDigits(maxDigits);
55     return numberFormat.format(value);
56   }
57
58         /**
59          * Wandelt Datum in einen 8-ziffrigen String um (yyyymmdd)
60          * @param theDate
61          * @return 8-ziffriger String (yyyymmdd)
62          */
63
64         public static final String date2webdbDate (GregorianCalendar theDate) {
65                 StringBuffer webdbDate = new StringBuffer();
66                 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
67                 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
68                 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
69                 return  webdbDate.toString();
70         }
71
72         /**
73          * Wandelt Calendar in einen 12-ziffrigen String um (yyyymmddhhmm)
74          * @param theDate
75          * @return 12-ziffriger String (yyyymmdd)
76          */
77
78         public static final String date2webdbDateTime (GregorianCalendar theDate) {
79                 StringBuffer webdbDate = new StringBuffer();
80                 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
81                 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
82                 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
83                 webdbDate.append(pad2(theDate.get(Calendar.HOUR)));
84                 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
85                 return  webdbDate.toString();
86         }
87
88         /**
89          * Return a http://www.w3.org/TR/NOTE-datetime formatted date (yyyy-mm-ddThh:mm:ssTZ)
90          * @param theDate
91          * @return w3approved datetime
92          */
93
94         public static final String date2w3DateTime (GregorianCalendar theDate) {
95                 StringBuffer webdbDate = new StringBuffer();
96                 webdbDate.append(String.valueOf(theDate.get(Calendar.YEAR)));
97                 webdbDate.append("-");
98                 webdbDate.append(pad2(theDate.get(Calendar.MONTH) + 1));
99                 webdbDate.append("-");
100                 webdbDate.append(pad2(theDate.get(Calendar.DATE)));
101                 webdbDate.append("T");
102                 webdbDate.append(pad2(theDate.get(Calendar.HOUR)));
103                 webdbDate.append(":");
104                 webdbDate.append(pad2(theDate.get(Calendar.MINUTE)));
105                 webdbDate.append(":");
106                 webdbDate.append(pad2(theDate.get(Calendar.SECOND)));
107                 //assumes you are an hour-multiple away from UTC....
108                 int offset=(theDate.get(Calendar.ZONE_OFFSET)/(60*60*1000));
109                 if (offset < 0){
110                 webdbDate.append("-");
111                 }
112                 else{
113                 webdbDate.append("+");
114                 }
115                 webdbDate.append(pad2(Math.abs(offset)));
116                 webdbDate.append(":00");
117                 return  webdbDate.toString();
118         }
119
120         /**
121          * wandelt Calendar in dd.mm.yyyy / hh.mm um
122          * @param theDate
123          * @return String mit (dd.mm.yyyy / hh.mm um)
124          */
125         public static String date2readableDateTime (GregorianCalendar theDate) {
126                 String readable = "";
127                 int hour;
128                 readable += pad2(theDate.get(Calendar.DATE));
129                 readable += "." + pad2(theDate.get(Calendar.MONTH) + 1);
130                 readable += "." + String.valueOf(theDate.get(Calendar.YEAR));
131                 hour = theDate.get(Calendar.HOUR);
132                 if (theDate.get(Calendar.AM_PM) == Calendar.PM)
133                         hour += 12;
134                 readable += " / " + pad2(hour);
135                 readable += ":" + pad2(theDate.get(Calendar.MINUTE));
136                 return  readable;
137         }
138
139         /**
140          * wandelt eine Datum in einen 8-buchstabigen String, der durch <code>/</code>
141          * getrennt ist.
142          *
143          * @param webdbDate
144          * @return String mit <code>/yyyy/mm/dd</code>
145          */
146         public static final String webdbDate2path (String webdbDate) {
147                 StringBuffer path = new StringBuffer();
148                 path.append("/").append(webdbDate.substring(0, 4));
149                 path.append("/").append(webdbDate.substring(4, 6));
150                 path.append("/");
151                 //who did this?
152                 //path.append("/").append(webdbDate.substring(6, 8));
153                 return  path.toString();
154         }
155
156         /**
157          * wandelt Calendar in dd.mm.yyyy um
158          *
159          * @param theDate
160          * @return String mit  <code>yyyy.mm.dd</code>
161          */
162         public static final String webdbDate2readableDate (String webdbDate) {
163                 String date = "";
164                 date += webdbDate.substring(0, 4);
165                 date += "-" + webdbDate.substring(5, 7);
166                 date += "-"+webdbDate.substring(8, 10);
167                 return  date;
168         }
169
170
171         /**
172          * converts string from format: yyyy-mm-dd__hh:mm:ss.d
173          * to dd.mm.yyyy hh:mm
174          */
175         public static String dateToReadableDate(String date) {
176                 StringBuffer returnDate = new StringBuffer();
177                 if (date!=null) {
178
179                         returnDate.append(date.substring(8,10)).append('.');
180                         returnDate.append(date.substring(5,7)).append('.');
181                         returnDate.append(date.substring(0,4)).append(' ');
182                         returnDate.append(date.substring(11,16));
183                 }
184                 return returnDate.toString();
185         }
186         
187   /**
188          * converts string from format: yyyy-mm-dd__hh:mm:ss.dddddd+TZ
189          * to yyyy-mm-ddThh:mm:ss+TZ:00 (w3 format for Dublin Core)
190          */
191         public static String webdbdateToDCDate(String date) {
192                 StringBuffer returnDate = new StringBuffer();
193                 if (date!=null) {
194       returnDate.append(date.substring(0,10));
195       returnDate.append("T");
196       returnDate.append(date.substring(11,19));
197       //String tzInfo=date.substring(26,29);
198       //if (tzInfo.equals("+00")){
199       //UTC gets a special code in w3 dates
200       //    returnDate.append("Z");
201       //}
202       //else{
203       //need to see what a newfoundland postgres
204       //timestamp looks like before making this robust
205       //    returnDate.append(tzInfo);
206       //    returnDate.append(":00");
207       //}
208
209                 }
210                 return returnDate.toString();
211         }
212
213
214         /**
215          * converts string from format: yyyy-mm-dd__hh:mm:ss.d
216          * to yyyy
217          */
218         public static String dateToYear (String date) {
219                 StringBuffer returnDate = new StringBuffer();
220                 if (date!=null) {
221
222                         returnDate.append(date.substring(0,4));
223                 }
224                 return returnDate.toString();
225         }
226
227         /**
228          * converts string from format: yyyy-mm-dd__hh:mm:ss.d
229          * to [m]m
230          */
231         public static String dateToMonth (String date) {
232                 StringBuffer returnDate = new StringBuffer();
233                 if (date!=null) {
234                         if (!date.substring(5,6).equalsIgnoreCase("0")) returnDate.append(date.substring(5,7));
235                         else returnDate.append(date.substring(6,7));
236                 }
237                 return returnDate.toString();
238         }
239
240         /**
241          * converts string from format: yyyy-mm-dd__hh:mm:ss.d
242          * to [d]d
243          */
244         public static String dateToDayOfMonth (String date) {
245                 StringBuffer returnDate = new StringBuffer();
246                 if (date!=null) {
247                         if (!date.substring(8,9).equalsIgnoreCase("0")) returnDate.append(date.substring(8,10));
248                         else returnDate.append(date.substring(9,10));
249                 }
250                 return returnDate.toString();
251         }
252
253         /**
254          * converts string from format: yyyy-mm-dd__hh:mm:ss.d
255          * to hh:mm
256          */
257         public static String dateToTime (String date) {
258                 StringBuffer returnDate = new StringBuffer();
259                 if (date!=null) {
260                         returnDate.append(date.substring(11,16));
261                 }
262                 return returnDate.toString();
263         }
264
265     /**
266      * Splits the provided CSV text into a list. stolen wholesale from
267      * from Jakarta Turbine StrinUtils.java -mh
268      *
269      * @param text      The CSV list of values to split apart.
270      * @param separator The separator character.
271      * @return          The list of values.
272      */
273     public static String[] split(String text, String separator)
274     {
275         StringTokenizer st = new StringTokenizer(text, separator);
276         String[] values = new String[st.countTokens()];
277         int pos = 0;
278         while (st.hasMoreTokens())
279         {
280             values[pos++] = st.nextToken();
281         }
282         return values;
283     }
284
285     /**
286      * Joins the elements of the provided array into a single string
287      * containing a list of CSV elements. Stolen wholesale from Jakarta
288      * Turbine StringUtils.java. -mh
289      *
290      * @param list      The list of values to join together.
291      * @param separator The separator character.
292      * @return          The CSV text.
293      */
294     public static String join(String[] list, String separator)
295     {
296         StringBuffer csv = new StringBuffer();
297         for (int i = 0; i < list.length; i++)
298         {
299             if (i > 0)
300             {
301                 csv.append(separator);
302             }
303             csv.append(list[i]);
304         }
305         return csv.toString();
306     }
307
308
309         /**
310          * schließt einen String in Anführungsszeichen ein, falls er Leerzeichen o.ä. enthält
311          *
312          * @return gequoteter String
313          */
314          public static String quoteIfNecessary(String s) {
315                 for (int i = 0; i < s.length(); i++)
316                         if (!(Character.isLetterOrDigit(s.charAt(i)) || s.charAt(i) == '.'))
317                                 return quote(s, '"');
318                 return s;
319         }
320
321          /**
322          * schließt <code>s</code> in <code>'</code> ein und setzt Backslashes vor
323          * "gefährliche" Zeichen innerhalb des Strings
324          * Quotes special SQL-characters in <code>s</code>
325          *
326          * @return geqoteter String
327          */
328         public static String quote(String s)
329         {
330                 //String s2 = quote(s, '\'');
331                 //Quickhack     ÃŠÃŠ ÃŠ ÃŠ ÃŠ ÃŠ ÃŠ ÃŠ
332                 //Because of '?-Bug in Postgresql-JDBC-Driver
333                 StringBuffer temp = new StringBuffer();
334                 for(int i=0;i<s.length();i++){
335                         if(s.charAt(i)=='\''){
336                                 temp.append("&#39;");
337                         } else {
338                                 temp.append(s.charAt(i));
339                         }
340                 }
341                 String s2 = temp.toString();
342                 //end Quickhack
343                 
344                 s2 = quote(s2, '\"');
345                 return s2;
346         }
347
348         /**
349          * schließt <code>s</code> in <code>'</code> ein und setzt Backslashes vor
350          * "gefährliche" Zeichen innerhalb des Strings
351          *
352          * @param s String, der gequoted werden soll
353          * @param quoteChar zu quotendes Zeichen
354          * @return gequoteter String
355          */
356         public static String quote(String s, char quoteChar)
357         {
358                 StringBuffer buf = new StringBuffer(s.length());
359                 int pos = 0;
360                 while (pos < s.length()) {
361                         int i = s.indexOf(quoteChar, pos);
362                         if (i < 0) i = s.length();
363                         buf.append(s.substring(pos, i));
364                         pos = i;
365                         if (pos < s.length()) {
366                                 buf.append('\\');
367                                 buf.append(quoteChar);
368                                 pos++;
369                         }
370                 }
371                 return buf.toString();
372         }
373
374         /**
375          * replaces dangerous characters in <code>s</code>
376          *
377          */
378
379         public static String unquote(String s)
380         {
381                 char quoteChar='\'';
382                 StringBuffer buf = new StringBuffer(s.length());
383                 int pos = 0;
384                 String searchString = "\\"+quoteChar;
385                 while (pos < s.length()) {
386                         int i = s.indexOf(searchString, pos);
387                         if (i < 0) i = s.length();
388                         buf.append(s.substring(pos, i));
389                         pos = i+1;
390                 }
391                 return buf.toString();
392         }
393
394         /**
395          * Wandelet String in byte[] um.
396          * @param s
397          * @return byte[] des String
398          */
399
400         public static byte[] stringToBytes(String s) {
401                 String crlf = System.getProperty("line.separator");
402                 if (!crlf.equals("\n"))
403                         s = replace(s, "\n", crlf);
404                 // byte[] buf = new byte[s.length()];
405                 byte[] buf = s.getBytes();
406                 return buf;
407         }
408
409                 /**
410          * Ersetzt in String <code>s</code> das <code>pattern</code> durch <code>substitute</code>
411          * @param s
412          * @param pattern
413          * @param substitute
414          * @return String mit den Ersetzungen
415          */
416         public static String replace(String s, String pattern, String substitute) {
417                 int i = 0, pLen = pattern.length(), sLen = substitute.length();
418                 StringBuffer buf = new StringBuffer(s.length());
419                 while (true) {
420                         int j = s.indexOf(pattern, i);
421                         if (j < 0) {
422                                 buf.append(s.substring(i));
423                                 break;
424                         } else {
425                                 buf.append(s.substring(i, j));
426                                 buf.append(substitute);
427                                 i = j+pLen;
428                         }
429                 }
430                 return buf.toString();
431         }
432
433         /**
434          * Ersetzt in String <code>s</code> das Regexp <code>pattern</code> durch <code>substitute</code>
435          * @param s
436          * @param pattern
437          * @param substitute
438          * @return String mit den Ersetzungen
439          */
440         public static String regexpReplace(String haystack, String pattern, String substitute) {
441                 try {
442                         RE regex = new RE(pattern);
443                         return regex.substituteAll(haystack,substitute);
444                 } catch(REException ex){
445                         return null;
446                 }
447         }
448
449
450
451
452         /**
453          * Fügt einen Separator an den Pfad an
454          * @param path
455          * @return Pfad mit Separator am Ende
456          */
457         public static final String addSeparator (String path) {
458                 return  path.length() == 0 || path.endsWith(File.separator) ? path : path
459                                 + File.separatorChar;
460         }
461
462         /**
463          * Fügt ein <code>/</code> ans ende des Strings and
464          * @param path
465          * @return Pfad mit <code>/</code> am Ende
466          */
467         public static final String addSlash (String path) {
468                 return  path.length() == 0 || path.endsWith("/") ? path : path + '/';
469         }
470
471         /**
472          * Löscht <code>/</code> am Ende des Strings, falls vorhanden
473          * @param path
474          * @return String ohne <code>/</code> am Ende
475          */
476         public static final String removeSlash (String path) {
477                 return  path.length() > 1 && path.endsWith("/") ? path.substring(0, path.length()
478                                 - 1) : path;
479         }
480
481         /**
482          * Checks to see if the path is absolute by looking for a leading file
483          * separater
484          * @param path
485          * @return
486          */
487         public static boolean isAbsolutePath (String path) {
488                 return  path.startsWith(File.separator);
489         }
490
491         /**
492          * Löscht Slash am Anfang des Strings
493          * @param path
494          * @return
495          */
496         public static String removeFirstSlash (String path) {
497                 return  path.startsWith("/") ? path.substring(1) : path;
498         }
499
500         /**
501          * formatiert eine Zahl (0-99) zweistellig (z.B. 5 -> 05)
502          * @return zwistellige Zahl
503          */
504         public static String pad2 (int number) {
505                 return  number < 10 ? "0" + number : String.valueOf(number);
506         }
507
508         /**
509          * formatiert eine Zahl (0-999) dreistellig (z.B. 7 -> 007)
510          *
511          * @return 3-stellige Zahl
512          */
513         public static String pad3 (int number) {
514                 return  number < 10 ? "00" + number : number < 100 ? "0" + number : String.valueOf(number);
515         }
516
517         /**
518          * Konvertiert Unix-Linefeeds in Win-Linefeeds
519          * @param s
520          * @return Konvertierter String
521          */
522         public static String unixLineFeedsToWin(String s) {
523                 int i = -1;
524                 while (true) {
525                         i = s.indexOf('\n', i+1);
526                         if (i < 0) break;
527                         if ((i == 0 || s.charAt(i-1) != '\r') &&
528                                 (i == s.length()-1 || s.charAt(i+1) != '\r')) {
529                                 s = s.substring(0, i)+'\r'+s.substring(i);
530                                 i++;
531                         }
532                 }
533                 return s;
534         }
535
536
537         /**
538          * verwandelt einen String in eine gültige Url, konvertiert Sonderzeichen
539          * und Spaces werden zu Underscores
540          *
541          * @return gültige Url
542          */
543         public static String convert2url(String s) {
544                 s = toLowerCase(s);
545                 StringBuffer buf = new StringBuffer();
546                 for(int i = 0; i < s.length(); i++ ) {
547                                 switch( s.charAt( i ) ) {
548                                 case 'ö':
549                         buf.append( "oe" ); break;
550                                 case 'ä':
551                         buf.append( "ae" ); break;
552                                 case 'ü':
553                         buf.append( "ue" ); break;
554                                 case 'ã':
555                         buf.append( "a" ); break;
556                                 case '´':
557                                 case '.':
558                         buf.append( "_" ); break;
559                                 case ' ':
560                         if( buf.charAt( buf.length() - 1 ) != '_' ) {
561                                         buf.append( "_" );
562                         }
563                         break;
564                                 default:
565                         buf.append( s.charAt( i ) );
566                                 }
567                 }
568                 return buf.toString();
569         }
570
571
572         public static String decodeHTMLinTags(String s){
573                 StringBuffer buffer = new StringBuffer();
574                 boolean start = false;
575                 boolean stop = false;
576                 int startIndex = 0;
577                 int stopIndex = 0;
578                 int temp = 0;
579
580                 for(int i=0;i<s.length();i++){
581                         if(s.charAt(i)=='<'){
582                                 start = true;
583                                 startIndex = i;
584                         } else if(s.charAt(i)=='>'){
585                                 stop = true;
586                                 stopIndex = i;
587
588                                 if(start && stop){
589                                         buffer.append(s.substring(temp,startIndex));
590                                         buffer.append(replaceQuot(s.substring(startIndex,stopIndex+1)));
591                                         i= temp= stopIndex+1;
592                                         start= stop= false;
593                                 }
594                         }
595                 }
596                 if(stopIndex>0){
597                         buffer.append(s.substring(stopIndex+1));
598                         return buffer.toString();
599                 } else {
600                         return s;
601                 }
602         }
603
604         public static String replaceQuot(String s) {
605                 StringBuffer buffer = new StringBuffer();
606                 for(int j = 0; j < s.length();j++){
607                         if(s.charAt(j)=='&'){
608                                 if(s.indexOf( "&quot;",j) == j) {
609                                         buffer.append( "\"" );
610                                         j += 5;
611                                 }//if
612                         } else {
613                                 buffer.append(s.charAt(j));
614                         }//else
615                 }//for
616                 return buffer.toString();
617         }
618
619         /** wandelt Quotes in Sonderzeichen um
620          */
621         /**
622         public static String decodeHtml(String s) {
623                 StringBuffer buf = new StringBuffer();
624                 for(int i=0;i < s.length(); i++ ) {
625                         if( s.indexOf( "&ouml;", i ) == i ) {
626                                 buf.append( "ö" ); i += 5;
627                                 continue;
628                         }
629                         if( s.indexOf( "&auml;", i ) == i ) {
630                                 buf.append( "ä" ); i += 5;
631                                 continue;
632                         }
633                         if( s.indexOf( "&uuml;", i ) == i ) {
634                                 buf.append( "ü" ); i += 5;
635                                 continue;
636                         }
637                         if( s.indexOf( "&Ouml;", i ) == i ) {
638                                 buf.append( "Ö" ); i += 5;
639                                 continue;
640                         }
641                         if( s.indexOf( "&Auml;", i ) == i ) {
642                                 buf.append( "Ä" ); i += 5;
643                                 continue;
644                         }
645                         if( s.indexOf( "&Uuml;", i ) == i ) {
646                                 buf.append( "Ãœ" ); i += 5;
647                                 continue;
648                         }
649                         if( s.indexOf( "&szlig;", i ) == i ) {
650                                 buf.append( "ß" ); i += 6;
651                                 continue;
652                         }
653                         if( s.indexOf( "&quot;", i ) == i ) {
654                                 buf.append( "\"" ); i += 5;
655                                 continue;
656                         }
657                         buf.append( s.charAt(i) );
658                 }
659                 return buf.toString();
660         }
661          */
662
663         /**
664          * schnellere Variante der String.toLowerCase()-Routine
665          *
666          * @return String in Kleinbuchsten
667          */
668         public static String toLowerCase(String s) {
669                 int l = s.length();
670                 char[] a = new char[l];
671                 for (int i = 0; i < l; i++)
672                         a[i] = Character.toLowerCase(s.charAt(i));
673                 return new String(a);
674         }
675
676                 /**
677          * Findet <code>element</code> im String-Array <code>array</code>
678          * @param array
679          * @param element
680          * @return Fundstelle als int oder -1
681          */
682         public static int indexOf(String[] array, String element) {
683                 if (array != null)
684                         for (int i = 0; i < array.length; i++)
685                                 if (array[i].equals(element))
686                                         return i;
687                 return -1;
688         }
689
690         /**
691          * Testet auf Vorkommen von <code>element</code> in <code>array</code>
692          * @param array String-Array
693          * @param element
694          * @return true wenn <code>element</code> vorkommt, sonst false
695          */
696         public static boolean contains(String[] array, String element) {
697                 return indexOf(array, element) >= 0;
698         }
699
700                 /**
701          * Ermittelt CRC-Prüfsumme von String <code>s</code>
702          * @param s
703          * @return CRC-Prüfsumme
704          */
705         public static int getCRC(String s) {
706                 int h = 0;
707                 char val[] = s.toCharArray();
708                 int len = val.length;
709
710                 for (int i = 0 ; i < len; i++) {
711                         h &= 0x7fffffff;
712                         h = (((h >> 30) | (h << 1)) ^ (val[i]+i));
713                 }
714
715                 return (h << 8) | (len & 0xff);
716         }
717
718                 /**
719          * Liefert Default-Wert def zurück, wenn String <code>s</code>
720          * kein Integer ist.
721          *
722          * @param s
723          * @param def
724          * @return geparster int aus s oder def
725          */
726         public static int parseInt(String s, int def) {
727                 if (s == null) return def;
728                 try {
729                         return Integer.parseInt(s);
730                 } catch (NumberFormatException e) {
731                         return def;
732                 }
733         }
734
735         /**
736          * Liefert Defaultwert def zurück, wenn s nicht zu einem float geparsed werden kann.
737          * @param s
738          * @param def
739          * @return geparster float oder def
740          */
741         public static float parseFloat(String s, float def) {
742                 if (s == null) return def;
743                 try {
744                         return new Float(s).floatValue();
745                 } catch (NumberFormatException e) {
746                         return def;
747                 }
748         }
749
750                 /**
751          * Findet Ende eines Satzes in String <code>text</code>
752          * @param text
753          * @param startIndex
754          * @return index des Satzendes, oder -1
755          */
756         public static int findEndOfSentence(String text, int startIndex) {
757                  while (true) {
758                          int i = text.indexOf('.', startIndex);
759                          if (i < 0) return -1;
760                          if (i > 0 && !Character.isDigit(text.charAt(i-1)) &&
761                                         (i+1 >= text.length()
762                                         || text.charAt(i+1) == ' '
763                                         || text.charAt(i+1) == '\n'
764                                         || text.charAt(i+1) == '\t'))
765                                         return i+1;
766                          startIndex = i+1;
767                  }
768         }
769
770                 /**
771          * Findet Wortende in String <code>text</code> ab <code>startIndex</code>
772          * @param text
773          * @param startIndex
774          * @return Index des Wortendes, oder -1
775          */
776         public static int findEndOfWord(String text, int startIndex) {
777                 int i = text.indexOf(' ', startIndex),
778                         j = text.indexOf('\n', startIndex);
779                 if (i < 0) i = text.length();
780                 if (j < 0) j = text.length();
781                 return Math.min(i, j);
782         }
783
784
785         /**
786          *  convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
787          *  in den html-tag <p>
788          *  nur sinnvoll, wenn text nicht im html-format eingegeben
789          */
790         public static String convertNewline2P(String haystack) {
791                         return re_brbr2p.substituteAll(haystack,"\n</p><p>");
792         }
793
794         /**
795          *  convertNewline2Break ist eine regex-routine zum umwandeln von 1 newline (\n)
796          *  in den html-tag <br>
797          *  nur sinnvoll, wenn text nicht im html-format eingegeben
798          */
799         public static String convertNewline2Break(String haystack) {
800                 return re_newline2br.substituteAll(haystack,"$0<br />");
801         }
802
803         /**
804          *  createMailLinks wandelt text im email-adressenformat
805          *  in einen klickbaren link um
806          *  nur sinnvoll, wenn text nicht im html-format eingegeben
807          */
808         public static String createMailLinks(String haystack) {
809                         return re_mail.substituteAll(haystack,"<a href=\"mailto:$0\">$0</a>");
810         }
811
812
813         /**
814          *  createMailLinks wandelt text im email-adressenformat
815          *  in einen klickbaren link um
816          *  nur sinnvoll, wenn text nicht im html-format eingegeben
817          */
818         public static String createMailLinks(String haystack, String imageRoot, String mailImage) {
819                 return re_mail.substituteAll(haystack,"<img src=\""+imageRoot+"/"+mailImage+"\" border=\"0\"/>&#160;<a href=\"mailto:$0\">$0</a>");
820         }
821
822
823         /**
824          *  createURLLinks wandelt text im url-format
825          *  in einen klickbaren link um
826          *  nur sinnvoll, wenn text nicht im html-format eingegeben
827          */
828         public static String createURLLinks(String haystack) {
829                 return re_url.substituteAll(haystack,"<a href=\"$0\">$0</a>");
830         }
831
832         /**
833          * this routine takes text in url format and makes
834          * a clickaeble "<href>" link removing any "illegal" html tags
835          * @param haystack, the url
836          * @param title, the href link text
837          * @param imagRoot, the place to find icons
838          * @param extImage, the url of the icon to show next to the link
839          * @return a String containing the url
840          */
841         public static String createURLLinks(String haystack, String title, String imageRoot,String extImage) {
842                 if (title == null) {
843                         return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">$0</a>");
844                 } else {
845                         title = removeHTMLTags(title);
846                         return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">"+title+"</a>");
847                 }
848         }
849
850         /**
851          * this routine takes text in url format and makes
852          * a clickaeble "<href>" link removing any "illegal" html tags
853          * @param haystack, the url
854          * @param imageRoot, the place to find icons
855          * @param extImage, the url of the icon to show next to the link
856          * @param intImage, unused
857          * @return a String containing the url
858          */
859         public static String createURLLinks(String haystack, String title, String imageRoot,String extImage,String intImage) {
860                 return createURLLinks(haystack, title, imageRoot, extImage);
861         }
862
863          /**
864          *  deleteForbiddenTags
865          *  this method deletes all <script>, <body> and <head>-tags
866          */
867         public static final String deleteForbiddenTags(String haystack) {
868                 try {
869                         RE regex = new RE("<[ \t\r\n](.*?)script(.*?)/script(.*?)>",RE.REG_ICASE);
870                         haystack = regex.substituteAll(haystack,"");
871                         regex = new RE("<head>(.*?)</head>");
872                         haystack = regex.substituteAll(haystack,"");
873                         regex = new RE("<[ \t\r\n/]*body(.*?)>");
874                         haystack = regex.substituteAll(haystack,"");
875                         return haystack;
876                 } catch(REException ex){
877                         return null;
878                 }
879         }
880
881         /**
882          * this method deletes all html tags
883          */
884         public static final String removeHTMLTags(String haystack){
885                         return re_tags.substituteAll(haystack,"");
886         }
887
888
889         /**
890          * this method deletes all but the approved tags html tags
891          * it also deletes approved tags which contain malicious-looking attributes and doesn't work at all
892          */
893         public static String approveHTMLTags(String haystack){
894                 try {
895                         String approvedTags="a|img|h1|h2|h3|h4|h5|h6|br|b|i|strong|p";
896                         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";
897                         String approvedProtocols="rtsp|http|ftp|https|freenet|mailto";
898
899                         // kill all the bad tags that have attributes
900                         String s = "<\\s*/?\\s*(?!(("+approvedTags+")\\s))\\w+\\s[^>]*>";
901                         RE regex = new RE(s,RE.REG_ICASE);
902                         haystack = regex.substituteAll(haystack,"");
903
904                         // kill all the bad tags that are attributeless
905                         regex = new RE("<\\s*/?\\s*(?!(("+approvedTags+")\\s*>))\\w+\\s*>",RE.REG_ICASE);
906                         haystack = regex.substituteAll(haystack,"");
907
908                         // kill all the tags which have a javascript attribute like onLoad
909                         regex = new RE("<[^>]*("+badAttributes+")[^>]*>",RE.REG_ICASE);
910                         haystack = regex.substituteAll(haystack,"");
911
912                         // kill all the tags which include a url to an unacceptable protocol
913                         regex = new RE("<\\s*a\\s+[^>]*href=(?!(\'|\")?("+approvedProtocols+"))[^>]*>",RE.REG_ICASE);
914                         haystack = regex.substituteAll(haystack,"");
915
916                         return haystack;
917                 } catch(REException ex){
918                         ex.printStackTrace();
919                         return null;
920                 }
921         }
922
923
924         /**
925          *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
926          *  htmlcodierten string auf und returnt einen htmlcodierten String
927          */
928         public static String createHTML(String content){
929                 content=convertNewline2Break(content);
930                 content=convertNewline2P(content);
931                 content=createMailLinks(content);
932                 content=createURLLinks(content);
933                 return content;
934         }
935
936
937         /**
938          *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
939          *  htmlcodierten string auf und returnt einen htmlcodierten String
940          */
941         public static String createHTML(String content,String producerDocRoot,String mailImage,String extImage,String intImage){
942                 content=convertNewline2Break(content);
943                 content=convertNewline2P(content);
944                 content=createMailLinks(content,producerDocRoot,mailImage);
945                 content=createURLLinks(content,null,producerDocRoot,extImage,intImage);
946                 return content;
947         }
948
949 }
950