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