remove unused methods
[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.28 2002/11/27 08:21:02 mh 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         public static String replaceQuot(String s) {
558                 StringBuffer buffer = new StringBuffer();
559                 for(int j = 0; j < s.length();j++){
560                         if(s.charAt(j)=='&'){
561                                 if(s.indexOf( "&quot;",j) == j) {
562                                         buffer.append( "\"" );
563                                         j += 5;
564                                 }//if
565                         } else {
566                                 buffer.append(s.charAt(j));
567                         }//else
568                 }//for
569                 return buffer.toString();
570         }
571
572         /** wandelt Quotes in Sonderzeichen um
573          */
574         /**
575         public static String decodeHtml(String s) {
576                 StringBuffer buf = new StringBuffer();
577                 for(int i=0;i < s.length(); i++ ) {
578                         if( s.indexOf( "&ouml;", i ) == i ) {
579                                 buf.append( "ö" ); i += 5;
580                                 continue;
581                         }
582                         if( s.indexOf( "&auml;", i ) == i ) {
583                                 buf.append( "ä" ); i += 5;
584                                 continue;
585                         }
586                         if( s.indexOf( "&uuml;", i ) == i ) {
587                                 buf.append( "ü" ); i += 5;
588                                 continue;
589                         }
590                         if( s.indexOf( "&Ouml;", i ) == i ) {
591                                 buf.append( "Ö" ); i += 5;
592                                 continue;
593                         }
594                         if( s.indexOf( "&Auml;", i ) == i ) {
595                                 buf.append( "Ä" ); i += 5;
596                                 continue;
597                         }
598                         if( s.indexOf( "&Uuml;", i ) == i ) {
599                                 buf.append( "Ãœ" ); i += 5;
600                                 continue;
601                         }
602                         if( s.indexOf( "&szlig;", i ) == i ) {
603                                 buf.append( "ß" ); i += 6;
604                                 continue;
605                         }
606                         if( s.indexOf( "&quot;", i ) == i ) {
607                                 buf.append( "\"" ); i += 5;
608                                 continue;
609                         }
610                         buf.append( s.charAt(i) );
611                 }
612                 return buf.toString();
613         }
614          */
615
616         /**
617          * schnellere Variante der String.toLowerCase()-Routine
618          *
619          * @return String in Kleinbuchsten
620          */
621         public static String toLowerCase(String s) {
622                 int l = s.length();
623                 char[] a = new char[l];
624                 for (int i = 0; i < l; i++)
625                         a[i] = Character.toLowerCase(s.charAt(i));
626                 return new String(a);
627         }
628
629                 /**
630          * Findet <code>element</code> im String-Array <code>array</code>
631          * @param array
632          * @param element
633          * @return Fundstelle als int oder -1
634          */
635         public static int indexOf(String[] array, String element) {
636                 if (array != null)
637                         for (int i = 0; i < array.length; i++)
638                                 if (array[i].equals(element))
639                                         return i;
640                 return -1;
641         }
642
643         /**
644          * Testet auf Vorkommen von <code>element</code> in <code>array</code>
645          * @param array String-Array
646          * @param element
647          * @return true wenn <code>element</code> vorkommt, sonst false
648          */
649         public static boolean contains(String[] array, String element) {
650                 return indexOf(array, element) >= 0;
651         }
652
653                 /**
654          * Ermittelt CRC-Prüfsumme von String <code>s</code>
655          * @param s
656          * @return CRC-Prüfsumme
657          */
658         public static int getCRC(String s) {
659                 int h = 0;
660                 char val[] = s.toCharArray();
661                 int len = val.length;
662
663                 for (int i = 0 ; i < len; i++) {
664                         h &= 0x7fffffff;
665                         h = (((h >> 30) | (h << 1)) ^ (val[i]+i));
666                 }
667
668                 return (h << 8) | (len & 0xff);
669         }
670
671                 /**
672          * Liefert Default-Wert def zurück, wenn String <code>s</code>
673          * kein Integer ist.
674          *
675          * @param s
676          * @param def
677          * @return geparster int aus s oder def
678          */
679         public static int parseInt(String s, int def) {
680                 if (s == null) return def;
681                 try {
682                         return Integer.parseInt(s);
683                 } catch (NumberFormatException e) {
684                         return def;
685                 }
686         }
687
688         /**
689          * Liefert Defaultwert def zurück, wenn s nicht zu einem float geparsed werden kann.
690          * @param s
691          * @param def
692          * @return geparster float oder def
693          */
694         public static float parseFloat(String s, float def) {
695                 if (s == null) return def;
696                 try {
697                         return new Float(s).floatValue();
698                 } catch (NumberFormatException e) {
699                         return def;
700                 }
701         }
702
703                 /**
704          * Findet Ende eines Satzes in String <code>text</code>
705          * @param text
706          * @param startIndex
707          * @return index des Satzendes, oder -1
708          */
709         public static int findEndOfSentence(String text, int startIndex) {
710                  while (true) {
711                          int i = text.indexOf('.', startIndex);
712                          if (i < 0) return -1;
713                          if (i > 0 && !Character.isDigit(text.charAt(i-1)) &&
714                                         (i+1 >= text.length()
715                                         || text.charAt(i+1) == ' '
716                                         || text.charAt(i+1) == '\n'
717                                         || text.charAt(i+1) == '\t'))
718                                         return i+1;
719                          startIndex = i+1;
720                  }
721         }
722
723                 /**
724          * Findet Wortende in String <code>text</code> ab <code>startIndex</code>
725          * @param text
726          * @param startIndex
727          * @return Index des Wortendes, oder -1
728          */
729         public static int findEndOfWord(String text, int startIndex) {
730                 int i = text.indexOf(' ', startIndex),
731                         j = text.indexOf('\n', startIndex);
732                 if (i < 0) i = text.length();
733                 if (j < 0) j = text.length();
734                 return Math.min(i, j);
735         }
736
737
738         /**
739          *  convertNewline2P ist eine regex-routine zum umwandeln von 2 oder mehr newlines (\n)
740          *  in den html-tag <p>
741          *  nur sinnvoll, wenn text nicht im html-format eingegeben
742          */
743         public static String convertNewline2P(String haystack) {
744                         return re_brbr2p.substituteAll(haystack,"\n</p><p>");
745         }
746
747         /**
748          *  convertNewline2Break ist eine regex-routine zum umwandeln von 1 newline (\n)
749          *  in den html-tag <br>
750          *  nur sinnvoll, wenn text nicht im html-format eingegeben
751          */
752         public static String convertNewline2Break(String haystack) {
753                 return re_newline2br.substituteAll(haystack,"$0<br />");
754         }
755
756         /**
757          *  createMailLinks wandelt text im email-adressenformat
758          *  in einen klickbaren link um
759          *  nur sinnvoll, wenn text nicht im html-format eingegeben
760          */
761         public static String createMailLinks(String haystack) {
762                         return re_mail.substituteAll(haystack,"<a href=\"mailto:$0\">$0</a>");
763         }
764
765
766         /**
767          *  createMailLinks wandelt text im email-adressenformat
768          *  in einen klickbaren link um
769          *  nur sinnvoll, wenn text nicht im html-format eingegeben
770          */
771         public static String createMailLinks(String haystack, String imageRoot, String mailImage) {
772                 return re_mail.substituteAll(haystack,"<img src=\""+imageRoot+"/"+mailImage+"\" border=\"0\"/>&#160;<a href=\"mailto:$0\">$0</a>");
773         }
774
775
776         /**
777          *  createURLLinks wandelt text im url-format
778          *  in einen klickbaren link um
779          *  nur sinnvoll, wenn text nicht im html-format eingegeben
780          */
781         public static String createURLLinks(String haystack) {
782                 return re_url.substituteAll(haystack,"<a href=\"$0\">$0</a>");
783         }
784
785         /**
786          * this routine takes text in url format and makes
787          * a clickaeble "<href>" link removing any "illegal" html tags
788          * @param haystack, the url
789          * @param title, the href link text
790          * @param imagRoot, the place to find icons
791          * @param extImage, the url of the icon to show next to the link
792          * @return a String containing the url
793          */
794         public static String createURLLinks(String haystack, String title, String imageRoot,String extImage) {
795                 if (title == null) {
796                         return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">$0</a>");
797                 } else {
798                         title = removeHTMLTags(title);
799                         return re_url.substituteAll(haystack,"<img src=\""+imageRoot+"/"+extImage+"\" border=\"0\"/>&#160;<a href=\"$0\">"+title+"</a>");
800                 }
801         }
802
803         /**
804          * this routine takes text in url format and makes
805          * a clickaeble "<href>" link removing any "illegal" html tags
806          * @param haystack, the url
807          * @param imageRoot, the place to find icons
808          * @param extImage, the url of the icon to show next to the link
809          * @param intImage, unused
810          * @return a String containing the url
811          */
812         public static String createURLLinks(String haystack, String title, String imageRoot,String extImage,String intImage) {
813                 return createURLLinks(haystack, title, imageRoot, extImage);
814         }
815
816          /**
817          *  deleteForbiddenTags
818          *  this method deletes all <script>, <body> and <head>-tags
819          */
820         public static final String deleteForbiddenTags(String haystack) {
821                 try {
822                         RE regex = new RE("<[ \t\r\n](.*?)script(.*?)/script(.*?)>",RE.REG_ICASE);
823                         haystack = regex.substituteAll(haystack,"");
824                         regex = new RE("<head>(.*?)</head>");
825                         haystack = regex.substituteAll(haystack,"");
826                         regex = new RE("<[ \t\r\n/]*body(.*?)>");
827                         haystack = regex.substituteAll(haystack,"");
828                         return haystack;
829                 } catch(REException ex){
830                         return null;
831                 }
832         }
833
834         /**
835          * this method deletes all html tags
836          */
837         public static final String removeHTMLTags(String haystack){
838                         return re_tags.substituteAll(haystack,"");
839         }
840
841
842         /**
843          * this method deletes all but the approved tags html tags
844          * it also deletes approved tags which contain malicious-looking attributes and doesn't work at all
845          */
846         public static String approveHTMLTags(String haystack){
847                 try {
848                         String approvedTags="a|img|h1|h2|h3|h4|h5|h6|br|b|i|strong|p";
849                         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";
850                         String approvedProtocols="rtsp|http|ftp|https|freenet|mailto";
851
852                         // kill all the bad tags that have attributes
853                         String s = "<\\s*/?\\s*(?!(("+approvedTags+")\\s))\\w+\\s[^>]*>";
854                         RE regex = new RE(s,RE.REG_ICASE);
855                         haystack = regex.substituteAll(haystack,"");
856
857                         // kill all the bad tags that are attributeless
858                         regex = new RE("<\\s*/?\\s*(?!(("+approvedTags+")\\s*>))\\w+\\s*>",RE.REG_ICASE);
859                         haystack = regex.substituteAll(haystack,"");
860
861                         // kill all the tags which have a javascript attribute like onLoad
862                         regex = new RE("<[^>]*("+badAttributes+")[^>]*>",RE.REG_ICASE);
863                         haystack = regex.substituteAll(haystack,"");
864
865                         // kill all the tags which include a url to an unacceptable protocol
866                         regex = new RE("<\\s*a\\s+[^>]*href=(?!(\'|\")?("+approvedProtocols+"))[^>]*>",RE.REG_ICASE);
867                         haystack = regex.substituteAll(haystack,"");
868
869                         return haystack;
870                 } catch(REException ex){
871                         ex.printStackTrace();
872                         return null;
873                 }
874         }
875
876
877         /**
878          *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
879          *  htmlcodierten string auf und returnt einen htmlcodierten String
880          */
881         public static String createHTML(String content){
882                 content=convertNewline2Break(content);
883                 content=convertNewline2P(content);
884                 content=createMailLinks(content);
885                 content=createURLLinks(content);
886                 return content;
887         }
888
889
890         /**
891          *  createHTML ruft alle regex-methoden zum unwandeln eines nicht
892          *  htmlcodierten string auf und returnt einen htmlcodierten String
893          */
894         public static String createHTML(String content,String producerDocRoot,String mailImage,String extImage,String intImage){
895                 content=convertNewline2Break(content);
896                 content=convertNewline2P(content);
897                 content=createMailLinks(content,producerDocRoot,mailImage);
898                 content=createURLLinks(content,null,producerDocRoot,extImage,intImage);
899                 return content;
900         }
901
902 }
903