From: zapata Date: Sat, 15 Dec 2007 00:24:41 +0000 (+0000) Subject: support for CAPTCHAs X-Git-Url: http://erislabs.net/gitweb/?p=mir.git;a=commitdiff_plain;h=c26251faa299ed62d0e47c32636f440c554610ec support for CAPTCHAs replaced gnu regexp with oro which is much faster --- diff --git a/bundles/admin_en.properties b/bundles/admin_en.properties index 5462196d..7b5c9e51 100755 --- a/bundles/admin_en.properties +++ b/bundles/admin_en.properties @@ -1,6 +1,6 @@ ########## admin ########## # language: english -# $Id: admin_en.properties,v 1.48.2.29 2006/12/25 20:10:22 zapata Exp $ +# $Id: admin_en.properties,v 1.48.2.30 2007/12/15 00:24:41 zapata Exp $ languagename=English @@ -213,6 +213,7 @@ content.uploadvideo=upload video content.addother=add other media content.uploadother=upload other media + content.creationdate=date content.modificationdate=last change content.status=Status @@ -476,7 +477,7 @@ abuse.setting = Setting abuse.value = Value abuse.disableopenpostings=Turn off open posting -abuse.openpostingpassword=Require a password for open postings +abuse.openpostingpassword=Require a CAPTCHA for open postings abuse.logpostings=Log IPs for open postings abuse.logsize=Logging buffer size abuse.cookies=Use cookies for blocked users diff --git a/etc/bundles/open_en.properties b/etc/bundles/open_en.properties index 97ed4a0e..f48be853 100755 --- a/etc/bundles/open_en.properties +++ b/etc/bundles/open_en.properties @@ -8,58 +8,60 @@ required=required general.unexpectederror=An unexpected error has occurred -posting.htmltitle=Mir | open posting - -posting.step00= Step 00 -posting.step01= Step 01 -posting.step02= Step 02 -posting.step03= Step 03 -posting.step04= Step 04 -posting.step05= Step 05 -posting.step06= Step 06 - -posting.readhowtos = Add some general tips on how to post stories. - -posting.password=Password -posting.meta.description=Mir CMS system -posting.meta.author=mir -posting.meta.keywords=free media -posting.jump_to_form=Jump directly to the form. -posting.title=Publish your article! -posting.nr_of_media=Number of Media Items (max 20) -posting.nr_of_media.info=(Enter the number of files you want to upload and press the button before you enter data into the other fields.) -posting.nr_of_media.submit=define number (max 20) -posting.form.title=Publishing Form -posting.title=title of your article -posting.title.info=(Please use a clear and meaningful title) -posting.topic=Topic of your Posting -posting.topic.info=(multiple selection is possible. use the [Ctrl] key) -posting.author=author of this article -posting.abstract=A short abstract of your article -posting.abstract.info=(should give the readers a short introduction on what your article is about. If you use the first paragraph of your article for this purpose, please do not include it in the main text field below.) -posting.abstract.constraint=(not more than 5 lines) -posting.contact.info=Contact information is optional but enables other people to get in touch with you. -posting.email=your e-mail address -posting.url=your web-site address -posting.address=your address -posting.phone=your telephone number -posting.language=the language of your article -posting.text=your article -posting.text.info=fill in the text of your article here -posting.media.ftpmedia = FTP uploads (please enter the filename) -posting.media=media -posting.media.info=upload media-files (supported are jpg|gif|mp3|avi|qt|mpeg) max size: 20 Mb -posting.media.howto=(Press "Browse" and select the file you want to upload) -posting.media.media=Media -posting.media.title=media sub-title -posting.media.cancel=Cancel -posting.submit.info=Please press submit only once!
It will appear in a few minutes on the main page. It might even take longer in case of technical problems. -posting.criteria= -posting.submit=Submit (patience is a virtue!) -posting.reset=Form Reset -posting.error.missingpassword=The one-time password must be copied into the password field -posting.error.invalidpassword=The one-time password was not copied correctly into the password field -posting.error.missingfield=At least one field was not correctly entered +content.htmltitle=Mir | open posting +content.errors= Errors +content.errors.info = Your input had the following errors: +content.step00= Step 00 +content.step01= Step 01 +content.step02= Step 02 +content.step03= Step 03 +content.step04= Step 04 +content.step05= Step 05 +content.step06= Step 06 + +content.readhowtos = Add some general tips on how to post stories. + +content.password=Password +content.meta.description=Mir CMS system +content.meta.author=mir +content.meta.keywords=free media +content.jump_to_form=Jump directly to the form. +content.title=Publish your article! +content.nr_of_media=Number of Media Items (max 20) +content.nr_of_media.info=(Enter the number of files you want to upload and press the button before you enter data into the other fields.) +content.nr_of_media.submit=define number (max 20) +content.form.title=Publishing Form +content.title=title of your article +content.title.info=(Please use a clear and meaningful title) +content.topic=Topic of your Posting +content.topic.info=(multiple selection is possible. use the [Ctrl] key) +content.creator=author of this article +content.abstract=A short abstract of your article +content.abstract.info=(should give the readers a short introduction on what your article is about. If you use the first paragraph of your article for this purpose, please do not include it in the main text field below.) +content.abstract.constraint=(not more than 5 lines) +content.contact.info=Contact information is optional but enables other people to get in touch with you. +content.email=your e-mail address +content.url=your web-site address +content.address=your address +content.phone=your telephone number +content.language=the language of your article +content.content_data=your article +content.content_data.info=fill in the text of your article here +content.media.ftpmedia = FTP uploads (please enter the filename) +content.media=media +content.media.info=upload media-files (supported are jpg|gif|mp3|avi|qt|mpeg) max size: 20 Mb +content.media.howto=(Press "Browse" and select the file you want to upload) +content.media.media=Media +content.media.title=media sub-title +content.media.cancel=Cancel +content.submit.info=Please press submit only once!
It will appear in a few minutes on the main page. It might even take longer in case of technical problems. +content.criteria= +content.submit=Submit (patience is a virtue!) +content.reset=Form Reset +content.error.missingpassword=The one-time password must be copied into the password field +validationerror.passwordmismatch=The password was not entered correctly +content.error.missingfield=At least one field was not correctly entered + media.error.unsupportedformat=The format of the media you uploaded ({0}) is not supported postingdone.htmltitle=open posting @@ -92,7 +94,7 @@ comment.url=your web site address comment.phone=your telephone number. comment.address=your address comment.language=language of your comment -comment.text=your comment +comment.description=your comment comment.submit=submit comment comment.reset=reset form comment.error.missingpassword=The one-time password must be copied into the password field @@ -168,4 +170,8 @@ newsletter.prepare.htmltitle=Preparing Newsletter newsletter.prepare.title=Prepare the newsletter newsletter.prepare.description=Use the following form to prepare a newsletter. Put article ids in the boxes and hit the button. -htmlcharset=utf-8 +validationerror.missing = Must be entered +content.password = Password +content.title = Title +content.description = abstract + diff --git a/etc/bundles/open_es.properties b/etc/bundles/open_es.properties index ef009571..7ee9e122 100755 --- a/etc/bundles/open_es.properties +++ b/etc/bundles/open_es.properties @@ -35,53 +35,53 @@ commentdupe.explanation=Probablemente haya apretado el bot commentdupe.no_panic=No se altere! commentdupe.back=Volver al artículo comentado -posting.htmltitle=Mir | envío abierto +content.htmltitle=Mir | envío abierto -posting.step00= Step 00 -posting.step01= Step 01 -posting.step02= Step 02 -posting.step03= Step 03 -posting.step04= Step 04 -posting.step05= Step 05 -posting.step06= Step 06 +content.step00= Step 00 +content.step01= Step 01 +content.step02= Step 02 +content.step03= Step 03 +content.step04= Step 04 +content.step05= Step 05 +content.step06= Step 06 -posting.readhowtos = Add some general tips on how to post stories. +content.readhowtos = Add some general tips on how to post stories. -posting.password=Password -posting.meta.description=Centro de Periodismo Independiente -posting.meta.author=Colectivo IMC -posting.meta.keywords=Periodismo Libre -posting.jump_to_form=Ir directamente al formulario. -posting.title=Publique su artículo -posting.nr_of_media=Número de recursos mediáticos -posting.nr_of_media.info=(wenn Du mehr als eine Datei hochladen willst, bitte hier die Anzahl eintragen und den Knopf drücken, bevor Du weitere Felder ausfüllst.) -posting.nr_of_media.submit=Anzahl festlegen -posting.form.title=Formulario de publicación -posting.title=Título de su artículo -posting.title.info=(Bitte wähle einen möglichst klaren, aussagekräftigen Titel.) -posting.topic=Thema Deines Beitrags -posting.topic.info=(Mehrfachwahl ist möglich. Bitte dazu die [Strg]- bzw [Ctrl]-Taste benutzen) -posting.author=autor de este artículo -posting.abstract=Descripción breve de su artículo -posting.abstract.info=(Sie soll den LeserInnen schnell vermitteln, worum es in Deinem Beitrag geht. Falls Du den ersten Absatz Deines Artikels dazu wählst, achte bitte darauf ihn im Haupttextfeld weiter unten nicht nochmal einzusetzen.) -posting.abstract.constraint=(que no exceda de 5 líneas) -posting.contact.info=La información de contacto es opcional pero ayuda a que otras personas puedan ponerse en contacto con usted. -posting.email=su dirección de email -posting.url=su dirección web -posting.address=su dirección personal -posting.phone=su número de teléfono -posting.language=idioma de su artículo -posting.text=su artículo -posting.text.info=ponga aquí el texto de su artículo -posting.media=recursos mediáticos -posting.media.info=cargue sus ficheros de medios (de momento tan solo se aceptan jpg|gif|mp3|avi|qt|mpeg) -posting.media.howto=(Dazu wählst Du mit "Durchsuchen.." die entsprechende Datei auf Deiner Festplatte aus. -posting.media.media=Media -posting.media.title=subtítulo de los recursos mediáticos -posting.submit.info=Bitte drücke den Verschicken-Knopf nur einmal!
In wenigen Minuten erscheind Dein Beitrag dann auf der "Open Posting" - Seite.   Das ist nicht die Startseite.
Manchmal kann es aber aufgrund technischer Probleme etwas dauern bis er erscheint. -posting.criteria=Die Moderationskriterien kannst Du hier nachlesen -posting.submit=Enviar (la paciencia es una virtud!!) -posting.reset=Limpiar formulario +content.password=Password +content.meta.description=Centro de Periodismo Independiente +content.meta.author=Colectivo IMC +content.meta.keywords=Periodismo Libre +content.jump_to_form=Ir directamente al formulario. +content.title=Publique su artículo +content.nr_of_media=Número de recursos mediáticos +content.nr_of_media.info=(wenn Du mehr als eine Datei hochladen willst, bitte hier die Anzahl eintragen und den Knopf drücken, bevor Du weitere Felder ausfüllst.) +content.nr_of_media.submit=Anzahl festlegen +content.form.title=Formulario de publicación +content.title=Título de su artículo +content.title.info=(Bitte wähle einen möglichst klaren, aussagekräftigen Titel.) +content.topic=Thema Deines Beitrags +content.topic.info=(Mehrfachwahl ist möglich. Bitte dazu die [Strg]- bzw [Ctrl]-Taste benutzen) +content.creator=autor de este artículo +content.abstract=Descripción breve de su artículo +content.abstract.info=(Sie soll den LeserInnen schnell vermitteln, worum es in Deinem Beitrag geht. Falls Du den ersten Absatz Deines Artikels dazu wählst, achte bitte darauf ihn im Haupttextfeld weiter unten nicht nochmal einzusetzen.) +content.abstract.constraint=(que no exceda de 5 líneas) +content.contact.info=La información de contacto es opcional pero ayuda a que otras personas puedan ponerse en contacto con usted. +content.email=su dirección de email +content.url=su dirección web +content.address=su dirección personal +content.phone=su número de teléfono +content.language=idioma de su artículo +content.content_data=su artículo +content.content_data.info=ponga aquí el texto de su artículo +content.media=recursos mediáticos +content.media.info=cargue sus ficheros de medios (de momento tan solo se aceptan jpg|gif|mp3|avi|qt|mpeg) +content.media.howto=(Dazu wählst Du mit "Durchsuchen.." die entsprechende Datei auf Deiner Festplatte aus. +content.media.media=Media +content.media.title=subtítulo de los recursos mediáticos +content.submit.info=Bitte drücke den Verschicken-Knopf nur einmal!
In wenigen Minuten erscheind Dein Beitrag dann auf der "Open Posting" - Seite.   Das ist nicht die Startseite.
Manchmal kann es aber aufgrund technischer Probleme etwas dauern bis er erscheint. +content.criteria=Die Moderationskriterien kannst Du hier nachlesen +content.submit=Enviar (la paciencia es una virtud!!) +content.reset=Limpiar formulario postingdone.htmltitle=open posting postingdone.title=Hurra, Du hast Deinen Artikel abgeschickt! diff --git a/etc/open/editarticle.template b/etc/open/editarticle.template index 5bd19d75..67356bca 100755 --- a/etc/open/editarticle.template +++ b/etc/open/editarticle.template @@ -1,7 +1,7 @@ -${lang("posting.htmltitle")} +${lang("content.htmltitle")} @@ -54,6 +54,31 @@ border-width: 2px; border-style: solid; } +.pformerrors +{ +margin: none; +border: none; +padding: 8px; +margin-top: 0px; +margin-bottom: 6px; +background-color: #FFFFFF; +border-color: gray; +border-width: 1px; +border-style: solid; +} +.pformstep00 +{ +margin: none; +border: none; +padding: 8px; +margin-top: 0px; +margin-bottom: 6px; +background-color: #FAFAD2; +border-color: gray; +border-width: 1px; +border-style: solid; +} + .pformstep01 { margin: none; @@ -184,13 +209,20 @@ color: red; - ${lang(e.message + "." + e.field)} + ${lang(e.message)} +
+ +

+${lang("content.form.title")} +

+ +
Your input had the following errors:

@@ -203,75 +235,50 @@ color: red; - - - - - -
-
- -
- -
- -

-${lang("posting.form.title")} -

- - -

${lang("posting.errors")}

-${lang("posting.step00")} +${lang("content.step00")} +

-
-${lang("posting.readhowtos")} +
+${lang("content.readhowtos")} +

-${lang("posting.step01")} +${lang("content.step01")}

-${lang("posting.nr_of_media")} +${lang("content.nr_of_media")}

-${lang("posting.nr_of_media.info")} +${lang("content.nr_of_media.info")}

- +

- -
-${password} - -

${lang("posting.password")}

- -

- -

-${lang("posting.step02")} +${lang("content.step02")}

-${lang("posting.title")} +${lang("content.title")}

-${lang("posting.title.info")} +${lang("content.title.info")}

@@ -284,10 +291,10 @@ ${lang("posting.title")}

-${lang("posting.topic")} +${lang("content.topic")}

-${lang("posting.topic.info")} +${lang("content.topic.info")}

@@ -311,10 +318,10 @@ ${lang("posting.author")}

-${lang("posting.abstract")} +${lang("content.abstract")}

-${lang("posting.abstract.info")} +${lang("content.abstract.info")}

@@ -323,57 +330,57 @@ ${lang("posting.abstract.info")} (${lang("required")})

-${lang("posting.abstract.constraint")} +${lang("content.abstract.constraint")}

-${lang("posting.step03")} +${lang("content.step03")}

-${lang("posting.contact.info")} +${lang("content.contact.info")}

-${lang("posting.email")} +${lang("content.email")}

(${lang("optional")})

-${lang("posting.url")} +${lang("content.url")}

(${lang("optional")})

-${lang("posting.address")} +${lang("content.address")}

(${lang("optional")})

-${lang("posting.phone")} +${lang("content.phone")}

(${lang("optional")})

-${lang("posting.step04")} +${lang("content.step04")}

-${lang("posting.language")} +${lang("content.language")}

@@ -395,7 +402,7 @@ ${lang("posting.text.info")} (${lang("required")}) -

${lang("posting.html")}

+

${lang("content.html")}

${lang("posting.media.cancel")} + ${lang("content.media.cancel")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}

-${lang("posting.media.info")} +${lang("content.media.info")}

-${lang("posting.media.howto")} +${lang("content.media.howto")}


- ${lang("posting.media.media")} ${m} + ${lang("content.media.media")} ${m}

- ${lang("posting.media.title")} ${m} + ${lang("content.media.title")} ${m}

@@ -451,7 +458,7 @@ ${lang("posting.media.howto")}

- ${lang("posting.media.ftpmedia")} + ${lang("content.media.ftpmedia")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}


- ${lang("posting.media.ftpmedia")} + ${lang("content.media.ftpmedia")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}

@@ -481,18 +488,28 @@ ${lang("posting.media.howto")}

-${lang("posting.step06")} +${lang("content.step06")}

-${lang("posting.submit.info")} +${lang("content.submit.info")}

-${lang("posting.criteria")} +${lang("content.criteria")}

+ +
+ + +

${lang("content.password")}

+ +

+ + +

- - + +
diff --git a/etc/open/editcomment.template b/etc/open/editcomment.template index 7932a9d0..c5624f80 100755 --- a/etc/open/editcomment.template +++ b/etc/open/editcomment.template @@ -23,6 +23,20 @@ padding-bottom: 0px; padding-top: 0px; } +.pformerrors +{ +margin: none; +border: none; +padding: 8px; +margin-top: 0px; +margin-bottom: 6px; +background-color: #FFFFFF; +border-color: gray; +border-width: 1px; +border-style: solid; +} + + h1 { padding-bottom: 0px; margin-bottom: 0px;} h2 { @@ -145,7 +159,7 @@ function to display error message at the input box // occam, 2003-06-09 -${lang(e.message + "." + e.field)} +${lang(e.message)} @@ -163,12 +177,19 @@ ${lang("comment.note")} ${lang("comment.formtitle")} +
+ + +

+${lang("content.errors")} +

+
Your input had the following errors:

- ${lang("content."+e.field)}: + ${lang("comment."+e.field)}: ${lang(e.message)}
@@ -176,13 +197,11 @@ ${lang("comment.formtitle")}
+
- - -

-${lang("posting.step01")} +${lang("content.step01")}

@@ -210,7 +229,7 @@ ${lang("comment.name")}

-${lang("comment.text")} +${lang("comment.description")}

@@ -221,7 +240,7 @@ ${lang("comment.text")}

-${lang("posting.step02")} +${lang("content.step02")}

@@ -266,7 +285,7 @@ ${lang("comment.language")}

-${lang("posting.step03")} +${lang("content.step03")}

@@ -277,10 +296,10 @@ ${lang("posting.step03")}

${utility.encodeHTML(a.filename)}

- ${lang("posting.media.cancel")} + ${lang("content.media.cancel")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}

@@ -290,42 +309,42 @@ ${lang("posting.step03")} - + - + - + @@ -336,7 +355,7 @@ ${lang("posting.step03")}

- ${lang("posting.media.ftpmedia")} + ${lang("content.media.ftpmedia")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}


- ${lang("posting.media.ftpmedia")} + ${lang("content.media.ftpmedia")}

- ${lang("posting.media.title")} + ${lang("content.media.title")}

@@ -366,9 +385,19 @@ ${lang("posting.step03")}

-${lang("posting.step04")} +${lang("content.step04")}

+ +
+ + +

${lang("content.password")}

+ +

+ + +

diff --git a/lib/gnu-regexp-1.1.4.jar b/lib/gnu-regexp-1.1.4.jar deleted file mode 100755 index c3c8770b..00000000 Binary files a/lib/gnu-regexp-1.1.4.jar and /dev/null differ diff --git a/lib/jcaptcha-all-1.0-RC6.jar b/lib/jcaptcha-all-1.0-RC6.jar new file mode 100644 index 00000000..6be71a3f Binary files /dev/null and b/lib/jcaptcha-all-1.0-RC6.jar differ diff --git a/lib/pja-2.5.jar b/lib/pja-2.5.jar new file mode 100644 index 00000000..9d0cbf2a Binary files /dev/null and b/lib/pja-2.5.jar differ diff --git a/lib/pjatools-2.5.jar b/lib/pjatools-2.5.jar new file mode 100644 index 00000000..3365df4e Binary files /dev/null and b/lib/pjatools-2.5.jar differ diff --git a/source/mir/config/MirPropertiesConfiguration.java b/source/mir/config/MirPropertiesConfiguration.java index 71d41324..dff05610 100755 --- a/source/mir/config/MirPropertiesConfiguration.java +++ b/source/mir/config/MirPropertiesConfiguration.java @@ -46,21 +46,18 @@ public class MirPropertiesConfiguration extends ExtendedProperties { private File home; - /** - * Constructor for MirPropertiesConfiguration. - */ - private MirPropertiesConfiguration(ServletContext ctx) throws IOException { + private MirPropertiesConfiguration(ServletContext aContext) throws IOException { //loading the defaults-config - super(ctx.getRealPath("/WEB-INF/") + "/default.properties"); + super(aContext.getRealPath("/WEB-INF/") + "/default.properties"); //loading the user-config ExtendedProperties userConfig = - new ExtendedProperties(ctx.getRealPath("/WEB-INF/etc/") + "/config.properties"); + new ExtendedProperties(aContext.getRealPath("/WEB-INF/etc/") + "/config.properties"); //merging them to one config while overriding the defaults this.combine(userConfig); - home = new File(ctx.getRealPath("/WEB-INF/")+"/"); + home = new File(aContext.getRealPath("/WEB-INF/")+"/"); } public static synchronized MirPropertiesConfiguration instance() { @@ -100,6 +97,7 @@ public class MirPropertiesConfiguration extends ExtendedProperties { /** * Returns all properties in a Map + * * @return Map */ public Map allSettings() { diff --git a/source/mir/servlet/ServletModuleFailure.java b/source/mir/servlet/ServletModuleFailure.java index b8699847..c3a2f1d2 100755 --- a/source/mir/servlet/ServletModuleFailure.java +++ b/source/mir/servlet/ServletModuleFailure.java @@ -38,4 +38,8 @@ public class ServletModuleFailure extends Failure { public ServletModuleFailure(Throwable aCause) { this (aCause.getMessage(), aCause); } + + public ServletModuleFailure(String aMessage) { + super(aMessage, null); + } } diff --git a/source/mir/session/HTTPAdapters.java b/source/mir/session/HTTPAdapters.java index 4b50f56b..cbeead50 100755 --- a/source/mir/session/HTTPAdapters.java +++ b/source/mir/session/HTTPAdapters.java @@ -183,6 +183,11 @@ public class HTTPAdapters { public HTTPSessionAdapter(HttpSession aSession) { session = aSession; } + + public String getId() { + return session.getId(); + } + public Object getAttribute(String aName) { return session.getAttribute(aName); } diff --git a/source/mir/session/Session.java b/source/mir/session/Session.java index 37ddd699..315cae9a 100755 --- a/source/mir/session/Session.java +++ b/source/mir/session/Session.java @@ -28,6 +28,7 @@ package mir.session; public interface Session { + public String getId(); public Object getAttribute(String aName); public void setAttribute(String aName, Object aNewValue); public void deleteAttribute(String aName); diff --git a/source/mir/util/FileRoutines.java b/source/mir/util/FileRoutines.java index ac1d4c18..06de92a9 100755 --- a/source/mir/util/FileRoutines.java +++ b/source/mir/util/FileRoutines.java @@ -27,9 +27,22 @@ */ package mir.util; -import gnu.regexp.RE; - -import java.io.*; +import org.apache.oro.text.regex.MalformedPatternException; +import org.apache.oro.text.regex.Pattern; +import org.apache.oro.text.regex.Perl5Compiler; +import org.apache.oro.text.regex.Perl5Matcher; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -51,16 +64,15 @@ public class FileRoutines { inputStream = new BufferedInputStream(new FileInputStream(aSourceFile)); try { - File directory = new File(aDestinationFile.getParent()); - if (directory != null && !directory.exists()) { - directory.mkdirs(); - } + createParentDirectories(aDestinationFile); + outputStream = new BufferedOutputStream(new FileOutputStream(aDestinationFile), 8192); try { do { nrBytesRead = inputStream.read(buffer); - if (nrBytesRead > 0) + if (nrBytesRead > 0) { outputStream.write(buffer, 0, nrBytesRead); + } } while (nrBytesRead >= 0); } @@ -162,19 +174,18 @@ public class FileRoutines { } public static class RegExpFileFilter implements FilenameFilter { - private RE expression; + private Pattern expression; - public RegExpFileFilter(String anExpression) { - try { - expression = new RE(anExpression); - } - catch (Throwable t) { - throw new RuntimeException(t.getMessage()); - } + public RegExpFileFilter(String anExpression) throws MalformedPatternException { + Perl5Compiler compiler = new Perl5Compiler(); + + expression = compiler.compile(anExpression, Perl5Compiler.READ_ONLY_MASK); } public boolean accept(File aDir, String aName) { - return expression.isMatch(aName) && !new File(aDir, aName).isDirectory(); + Perl5Matcher matcher = new Perl5Matcher(); + + return !new File(aDir, aName).isDirectory() && matcher.matches(aName, expression); } } @@ -205,17 +216,22 @@ public class FileRoutines { } /** - * Return the extension of a path. (e.g. getExtension("example.txt") will + * Returns the extension of a path. (e.g. getExtension("example.txt") will * return "txt" */ public static String getExtension(String aPath) { int position = aPath.lastIndexOf('.'); + if (position >= 0) { return aPath.substring(position + 1); } + return ""; } + /** + * Returns true if the given path is absolute + */ public static boolean isAbsolutePath(String aPath) { return new File(aPath).isAbsolute(); } @@ -248,27 +264,24 @@ public class FileRoutines { return result.toByteArray(); } - /** - * Reads the content of a file into an array of bytes - */ - public static void writeByteArrayIntoFile(byte[] anArray, File aFile) throws IOException { - OutputStream output = new FileOutputStream(aFile); - - try { - ByteArrayInputStream input = new ByteArrayInputStream(anArray); - try { - IORoutines.copyStream(input, output); - } - finally { - input.close(); - } - } - finally { - output.close(); - } - } - - + /** + * Reads the content of a file into an array of bytes + */ + public static void writeByteArrayIntoFile(byte[] anArray, File aFile) throws IOException { + OutputStream output = new FileOutputStream(aFile); + try { + ByteArrayInputStream input = new ByteArrayInputStream(anArray); + try { + IORoutines.copyStream(input, output); + } + finally { + input.close(); + } + } + finally { + output.close(); + } + } /** * Creates all parent directories of a file if they do not exist diff --git a/source/mir/util/ParameterExpander.java b/source/mir/util/ParameterExpander.java index 3077611a..0dbd4b33 100755 --- a/source/mir/util/ParameterExpander.java +++ b/source/mir/util/ParameterExpander.java @@ -42,10 +42,6 @@ import multex.Exc; import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.beanutils.PropertyUtils; -/** - * Class to work with expressions. Will be gradually phased out and replaced - * with {@link mir.util.expressions.ExpressionParser} - */ public class ParameterExpander { final static String NODE_SEPARATOR = "."; final static char STRING_ESCAPE_CHARACTER = '\\'; @@ -810,18 +806,16 @@ public class ParameterExpander { } private int interpretAsInteger(Object aValue) { - if (aValue instanceof Integer) + if (aValue instanceof Integer) { return ((Integer) aValue).intValue(); - - if (aValue instanceof String) { - try { - return Integer.parseInt((String) aValue); - } - catch (Throwable t) { - } } - throw new RuntimeException("Not an integer"); + try { + return Integer.parseInt(aValue.toString()); + } + catch (NumberFormatException t) { + throw new RuntimeException("Not an integer"); + } } private String interpretAsString(Object aValue) { @@ -888,14 +882,18 @@ public class ParameterExpander { if (aToken instanceof ConcatenateToken) return interpretAsString(aValue1) + interpretAsString(aValue2); - if (aToken instanceof LessThanOrEqualsToken) + if (aToken instanceof LessThanOrEqualsToken) { return new Boolean(interpretAsInteger(aValue1) <= interpretAsInteger(aValue2)); - if (aToken instanceof LessThanToken) + } + if (aToken instanceof LessThanToken) { return new Boolean(interpretAsInteger(aValue1) < interpretAsInteger(aValue2)); - if (aToken instanceof GreaterThanOrEqualsToken) + } + if (aToken instanceof GreaterThanOrEqualsToken) { return new Boolean(interpretAsInteger(aValue1) >= interpretAsInteger(aValue2)); - if (aToken instanceof GreaterThanToken) + } + if (aToken instanceof GreaterThanToken) { return new Boolean(interpretAsInteger(aValue1) > interpretAsInteger(aValue2)); + } throw new RuntimeException("Internal error: unknown binary operator: " + aToken.getClass().getName()); } diff --git a/source/mir/util/SimpleParser.java b/source/mir/util/SimpleParser.java index 4b0b1482..92a806be 100755 --- a/source/mir/util/SimpleParser.java +++ b/source/mir/util/SimpleParser.java @@ -30,98 +30,111 @@ package mir.util; -import gnu.regexp.RE; -import gnu.regexp.REException; -import gnu.regexp.REMatch; -import multex.Exc; import multex.Failure; +import org.apache.oro.text.regex.*; /** * Simple parser. Can be used to parse a String based using * regular epxression. */ public class SimpleParser { - private String data; private int position; + private Perl5Compiler compiler = new Perl5Compiler(); + private Perl5Matcher matcher = new Perl5Matcher(); + private PatternMatcherInput input; + + /** - * Initialize a new SimpleParser, with aData + * Initialize a new SimpleParser, with someData * as the text to parse. + * + * @param someData the text to parse */ - public SimpleParser(String aData) { - data=aData; - position=0; + public SimpleParser(String someData) { + position = 0; + input = new PatternMatcherInput(someData); } /** * Parses a regular expression. Uses suppled aMessage parameter * in case of an error. + * + * @param aRegularExpression the expression to find at the cursor position + * @param aMessage the error message to apply if the regular expression couldn't be found + * + * @return the text that matched the regular expression + * + * @throws mir.util.SimpleParser.UnExpectedTokenExc + * if the token wasn't found. aMessage will be used in the + * exception's message */ - public String parse(RE aRegularExpression, String aMessage) throws SimpleParserExc { - REMatch match = aRegularExpression.getMatch(data, position); + public String parse(Pattern aRegularExpression, String aMessage) throws UnExpectedTokenExc { + input.setCurrentOffset(position); + if ( matcher.contains(input, aRegularExpression) && input.getMatchBeginOffset() == position) { + position = input.getMatchEndOffset(); - if (match==null || match.getStartIndex()!=position) { - throw new SimpleParserExc(aMessage+" at position "+position+" in '"+data+"'"); + return input.match(); + } + else { + throw new UnExpectedTokenExc(aMessage + " at position " + + position + " in '" + input.toString() + "'"); } - - position=match.getEndIndex(); - - return match.toString(); } /** * Attempts to match the data right after the parsing position to * a regular expression * - * @throws SimpleParserExc if no match could be found for the given regular + * @throws UnExpectedTokenExc if no match could be found for the given regular * expression. */ - public String parse(RE aRegularExpression) throws SimpleParserExc { - return parse( aRegularExpression, "No match found for '"+aRegularExpression.toString()+"'"); + public String parse(Pattern aRegularExpression) throws UnExpectedTokenExc { + return parse( aRegularExpression, "No match found for '" + aRegularExpression.getPattern() + "'"); } /** - * Attempts to skip data at the parsing position matching the supplied regular expression + * Attempts to skip data at the parsing position matching the supplied regular expression. + * If no match is found, the method will simply return * - * @throws SimpleParserExc if no match could be found for the given regular - * expression. + * @param aRegularExpression the expression to find and skip at the parsing position. */ - public void skip(RE aRegularExpression) throws SimpleParserExc { - REMatch match = aRegularExpression.getMatch(data, position); - - if (match!=null && match.getStartIndex()==position) - position=match.getEndIndex(); + public void skip(Pattern aRegularExpression) { + input.setCurrentOffset(position); + + if (matcher.contains(input, aRegularExpression) && + input.getMatchBeginOffset() == position) { + position = input.getMatchEndOffset(); + } } /** * Returns true if the data at the parsing position matches the given * regular expression. */ - public boolean parses(String anExpression) throws SimpleParserExc { + public boolean parses(String anExpression) throws MalformedRegularExpressionExc { try { - return parses(new RE(anExpression)); - } - catch (SimpleParserExc e) { - throw e; - } - catch (REException e) { - throw new SimpleParserFailure( "Error compiling regular expression '" + anExpression + "': " + e.getMessage(), e); + return parses(compiler.compile(anExpression)); } - catch (Throwable t) { - throw new SimpleParserFailure( t ); + catch (MalformedPatternException e) { + throw new MalformedRegularExpressionExc(e); } } /** - * Returns true if the data at the parsing position matches the given + * Tests whether the data at the parsing position matches a given * regular expression. + * + * @param aRegularExpression the pattern to look for + * @return returns true if the regular expression is found at the + * parsing position */ - public boolean parses(RE aRegularExpression) throws SimpleParserExc { - REMatch match = aRegularExpression.getMatch(data, position); + public boolean parses(Pattern aRegularExpression) { + input.setCurrentOffset(position); - return (match!=null && match.getStartIndex()==position) ; + return matcher.contains(input, aRegularExpression) && input.getMatchBeginOffset() == position; } /** @@ -131,18 +144,12 @@ public class SimpleParser { * @throws SimpleParserExc if no match could be found for the given regular * expression. */ - public String parse(String anExpression) throws SimpleParserExc, SimpleParserFailure { + public String parse(String anExpression) throws MalformedRegularExpressionExc, UnExpectedTokenExc { try { - return parse(new RE(anExpression)); - } - catch (SimpleParserExc e) { - throw e; - } - catch (REException e) { - throw new SimpleParserFailure( "Error compiling regular expression '" + anExpression + "': " + e.getMessage(), e); + return parse(compiler.compile(anExpression)); } - catch (Throwable t) { - throw new SimpleParserFailure( t ); + catch (MalformedPatternException e) { + throw new MalformedRegularExpressionExc(e); } } @@ -151,18 +158,12 @@ public class SimpleParser { * Parses text at the current parsing position matching the given anExpression. * Will apply the supplied message to an exception if no match could be found. */ - public String parse(String anExpression, String aMessage) throws SimpleParserExc, SimpleParserFailure { + public String parse(String anExpression, String aMessage) throws MalformedRegularExpressionExc, UnExpectedTokenExc { try { - return parse(new RE(anExpression), aMessage); + return parse(compiler.compile(anExpression), aMessage); } - catch (SimpleParserExc e) { - throw e; - } - catch (REException e) { - throw new SimpleParserFailure( "Error compiling regular expression '" + anExpression + "': " + e.getMessage(), e); - } - catch (Throwable t) { - throw new SimpleParserFailure( t ); + catch (MalformedPatternException e) { + throw new MalformedRegularExpressionExc(e); } } @@ -170,18 +171,12 @@ public class SimpleParser { * Skips (i.e. discards) text matching the supplied regular expression */ - public void skip(String anExpression) throws SimpleParserExc, SimpleParserFailure { + public void skip(String anExpression) throws MalformedRegularExpressionExc { try { - skip(new RE(anExpression)); - } - catch (SimpleParserExc e) { - throw e; + skip(compiler.compile(anExpression)); } - catch (REException e) { - throw new SimpleParserFailure( "Error compiling regular expression '" + anExpression + "': " + e.getMessage(), e); - } - catch (Throwable t) { - throw new SimpleParserFailure( t ); + catch (MalformedPatternException e) { + throw new MalformedRegularExpressionExc(e); } } @@ -189,14 +184,14 @@ public class SimpleParser { * returns true if the parser is at the end of the data */ public boolean isAtEnd() { - return position>=data.length(); + return position >=input.getEndOffset(); } /** * Returns the "remaining" data: the data after the current position */ public String remainingData() { - return data.substring(position); + return input.toString().substring(input.getEndOffset()); } /** @@ -216,9 +211,34 @@ public class SimpleParser { /** * Checked exception thrown from SimpleParser */ - public static class SimpleParserExc extends Exc { + public static class SimpleParserExc extends Exception { + protected SimpleParserExc(String aMessage, Throwable aCause) { + super(aMessage, aCause); + } + + public SimpleParserExc(Throwable aCause) { + super(aCause); + } + public SimpleParserExc(String aMessage) { super(aMessage); } } + + public static class MalformedRegularExpressionExc extends SimpleParserExc { + public MalformedRegularExpressionExc(String aMessage, Throwable aCause) { + super(aMessage, aCause); + } + + public MalformedRegularExpressionExc(Throwable aCause) { + super(aCause); + } + } + + public static class UnExpectedTokenExc extends SimpleParserExc { + public UnExpectedTokenExc(String aMessage) { + super(aMessage); + } + } + } \ No newline at end of file diff --git a/source/mir/util/StringRoutines.java b/source/mir/util/StringRoutines.java index 6757bdfd..55d5edfd 100755 --- a/source/mir/util/StringRoutines.java +++ b/source/mir/util/StringRoutines.java @@ -29,7 +29,7 @@ */ package mir.util; -import gnu.regexp.RE; +import org.apache.oro.text.regex.*; import java.util.ArrayList; import java.util.List; @@ -85,8 +85,6 @@ public class StringRoutines { return result.toString(); } - /** - */ public static String replaceEscapedStringCharacters(String aText, char anEscapeCharacter, char[] aCharactersToReplace, String[] aStringsToSubstitute) { if (aText==null) @@ -158,14 +156,13 @@ public class StringRoutines { public static String performRegularExpressionReplacement(String aSource, String aSearchExpression, String aReplacement) { try { - RE regularExpression; - - regularExpression = new RE(aSearchExpression); + Pattern pattern = new Perl5Compiler().compile(aSearchExpression); - return regularExpression.substituteAll(aSource, aReplacement); + return Util.substitute( + new Perl5Matcher(), pattern, new Perl5Substitution(aReplacement), aSource, Util.SUBSTITUTE_ALL); } - catch (Throwable t) { - throw new UtilFailure("StringRoutines.performRegularExpressionReplacement: " + t.toString(), t); + catch (MalformedPatternException t) { + throw new UtilFailure("Invalid regular expression", t); } } diff --git a/source/mircoders/entity/EntityComment.java b/source/mircoders/entity/EntityComment.java index 2e9e8db9..b2b0f491 100755 --- a/source/mircoders/entity/EntityComment.java +++ b/source/mircoders/entity/EntityComment.java @@ -41,7 +41,7 @@ import mircoders.storage.DatabaseContent; * This class maps one line of the comment-table to a java-object. * * @author $Author: zapata $ - * @version $Revision: 1.16.2.7 $ $Date: 2005/10/30 00:46:58 $ + * @version $Revision: 1.16.2.8 $ $Date: 2007/12/15 00:24:43 $ */ @@ -53,26 +53,6 @@ public class EntityComment extends AbstractEntity { } /** - * overridden method setFieldValues to patch creator_main_url - */ - public void setFieldValues(Map theStringValues) - { - if (theStringValues != null) { - if (theStringValues.containsKey("main_url")){ - if (((String)theStringValues.get("main_url")).equalsIgnoreCase("http://")) { - theStringValues.remove("main_url"); - } - else if ((!((String)theStringValues.get("main_url")).startsWith("http://")) - && ((String)theStringValues.get("main_url")).length()>0) { - theStringValues.put("main_url","http://"+((String)theStringValues.get("main_url"))); - } - } - - } - super.setFieldValues(theStringValues); - } - - /** * Deattaches media from a comment */ public void dettach(String aCommentId,String aMediaId) throws DatabaseFailure { diff --git a/source/mircoders/entity/EntityContent.java b/source/mircoders/entity/EntityContent.java index 96ab2dc9..64488d49 100755 --- a/source/mircoders/entity/EntityContent.java +++ b/source/mircoders/entity/EntityContent.java @@ -30,21 +30,19 @@ package mircoders.entity; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Map; - import mir.entity.AbstractEntity; -import mir.log.LoggerWrapper; import mir.storage.DatabaseFailure; import mircoders.storage.DatabaseContentToMedia; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; + /** * this class implements mapping of one line of the database table content * to a java object * - * @version $Id: EntityContent.java,v 1.19.2.12 2005/10/30 00:46:58 zapata Exp $ + * @version $Id: EntityContent.java,v 1.19.2.13 2007/12/15 00:24:43 zapata Exp $ * @author mir-coders group * */ @@ -54,8 +52,7 @@ public class EntityContent extends AbstractEntity { /** * set is_produced flag for the article */ - public void setProduced(boolean yesno) throws DatabaseFailure - { + public void setProduced(boolean yesno) throws DatabaseFailure { String value = (yesno) ? "1":"0"; if (value.equals( getFieldValue("is_produced") )) return; @@ -85,8 +82,7 @@ public class EntityContent extends AbstractEntity { * @param aMediaId * @throws DatabaseFailure */ - public void dettach(String anArticleId, String aMediaId) throws DatabaseFailure - { + public void dettach(String anArticleId, String aMediaId) throws DatabaseFailure { if (aMediaId!=null){ DatabaseContentToMedia.getInstance().delete(anArticleId, aMediaId); @@ -98,9 +94,8 @@ public class EntityContent extends AbstractEntity { * Attaches media to the article */ - public void attach(String aMediaId) throws DatabaseFailure - { - if (aMediaId!=null) { + public void attach(String aMediaId) throws DatabaseFailure { + if (aMediaId != null) { DatabaseContentToMedia.getInstance().addMedia(getId(),aMediaId); setProduced(false); } @@ -108,21 +103,4 @@ public class EntityContent extends AbstractEntity { getLogger().error("EntityContent: attach without mid"); } } - - /** - * overridden method setFieldValues to patch creator_main_url - */ - public void setFieldValues(Map theStringValues) { - if (theStringValues != null) { - if (theStringValues.containsKey("creator_main_url")){ - if (((String)theStringValues.get("creator_main_url")).equalsIgnoreCase("http://")){ - theStringValues.remove("creator_main_url"); - } - else if (!((String)theStringValues.get("creator_main_url")).startsWith("http://")){ - theStringValues.put("creator_main_url","http://"+((String)theStringValues.get("creator_main_url"))); - } - } - } - super.setFieldValues(theStringValues); - } } diff --git a/source/mircoders/global/Abuse.java b/source/mircoders/global/Abuse.java index 697d6e21..ea72ded6 100755 --- a/source/mircoders/global/Abuse.java +++ b/source/mircoders/global/Abuse.java @@ -249,7 +249,7 @@ public class Abuse { openPostingDisabled = anOpenPostingDisabled; } - public boolean getOpenPostingPassword() { + public boolean getRequireCaptcha() { return openPostingPassword; } @@ -382,7 +382,7 @@ public class Abuse { ExtendedProperties configuration = new ExtendedProperties(); configuration.addProperty("abuse.openPostingDisabled", getOpenPostingDisabled() ? "1" : "0"); - configuration.addProperty("abuse.openPostingPassword", getOpenPostingPassword() ? "1" : "0"); + configuration.addProperty("abuse.openPostingPassword", getRequireCaptcha() ? "1" : "0"); configuration.addProperty("abuse.cookieOnBlock", getCookieOnBlock() ? "1" : "0"); configuration.addProperty("abuse.logEnabled", getLogEnabled() ? "1" : "0"); configuration.addProperty("abuse.logSize", Integer.toString(getLogSize())); diff --git a/source/mircoders/localizer/LocalizerCache.java b/source/mircoders/localizer/LocalizerCache.java index 647e1e50..f6a09526 100755 --- a/source/mircoders/localizer/LocalizerCache.java +++ b/source/mircoders/localizer/LocalizerCache.java @@ -125,7 +125,6 @@ public class LocalizerCache implements MirLocalizer { return adapterModel; } - } private static class MirCachingGeneratorLocalizer implements MirGeneratorLocalizer { diff --git a/source/mircoders/localizer/MirOpenPostingLocalizer.java b/source/mircoders/localizer/MirOpenPostingLocalizer.java index 875309d0..023837ad 100755 --- a/source/mircoders/localizer/MirOpenPostingLocalizer.java +++ b/source/mircoders/localizer/MirOpenPostingLocalizer.java @@ -30,6 +30,7 @@ package mircoders.localizer; import java.util.List; +import java.awt.image.BufferedImage; import mir.session.Request; import mir.session.Session; @@ -68,4 +69,15 @@ public interface MirOpenPostingLocalizer { * not used by default by the production subsystem */ public boolean allowArticlePublication(EntityContent anArticle); + + + /** + * Generate a captcha with given id. + */ + public Captcha generateCaptcha(String someId); + + public interface Captcha { + BufferedImage getChallenge(); + boolean validateAnswer(String anAnswer); + } } diff --git a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java index ccdb4a88..8d09adc0 100755 --- a/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java @@ -259,10 +259,12 @@ public class MirBasicAdminInterfaceLocalizer implements MirAdminInterfaceLocaliz (new GregorianCalendar()).getTime(), MirGlobal.config().getString("Mir.DefaultTimezone"))); line.append(" "); - if (aUser != null) + if (aUser != null) { line.append(aUser.get("login")); - else - line.append("unknown"); + } + else { + line.append("system"); + } line.append(" "); line.append(getName()); diff --git a/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java b/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java index c3f42e49..6fad3a43 100755 --- a/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java +++ b/source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java @@ -152,6 +152,7 @@ public class MirBasicArticlePostingHandler extends MirBasicPostingSessionHandler id = article.insert(); if (id == null) { logger.info("Duplicate article rejected"); + throw new DuplicatePostingExc("Duplicate article rejected"); } aSession.setAttribute("content", article); diff --git a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java index 82b36e9c..688f1300 100755 --- a/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java @@ -34,13 +34,7 @@ import mir.log.LoggerWrapper; import mir.session.Request; import mir.session.Session; import mir.session.SessionHandler; -import mircoders.abuse.FilterType; -import mircoders.abuse.IPFilterType; -import mircoders.abuse.RegularExpressionFilterType; -import mircoders.abuse.SubStringFilterType; -import mircoders.abuse.ThrottleFilter; -import mircoders.abuse.PostingSizeFilterType; -import mircoders.abuse.URLBlacklistFilterType; +import mircoders.abuse.*; import mircoders.entity.EntityComment; import mircoders.entity.EntityContent; import mircoders.global.MirGlobal; @@ -49,14 +43,11 @@ import mircoders.localizer.MirLocalizerExc; import mircoders.localizer.MirLocalizerFailure; import mircoders.localizer.MirOpenPostingLocalizer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.Arrays; +import java.util.*; +import java.awt.image.BufferedImage; + +import com.octo.captcha.service.image.DefaultManageableImageCaptchaService; +import com.octo.captcha.service.image.ImageCaptchaService; public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { private List afterContentProducerTasks; @@ -65,6 +56,7 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { private Map filterTypesMap; protected LoggerWrapper logger; protected MirPropertiesConfiguration configuration; + private static ImageCaptchaService captchaService = new DefaultManageableImageCaptchaService(); public MirBasicOpenPostingLocalizer() throws MirLocalizerFailure { logger = new LoggerWrapper("Localizer.Basic.OpenPosting"); @@ -172,22 +164,6 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { } } - public String generateOnetimePassword() { - Random r = new Random(); - int random = r.nextInt(); - - long l = System.currentTimeMillis(); - - l = (l*l*l*l)/random; - if (l<0) { - l = l * -1; - } - - String returnString = ""+l; - - return returnString.substring(5); - } - public List getAntiAbuseFilterTypes() { return Collections.unmodifiableList(filterTypes); } @@ -206,4 +182,20 @@ public class MirBasicOpenPostingLocalizer implements MirOpenPostingLocalizer { filterTypesMap.put(aFilterType.getName(), aFilterType); filterTypes.add(aFilterType); } -} + + public Captcha generateCaptcha(final String aSessionId) { + final BufferedImage challenge = captchaService.getImageChallengeForID(aSessionId); + + return new Captcha() { + + public BufferedImage getChallenge() { + return challenge; + } + + public boolean validateAnswer(String anAnswer) { + return captchaService.validateResponseForID(aSessionId, anAnswer).booleanValue(); + } + }; + } + +} \ No newline at end of file diff --git a/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java b/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java index 31822f50..7483a781 100755 --- a/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java +++ b/source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java @@ -38,6 +38,7 @@ import mir.util.FileRoutines; import mir.util.IORoutines; import mircoders.global.MirGlobal; import mircoders.media.UnsupportedMediaTypeExc; +import mircoders.localizer.MirOpenPostingLocalizer; import java.io.*; import java.util.*; @@ -51,7 +52,7 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { protected MirPropertiesConfiguration configuration = MirPropertiesConfiguration.instance(); /** Previously uploaded files */ - protected List attachments; + protected final List attachments = new ArrayList(); /** counter to generate unique field names for uploaded files */ protected int uploadedFileIndex = 0; @@ -63,7 +64,6 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { private boolean persistentUploadedFiles; public MirBasicPostingSessionHandler(boolean aPersistentUploadedFiles) { - attachments = new ArrayList(); persistentUploadedFiles = aPersistentUploadedFiles; } @@ -114,6 +114,7 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { processAttachmentError(aRequest, aSession, attachment, t); } catch (Throwable u) { + logger.error("Error while processing attachment error", u); } logger.error("Error while processing attachment", t); } @@ -161,17 +162,6 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { * when an older session gets re-initiated after a session timeout. */ protected void initializeSession(Request aRequest, Session aSession) throws SessionExc, SessionFailure { - if (MirGlobal.abuse().getOpenPostingPassword()) { - String password = (String) aSession.getAttribute("password"); - if (password==null) { - password = generateOnetimePassword(); - aSession.setAttribute("password", password); - } - } - else { - aSession.deleteAttribute("password"); - } - aSession.setAttribute("referer", aRequest.getHeader("Referer")); } @@ -190,6 +180,8 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { nrMediaItems = Math.min(configuration.getInt("ServletModule.OpenIndy.MaxMediaUploadItems"), Integer.parseInt(aRequest.getParameter("nrmediaitems"))); } catch (Throwable t) { + logger.warn("Error while retrieving configuration setting " + + "ServletModule.OpenIndy.MaxMediaUploadItems", t); } aSession.setAttribute("nrmediaitems", new Integer(nrMediaItems)); @@ -201,7 +193,10 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { aResponse.setResponseValue("nrmediaitems", new Integer(nrMediaItems)); aResponse.setResponseValue("mediaitems", mediaItems); - aResponse.setResponseValue("password", aSession.getAttribute("password")); + + if (MirGlobal.abuse().getRequireCaptcha()) { + aResponse.setResponseValue("password", Boolean.TRUE); + } aResponse.setResponseValue("referer", aSession.getAttribute("referer")); aResponse.setResponseValue("errors", null); @@ -415,10 +410,12 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { * store data, etc */ protected boolean shouldProcessRequest(Request aRequest, Session aSession, List aValidationErrors) throws SessionExc, SessionFailure { - if (aRequest.getParameter("post")==null) + if (aRequest.getParameter("post")==null) { return false; - validate(aValidationErrors, aRequest, aSession); - return (aValidationErrors == null || aValidationErrors.size() == 0); + } + validate(aValidationErrors, aRequest, aSession); + + return (aValidationErrors == null || aValidationErrors.size() == 0); } /** @@ -429,43 +426,23 @@ public abstract class MirBasicPostingSessionHandler implements SessionHandler { * aResults is empty. */ protected void validate(List aResults, Request aRequest, Session aSession) throws SessionExc, SessionFailure { - String password = (String) aSession.getAttribute("password"); - - if (password!=null) { - String submittedPassword= aRequest.getParameter("password").trim(); + if (MirGlobal.abuse().getRequireCaptcha()) { + String submittedPassword = aRequest.getParameter("password"); + MirOpenPostingLocalizer.Captcha captcha = (MirOpenPostingLocalizer.Captcha) aSession.getAttribute("captcha"); - if (!password.equals(submittedPassword)) { - aResults.add(new ValidationError("password", "passwordmismatch")); + if (captcha == null || !captcha.validateAnswer(submittedPassword)) { + aResults.add(new ValidationError("password", "validationerror.passwordmismatch")); } } } - /** - * Method to generate a one-time password - * - * @return a password, to be used once - */ - protected String generateOnetimePassword() { - Random r = new Random(); - int random = r.nextInt(); - - long l = System.currentTimeMillis(); - - l = (l*l*l*l)/random; - if (l<0) - l = l * -1; - - String returnString = ""+l; - - return returnString.substring(5); - } /** * Method to filter the attributes and their values of a request * based on the fields of a database object. */ - protected static final Map getIntersectingValues(Request aRequest, Database aStorage) throws SessionFailure { + protected static Map getIntersectingValues(Request aRequest, Database aStorage) throws SessionFailure { Map result = new HashMap(); Iterator i = aStorage.getFieldNames().iterator(); diff --git a/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java b/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java index 9fbaa048..f79f4d4e 100755 --- a/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java +++ b/source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java @@ -29,7 +29,6 @@ */ package mircoders.localizer.basic; -import gnu.regexp.RE; import mir.config.MirPropertiesConfiguration; import mir.entity.adapter.EntityAdapter; import mir.entity.adapter.EntityIteratorAdapter; @@ -37,10 +36,7 @@ import mir.generator.Generator; import mir.generator.GeneratorExc; import mir.generator.GeneratorFailure; import mir.log.LoggerWrapper; -import mir.util.GeneratorDateTimeFunctions; -import mir.util.GeneratorFormatAdapters; -import mir.util.HTMLStripper; -import mir.util.StringRoutines; +import mir.util.*; import mir.util.generator.ReflectionGeneratorFunctionsAdapter; import mircoders.global.MirGlobal; import mircoders.localizer.MirLocalizerExc; @@ -52,34 +48,60 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.tidy.Configuration; import org.w3c.tidy.Tidy; +import org.apache.oro.text.regex.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringWriter; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantLocalizer { protected LoggerWrapper logger; private HTMLStripper stripper; - private RE regularExpressionLT; - private RE regularExpressionGT; - private RE regularExpressionWhitespace; - private RE regularExpressionLeadingSlashes; - + private Pattern regularExpressionWhitespace; + private Pattern regularExpressionLeadingSlashes; + private Set disallowedAttributes = new HashSet(); + private Set disallowedPrefixes = new HashSet(); + private Set allowedNodes = new HashSet(); + private Set externalPrefixes = new HashSet(); + private Set allowedExternalPrefixes = new HashSet(); + + + public MirBasicProducerAssistantLocalizer() throws MirLocalizerFailure { try { stripper = new HTMLStripper(); + Perl5Compiler compiler = new Perl5Compiler(); + + regularExpressionWhitespace = compiler.compile("\\s+| | ", Perl5Compiler.READ_ONLY_MASK); + regularExpressionLeadingSlashes = compiler.compile("^//+", Perl5Compiler.READ_ONLY_MASK); + + Iterator i = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributes"), ";").iterator(); + while (i.hasNext()) { + disallowedAttributes.add(((String) i.next()).toLowerCase()); + } + + i = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributeValuePrefixes"), ";").iterator(); + while (i.hasNext()) { + disallowedPrefixes.add(((String) i.next()).toLowerCase()); + } + + i = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.Whitelist"), ";").iterator(); + while (i.hasNext()) { + allowedNodes.add(((String) i.next()).toLowerCase()); + } + + i = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.ExternalLocationAttributeValuePrefixes"), ";").iterator(); + while (i.hasNext()) { + externalPrefixes.add(((String) i.next()).toLowerCase()); + } - regularExpressionLT = new RE("<"); - regularExpressionGT = new RE(">"); - regularExpressionWhitespace = new RE("\\s+| | "); - regularExpressionLeadingSlashes = new RE("^//+"); + i = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.WhitelistedExternalLocationAttributeValuePrefixes"), ";").iterator(); + while (i.hasNext()) { + allowedExternalPrefixes.add(((String) i.next()).toLowerCase()); + } } catch (Throwable t) { throw new MirLocalizerFailure(t); @@ -297,60 +319,40 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL } - - private boolean isBadAttr(String attrName) { - List badAttributes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributes"), ";"); - Iterator i = badAttributes.iterator(); - while (i.hasNext()) { - if (((String) i.next()).toLowerCase().equals(attrName.toLowerCase())) { - return true; - } - } - return false; + /** + * Test whether attributes of the given type are acceptable + * + * @param anAttibuteName + * @return true if the attribute is acceptable + */ + private boolean testAttribueName(String anAttibuteName) { + return !disallowedAttributes.contains(anAttibuteName.toLowerCase()); } private String stripWhitespace(String aString) { - try { - return regularExpressionWhitespace.substituteAll(aString, ""); - } - catch (Throwable t) { - return ""; - } + return Util.substitute( + new Perl5Matcher(), regularExpressionWhitespace, new Perl5Substitution(""), aString, Util.SUBSTITUTE_ALL); } - private boolean checkAttr(String attrName) { - if (isBadAttr(attrName)) { - return false; - } - return true; + private boolean testAttibuteValue(String anAttributeValue) { + Iterator i = disallowedPrefixes.iterator(); - } - - private boolean checkAttrValue(String attrValue) { - List badPrefixes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributeValuePrefixes"), ";"); - Iterator i = badPrefixes.iterator(); - while (i.hasNext()) { - if ((stripWhitespace(attrValue.toLowerCase())).startsWith(((String) i.next()).toLowerCase() + ":")) { + while (i.hasNext()) { + // todo: split the attribute value on : and use contains + if ((stripWhitespace(anAttributeValue.toLowerCase())).startsWith(((String) i.next()).toLowerCase() + ":")) { return false; } } + return true; } private boolean checkNode(String nodeName) { - List acceptableNodes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.Whitelist"), ";"); - - Iterator i = acceptableNodes.iterator(); - while (i.hasNext()) { - if (nodeName.equals(i.next())) { - return true; - } - } - return false; + return allowedNodes.contains(nodeName.toLowerCase()); } - private boolean checkAttrInContext(String nodeName,String attrName,String attrValue){ + private boolean testAttributeInContext(String aTag, String anAttibute, String aValue){ /* The intent here is to prevent external content from being loaded by the user's browser. It's extra paranoid, so will strip some legitimate stuff like an alt="http://www.indymedia.org" */ @@ -358,35 +360,43 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL return true; } else { - if ((nodeName.toLowerCase()).equals("a") && (attrName.toLowerCase()).equals("href") || (nodeName.toLowerCase()).equals("form") && (attrName.toLowerCase()).equals("action")){ - return true; //because we still love the web, even if it doesn't return the favor + if (("a".equalsIgnoreCase(aTag) && "href".equalsIgnoreCase(anAttibute)) || + ("form".equalsIgnoreCase(aTag) && "action".equalsIgnoreCase(anAttibute))) { + // because we still love the web, even if it doesn't return the favor + + return true; } else { - List externalPrefixes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.ExternalLocationAttributeValuePrefixes"), ";"); - List whitelist = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.WhitelistedExternalLocationAttributeValuePrefixes"), ";"); - Iterator i = externalPrefixes.iterator(); - while (i.hasNext()) { - if ((stripWhitespace(attrValue.toLowerCase())).startsWith(((String) i.next()).toLowerCase())) { - // we have hit a bad prefix, but we need to check the whitelist - Iterator wl=whitelist.iterator(); - while (wl.hasNext()){ - if ((stripWhitespace(attrValue.toLowerCase())).startsWith(((String) wl.next()).toLowerCase())) { - return true; //say, for example, something on a trusted server + String value = stripWhitespace(aValue.toLowerCase()); + + Iterator i = externalPrefixes.iterator(); + while (i.hasNext()) { + if (value.startsWith((String) i.next())) { + // we have hit a bad prefix, but we need to check the whitelist + Iterator wl = allowedExternalPrefixes.iterator(); + while (wl.hasNext()) { + if (value.startsWith((String) wl.next())) { + return true; + } + } + } + + return false; //don't let this attribute through } - } - return false; //don't let this attribute through - } - } - return true; //didn't seem to be an external prefix, so it's fine + + return true; //didn't seem to be an external prefix, so it's fine } } } + private void print(Node node, StringWriter out) throws IOException { if (node == null) { return; } int type = node.getNodeType(); - boolean canOutput = checkNode(node.getNodeName()); + + // will this node be present in the output? + boolean keepNode = checkNode(node.getNodeName()); switch (type) { @@ -397,7 +407,7 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL break; case Node.ELEMENT_NODE: - if (canOutput) { + if (keepNode) { out.write('<'); out.write(node.getNodeName()); @@ -406,11 +416,14 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL for (int i = 0; i < attrs.getLength(); i++) { String attrName = attrs.item(i).getNodeName(); String attrValue = attrs.item(i).getNodeValue(); - if (attrValue.startsWith("//")){ - attrValue=regularExpressionLeadingSlashes.substitute(attrValue, "/"); - } + + // todo: what is this? + if (attrValue.startsWith("//")){ + attrValue = Util.substitute( + new Perl5Matcher(), regularExpressionLeadingSlashes, new Perl5Substitution("/"), attrValue); + } - if (checkAttr(attrName) && checkAttrValue(attrValue) && checkAttrInContext(node.getNodeName(),attrName,attrValue)) { + if (testAttribueName(attrName) && testAttibuteValue(attrValue) && testAttributeInContext(node.getNodeName(), attrName, attrValue)) { out.write(' '); out.write(attrs.item(i).getNodeName()); out.write("=\""); @@ -420,11 +433,17 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL } } + // nodes without children will use the shorthand form
. Some browsers + // treat

as a double linebreak if (node.getChildNodes() == null || node.getChildNodes().getLength() == 0) { out.write("/"); + out.write('>'); + break; } out.write('>'); } + + NodeList children = node.getChildNodes(); if (children != null) { int len = children.getLength(); @@ -432,27 +451,19 @@ public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantL print(children.item(i), out); } } - break; - case Node.TEXT_NODE: - String value = node.getNodeValue(); - try { - value = regularExpressionLT.substituteAll(value, "<"); - value = regularExpressionGT.substituteAll(value, ">"); - } - catch (Throwable t) { - value = ""; + if (keepNode) { + out.write("'); } - out.write(value); break; - } + case Node.TEXT_NODE: + out.write(HTMLRoutines.encodeHTML(node.getNodeValue())); - if (type == Node.ELEMENT_NODE && canOutput && node.getChildNodes() != null && node.getChildNodes().getLength() > 0) { - out.write("'); + break; } out.flush(); diff --git a/source/mircoders/pdf/PDFGenerator.java b/source/mircoders/pdf/PDFGenerator.java index 8405ae0b..4514d008 100755 --- a/source/mircoders/pdf/PDFGenerator.java +++ b/source/mircoders/pdf/PDFGenerator.java @@ -29,47 +29,31 @@ */ package mircoders.pdf; -import gnu.regexp.RE; -import gnu.regexp.REException; -import gnu.regexp.REMatch; -import gnu.regexp.REMatchEnumeration; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.*; - +import com.lowagie.text.*; +import com.lowagie.text.pdf.*; import mir.config.MirPropertiesConfiguration; import mir.entity.EntityBrowser; import mir.entity.adapter.EntityAdapter; +import mir.generator.GeneratorExc; +import mir.generator.GeneratorHelper; import mir.log.LoggerWrapper; import mir.misc.StringUtil; import mir.util.DateTimeRoutines; import mir.util.HTMLRoutines; import mir.util.ParameterExpander; -import mir.generator.GeneratorHelper; -import mir.generator.GeneratorExc; import mircoders.entity.EntityContent; import mircoders.entity.EntityImages; -import mircoders.storage.DatabaseImages; import mircoders.global.MirGlobal; import mircoders.localizer.MirLocalizerExc; - -import com.lowagie.text.BadElementException; -import com.lowagie.text.Document; -import com.lowagie.text.DocumentException; -import com.lowagie.text.Element; -import com.lowagie.text.Font; -import com.lowagie.text.Image; -import com.lowagie.text.PageSize; -import com.lowagie.text.Paragraph; -import com.lowagie.text.Phrase; -import com.lowagie.text.pdf.BaseFont; -import com.lowagie.text.pdf.ColumnText; -import com.lowagie.text.pdf.PdfContentByte; -import com.lowagie.text.pdf.PdfTemplate; -import com.lowagie.text.pdf.PdfWriter; +import mircoders.storage.DatabaseImages; import multex.Failure; +import org.apache.oro.text.regex.*; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.util.*; +import java.util.List; public class PDFGenerator { public Document document; @@ -120,6 +104,46 @@ public class PDFGenerator { public int bigImageCaptionFontFamily; protected MirPropertiesConfiguration configuration; + private static Pattern nobackslashr; + private static Pattern HxTag; + private static Pattern ListItemTag; + private static Pattern ListTag; + private static Pattern DivTag; + private static Pattern PTag; + private static Pattern PTagClose; + private static Pattern BRTag; + private static Pattern ATagAll; + private static Pattern noTags; + private static Pattern re1; + private static Pattern re2; + private static Pattern re3; + + static { + Perl5Compiler compiler = new Perl5Compiler(); + + try { + Pattern nobackslashr = compiler.compile("\r"); + + HxTag = compiler.compile("]*>", Perl5Compiler.READ_ONLY_MASK + + Perl5Compiler.CASE_INSENSITIVE_MASK ); + ListItemTag = compiler.compile("]*>", Perl5Compiler.CASE_INSENSITIVE_MASK); + ListTag = compiler.compile("<(u|o)l[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK); + DivTag = compiler.compile("]*>", Perl5Compiler.CASE_INSENSITIVE_MASK); + PTag = compiler.compile("<(p|P)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK); + PTagClose = compiler.compile("]*)?>", Perl5Compiler.READ_ONLY_MASK); + BRTag = compiler.compile("<(br|BR)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK); + ATagAll = compiler.compile("]*href=(?:\"|\')([^#\"\'][^\'\"]+)(?:\"|\')[^>]*>(.*?)", + Perl5Compiler.READ_ONLY_MASK + + Perl5Compiler.CASE_INSENSITIVE_MASK ); + noTags = compiler.compile("<[^>]*>", Perl5Compiler.READ_ONLY_MASK); + re1 = compiler.compile("\r?\n\r?\n", Perl5Compiler.READ_ONLY_MASK); + re2 = compiler.compile("\r?\n", Perl5Compiler.READ_ONLY_MASK); + re3 = compiler.compile("BREAKHERE", Perl5Compiler.READ_ONLY_MASK); + } + catch (MalformedPatternException e) { + throw new RuntimeException(e.getMessage()); + } + } public PDFGenerator(ByteArrayOutputStream out) { @@ -612,9 +636,7 @@ public class PDFGenerator { private boolean enoughY(int heightOfBlockToAdd) { - if ((currentYPosition - heightOfBlockToAdd - footerHeight) < bottomEdge) - return false; - return true; + return (currentYPosition - heightOfBlockToAdd - footerHeight) >= bottomEdge; } @@ -668,106 +690,88 @@ public class PDFGenerator { String theDescription = ""; if (isHTML.equals("1")) { + theContent = + Util.substitute(new Perl5Matcher(), nobackslashr, new Perl5Substitution(""), theContentRaw, Util.SUBSTITUTE_ALL); + theDescription = + Util.substitute(new Perl5Matcher(), nobackslashr, new Perl5Substitution(""), theDescriptionRaw, Util.SUBSTITUTE_ALL); + theContent = Util.substitute(new Perl5Matcher(), HxTag, new Perl5Substitution("\n\n"), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), HxTag, new Perl5Substitution("\n\n"), theDescription, Util.SUBSTITUTE_ALL); + theContent = Util.substitute(new Perl5Matcher(), ListItemTag, new Perl5Substitution("\n * "), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), ListItemTag, new Perl5Substitution("\n * "), theDescription, Util.SUBSTITUTE_ALL); - try { - RE nobackslashr = new RE("\r"); - theContent = nobackslashr.substituteAll(theContentRaw, ""); - theDescription = nobackslashr.substituteAll(theDescriptionRaw, ""); - - RE HxTag = new RE("]*>", RE.REG_ICASE); - theContent = HxTag.substituteAll(theContent, "\n\n"); - theDescription = HxTag.substituteAll(theDescription, "\n\n"); - - RE ListItemTag = new RE("]*>", RE.REG_ICASE); - theContent = ListItemTag.substituteAll(theContent, "\n * "); - theDescription = ListItemTag.substituteAll(theDescription, "\n * "); + theContent = Util.substitute(new Perl5Matcher(), ListTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), ListTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL); - RE ListTag = new RE("<(u|o)l[^>]*>", RE.REG_ICASE); - theContent = ListTag.substituteAll(theContent, "\n"); - theDescription = ListTag.substituteAll(theDescription, "\n"); + theContent = Util.substitute(new Perl5Matcher(), DivTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), DivTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL); - RE DivTag = new RE("]*>", RE.REG_ICASE); - theContent = DivTag.substituteAll(theContent, "\n"); - theDescription = DivTag.substituteAll(theDescription, "\n"); + theContent = Util.substitute(new Perl5Matcher(), PTag, new Perl5Substitution("\n "), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), PTag, new Perl5Substitution("\n "), theDescription, Util.SUBSTITUTE_ALL); - RE PTag = new RE("<(p|P)([:space:]+[^>]*)?>"); - theContent = PTag.substituteAll(theContent, "\n "); - theDescription = PTag.substituteAll(theDescription, "\n "); + theContent = Util.substitute(new Perl5Matcher(), PTagClose, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), PTagClose, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL); - RE PTagClose = new RE("]*)?>"); - theContent = PTagClose.substituteAll(theContent, "\n"); - theDescription = PTagClose.substituteAll(theDescription, "\n"); + theContent = Util.substitute(new Perl5Matcher(), BRTag, new Perl5Substitution("\n"), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), BRTag, new Perl5Substitution("\n"), theDescription, Util.SUBSTITUTE_ALL); - RE BRTag = new RE("<(br|BR)([:space:]+[^>]*)?>"); - theContent = BRTag.substituteAll(theContent, "\n"); - theDescription = BRTag.substituteAll(theDescription, "\n"); - RE ATagAll = new RE("]*href=(?:\"|\')([^#\"\'][^\'\"]+)(?:\"|\')[^>]*>(.*?)", RE.REG_ICASE); - REMatchEnumeration atags = ATagAll.getMatchEnumeration(theContent); + Perl5Matcher matcher = new Perl5Matcher(); + PatternMatcherInput input = new PatternMatcherInput(theContent); String theContentCopy = theContent; - while (atags.hasMoreMatches()) { - REMatch atag = atags.nextMatch(); - String atagString = atag.toString(); - String atagStringHref = atag.toString(1); - String atagStringText = atag.toString(2); - int begin = theContentCopy.indexOf(atagString); - theContentCopy = theContentCopy.substring(0, begin) + atagStringText + " [" + atagStringHref + "] " + theContentCopy.substring(begin + atagString.length()); + while (matcher.contains(input, ATagAll)) { + String atagString = matcher.getMatch().group(0); + String atagStringHref = matcher.getMatch().group(1); + String atagStringText = matcher.getMatch().group(2); + int begin = matcher.getMatch().beginOffset(0); + theContentCopy = + theContentCopy.substring(0, begin) + atagStringText + + " [" + atagStringHref + "] " + theContentCopy.substring(begin + atagString.length()); } theContent = theContentCopy; - REMatchEnumeration atags2 = ATagAll.getMatchEnumeration(theDescription); + + input = new PatternMatcherInput(theDescription); + String theDescriptionCopy = theDescription; - while (atags2.hasMoreMatches()) { - REMatch atag = atags2.nextMatch(); - String atagString = atag.toString(); - String atagStringHref = atag.toString(1); - String atagStringText = atag.toString(2); - int begin = theDescriptionCopy.indexOf(atagString); - theDescriptionCopy = theDescriptionCopy.substring(0, begin) + atagStringText + " [" + atagStringHref + "] " + theDescriptionCopy.substring(begin + atagString.length()); + while (matcher.contains(input, ATagAll)) { + String atagString = matcher.getMatch().group(0); + String atagStringHref = matcher.getMatch().group(1); + String atagStringText = matcher.getMatch().group(2); + int begin = matcher.getMatch().beginOffset(0); + theDescriptionCopy = theDescriptionCopy.substring(0, begin) + atagStringText + " [" + atagStringHref + "] " + + theDescriptionCopy.substring(begin + atagString.length()); } theDescription = theDescriptionCopy; - RE noTags = new RE("<[^>]*>"); - theContent = noTags.substituteAll(theContent, " "); - theDescription = noTags.substituteAll(theDescription, " "); + theContent = Util.substitute(new Perl5Matcher(), noTags, new Perl5Substitution(" "), theContent, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), noTags, new Perl5Substitution(" "), theDescription, Util.SUBSTITUTE_ALL); theContent = HTMLRoutines.resolveHTMLEntites(theContent); theDescription = HTMLRoutines.resolveHTMLEntites(theDescription); - RE re1 = new RE("\r?\n\r?\n"); - String theDescription1 = re1.substituteAll(theDescription, "BREAKHERE"); - - RE re2 = new RE("\r?\n"); - String theDescription2 = re2.substituteAll(theDescription1, " "); + String theDescription1 = Util.substitute(new Perl5Matcher(), re1, new Perl5Substitution("BREAKHERE"), theDescription, Util.SUBSTITUTE_ALL); - RE re3 = new RE("BREAKHERE"); - theDescription = re3.substituteAll(theDescription2, "\n "); + String theDescription2 = Util.substitute(new Perl5Matcher(), re2, new Perl5Substitution(" "), theDescription1, Util.SUBSTITUTE_ALL); - - } - catch (REException ree) { - logger.error(ree.getMessage()); - } - } else { - try { - RE re1 = new RE("\r?\n\r?\n"); - String theContent1 = re1.substituteAll(theContentRaw, "BREAKHERE"); - String theDescription1 = re1.substituteAll(theDescriptionRaw, "BREAKHERE"); - - RE re2 = new RE("\r?\n"); - String theContent2 = re2.substituteAll(theContent1, " "); - String theDescription2 = re2.substituteAll(theDescription1, " "); - - RE re3 = new RE("BREAKHERE"); - theContent = " " + re3.substituteAll(theContent2, "\n "); - theDescription = re3.substituteAll(theDescription2, "\n "); - - } - catch (REException ree) { - logger.error(ree.getMessage()); - } + theDescription = Util.substitute(new Perl5Matcher(), re3, new Perl5Substitution("\n "), theDescription2, Util.SUBSTITUTE_ALL); + } + else { + String theContent1 = Util.substitute(new Perl5Matcher(), re1, + new Perl5Substitution("BREAKHERE"), theContentRaw, Util.SUBSTITUTE_ALL); + String theDescription1 = Util.substitute(new Perl5Matcher(), re1, + new Perl5Substitution("BREAKHERE"), theDescriptionRaw, Util.SUBSTITUTE_ALL); + + String theContent2 = Util.substitute(new Perl5Matcher(), re2, + new Perl5Substitution(" "), theContent1, Util.SUBSTITUTE_ALL); + String theDescription2 = Util.substitute(new Perl5Matcher(), re2, + new Perl5Substitution(" "), theDescription1, Util.SUBSTITUTE_ALL); + + theContent = " " + Util.substitute(new Perl5Matcher(), re3, + new Perl5Substitution("\n "), theContent2, Util.SUBSTITUTE_ALL); + theDescription = Util.substitute(new Perl5Matcher(), re3, + new Perl5Substitution("\n "), theDescription2, Util.SUBSTITUTE_ALL); } addArticleSeparator(); diff --git a/source/mircoders/servlet/ServletModuleAbuse.java b/source/mircoders/servlet/ServletModuleAbuse.java index 5cb0ded1..f2b8b0ab 100755 --- a/source/mircoders/servlet/ServletModuleAbuse.java +++ b/source/mircoders/servlet/ServletModuleAbuse.java @@ -349,7 +349,7 @@ public class ServletModuleAbuse extends AdminServletModule { responseData.put("commentactions", MirGlobal.abuse().getCommentActions()); responseData.put("disableop", new Boolean(MirGlobal.abuse().getOpenPostingDisabled())); - responseData.put("passwordop", new Boolean(MirGlobal.abuse().getOpenPostingPassword())); + responseData.put("passwordop", new Boolean(MirGlobal.abuse().getRequireCaptcha())); responseData.put("logenabled", new Boolean(MirGlobal.abuse().getLogEnabled())); responseData.put("logsize", Integer.toString(MirGlobal.abuse().getLogSize())); responseData.put("usecookies", new Boolean(MirGlobal.abuse().getCookieOnBlock())); diff --git a/source/mircoders/servlet/ServletModuleFileEdit.java b/source/mircoders/servlet/ServletModuleFileEdit.java index 6543c11c..e275250f 100755 --- a/source/mircoders/servlet/ServletModuleFileEdit.java +++ b/source/mircoders/servlet/ServletModuleFileEdit.java @@ -45,17 +45,20 @@ import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.*; +import org.apache.oro.text.regex.MalformedPatternException; + /* * ServletModuleFileEdit - * Allows one to do a basic edit of a file in a directory specified * in the config file. * * @author $Author: zapata $ - * @version $Revision: 1.13.2.14 $ $Date: 2006/12/25 20:10:23 $ + * @version $Revision: 1.13.2.15 $ $Date: 2007/12/15 00:24:44 $ * */ public class ServletModuleFileEdit extends AdminServletModule { + // todo: subdirectories use too many /'s private Map directories; private List directoryNames; @@ -80,7 +83,13 @@ public class ServletModuleFileEdit extends AdminServletModule { else { String name = (String) parts.get(0); String directory = (String) parts.get(1); - String filter = (String) parts.get(2); + FilenameFilter filter; + try { + filter = new FileRoutines.RegExpFileFilter((String) parts.get(2)); + } + catch (MalformedPatternException e) { + throw new ServletModuleFailure("Invalid regular expression for file edit: " + parts.get(2)); + } String recursive = (String) parts.get(3); directories.put(name, new FileEditDirectory(name, directory, filter, @@ -100,14 +109,16 @@ public class ServletModuleFileEdit extends AdminServletModule { public FileEditDirectory getDirectory(HttpServletRequest aRequest) throws ServletModuleExc { FileEditDirectory result = (FileEditDirectory) directories.get(aRequest.getParameter("entry")); - if (result == null) + + if (result == null) { throw new ServletModuleExc("Unknown entry: " + aRequest.getParameter("entry")); + } return result; } public void list(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { - listSubDirectory(getDirectory(aRequest), "/", aRequest, aResponse); + listSubDirectory(getDirectory(aRequest), "", aRequest, aResponse); } public void edit(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { @@ -117,8 +128,9 @@ public class ServletModuleFileEdit extends AdminServletModule { String filename = requestParser.getParameter("filename"); String subDirectory = requestParser.getParameterWithDefault("subdirectory", ""); - if (filename == null) + if (filename == null) { throw new ServletModuleExc("No filename specified"); + } editFile(getDirectory(aRequest), filename, subDirectory, aRequest, aResponse); } @@ -135,7 +147,7 @@ public class ServletModuleFileEdit extends AdminServletModule { String directoryName = requestParser.getParameter("directory"); String subDirectoryName = requestParser.getParameter("subdirectory"); - if (directoryName==null | subDirectoryName==null) + if (directoryName==null || subDirectoryName==null) throw new ServletModuleExc("No directory/subDirectory specified"); listSubDirectory(getDirectory(aRequest), subDirectoryName+File.separator+directoryName, aRequest, aResponse); @@ -186,7 +198,8 @@ public class ServletModuleFileEdit extends AdminServletModule { public void listSubDirectory(FileEditDirectory aDirectory, String aSubDirectory, HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc { try { - Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); + Map responseData = ServletHelper.makeGenerationData(aRequest, aResponse, + new Locale[] { getLocale(aRequest), getFallbackLocale(aRequest)}); File dir = new File(aDirectory.getRootDirectory(), aSubDirectory); if (!isDirectoryValid(aDirectory, dir) || !dir.isDirectory()) { @@ -284,14 +297,14 @@ public class ServletModuleFileEdit extends AdminServletModule { private class FileEditDirectory { private String name; - private FileRoutines.RegExpFileFilter filter; + private FilenameFilter filter; private File rootDirectory; private boolean recursive; - public FileEditDirectory(String aName, String aRootDirectory, String aFilter, boolean aRecursive) { + public FileEditDirectory(String aName, String aRootDirectory, FilenameFilter aFilter, boolean aRecursive) { name = aName; rootDirectory = new File(aRootDirectory); - filter = new FileRoutines.RegExpFileFilter(aFilter); + filter = aFilter; recursive = aRecursive; } @@ -299,7 +312,7 @@ public class ServletModuleFileEdit extends AdminServletModule { return name; } - public FileRoutines.RegExpFileFilter getFilter() { + public FilenameFilter getFilter() { return filter; } diff --git a/source/mircoders/servlet/ServletModuleOpenIndy.java b/source/mircoders/servlet/ServletModuleOpenIndy.java index 6769e429..0bb03aa1 100755 --- a/source/mircoders/servlet/ServletModuleOpenIndy.java +++ b/source/mircoders/servlet/ServletModuleOpenIndy.java @@ -30,41 +30,28 @@ package mircoders.servlet; -import gnu.regexp.RE; -import gnu.regexp.REMatch; import mir.bundle.Bundle; import mir.generator.Generator; import mir.misc.StringUtil; +import mir.module.ModuleExc; import mir.servlet.ServletModule; import mir.servlet.ServletModuleExc; import mir.servlet.ServletModuleFailure; import mir.servlet.ServletModuleUserExc; -import mir.session.HTTPAdapters; -import mir.session.Request; -import mir.session.Session; -import mir.session.SessionHandler; -import mir.session.SimpleResponse; +import mir.session.*; import mir.util.FileRoutines; import mir.util.HTTPParsedRequest; import mir.util.HTTPRequestParser; import mir.util.StringRoutines; -import mir.module.ModuleExc; import mircoders.entity.EntityContent; import mircoders.global.CacheKey; import mircoders.global.MirGlobal; +import mircoders.localizer.MirLocalizerExc; +import mircoders.localizer.MirOpenPostingLocalizer; import mircoders.module.ModuleContent; import mircoders.pdf.PDFGenerator; -import mircoders.search.AudioSearchTerm; -import mircoders.search.ContentSearchTerm; -import mircoders.search.ImagesSearchTerm; -import mircoders.search.KeywordSearchTerm; -import mircoders.search.TextSearchTerm; -import mircoders.search.TopicMatrixSearchTerm; -import mircoders.search.TopicSearchTerm; -import mircoders.search.UnIndexedSearchTerm; -import mircoders.search.VideoSearchTerm; +import mircoders.search.*; import mircoders.storage.DatabaseTopics; -import mircoders.localizer.MirLocalizerExc; import org.apache.commons.net.smtp.SMTPClient; import org.apache.commons.net.smtp.SMTPReply; import org.apache.lucene.analysis.standard.StandardAnalyzer; @@ -75,27 +62,17 @@ import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.Searcher; import org.apache.lucene.store.FSDirectory; +import org.apache.oro.text.regex.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.ListIterator; -import java.util.Locale; -import java.util.Map; -import java.util.Random; -import java.util.Set; +import javax.servlet.ServletOutputStream; +import java.io.*; +import java.util.*; + +import com.sun.image.codec.jpeg.JPEGCodec; +import com.sun.image.codec.jpeg.JPEGImageEncoder; /* */ @@ -123,12 +100,6 @@ public class ServletModuleOpenIndy extends ServletModule { /** * Method to return an out of service notice when open postings are disabled - * - * @param aRequest - * @param aResponse - * @throws ServletModuleExc - * @throws ServletModuleUserExc - * @throws ServletModuleFailure */ public void openPostingDisabled(HttpServletRequest aRequest, HttpServletResponse aResponse) throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { deliver(aRequest, aResponse, null, null, getConfiguration().getString("ServletModule.OpenIndy.PostingDisabledTemplate")); @@ -217,6 +188,33 @@ public class ServletModuleOpenIndy extends ServletModule { } } + public void captcha(HttpServletRequest aRequest, HttpServletResponse aResponse) + throws ServletModuleExc, ServletModuleUserExc, ServletModuleFailure { + try { + MirOpenPostingLocalizer.Captcha captcha = MirGlobal.localizer().openPostings().generateCaptcha(aRequest.getSession().getId()); + aRequest.getSession().setAttribute("captcha", captcha); + + // the output stream to render the captcha image as jpeg into + ByteArrayOutputStream jpegOutputStream = new ByteArrayOutputStream(); + JPEGImageEncoder jpegEncoder = JPEGCodec.createJPEGEncoder(jpegOutputStream); + jpegEncoder.encode(captcha.getChallenge()); + + aResponse.setHeader("Cache-Control", "no-store"); + aResponse.setHeader("Pragma", "no-cache"); + aResponse.setDateHeader("Expires", 0); + aResponse.setContentType("image/jpeg"); + + ServletOutputStream responseOutputStream = aResponse.getOutputStream(); + + responseOutputStream.write(jpegOutputStream.toByteArray()); + responseOutputStream.flush(); + responseOutputStream.close(); + } + catch (IOException e) { + throw new ServletModuleFailure(e); + } + } + /** * Method for preparing and sending a content as an email message */ @@ -481,7 +479,7 @@ public class ServletModuleOpenIndy extends ServletModule { } else { try { - Searcher searcher = null; + Searcher searcher; try { searcher = new IndexSearcher(FSDirectory.getDirectory(indexFile,false)); @@ -660,20 +658,19 @@ public class ServletModuleOpenIndy extends ServletModule { String ID_REQUEST_PARAM = "id"; int maxArticlesInNewsleter = 15; // it is nice not to be dos'ed try { - String idParam = aRequest.getParameter(ID_REQUEST_PARAM); - if (idParam != null) { - RE re = new RE("[0-9]+"); - - REMatch[] idMatches = re.getAllMatches(idParam); - String cacheSelector = ""; - - for (int i = 0; i < idMatches.length; i++) { - cacheSelector = cacheSelector + "," + idMatches[i].toString(); + String idParameterValue = aRequest.getParameter(ID_REQUEST_PARAM); + if (idParameterValue != null) { + Pattern idPattern = new Perl5Compiler().compile("[0-9]+"); + PatternMatcher matcher = new Perl5Matcher(); + PatternMatcherInput input = new PatternMatcherInput(idParameterValue); + List ids = new ArrayList(); + while (matcher.contains(input, idPattern)) { + ids.add(matcher.getMatch().toString()); } String cacheType = "pdf"; - CacheKey theCacheKey = new CacheKey(cacheType, cacheSelector); + CacheKey theCacheKey = new CacheKey(cacheType, idParameterValue); byte[] thePDF; @@ -686,22 +683,17 @@ public class ServletModuleOpenIndy extends ServletModule { ByteArrayOutputStream out = new ByteArrayOutputStream(); PDFGenerator pdfMaker = new PDFGenerator(out); - if (idMatches.length > 1) { + if (ids.size() > 1) { pdfMaker.addLine(); - for (int i = 0; i < idMatches.length && i < maxArticlesInNewsleter; i++) { - REMatch aMatch = idMatches[i]; - String id = aMatch.toString(); - EntityContent contentEnt = (EntityContent) contentModule.getById(id); - + for (int i = 0; i < ids.size() && i < maxArticlesInNewsleter; i++) { + EntityContent contentEnt = (EntityContent) contentModule.getById((String) ids.get(i)); pdfMaker.addIndexItem(contentEnt); } } - for (int i = 0; i < idMatches.length; i++) { - REMatch aMatch = idMatches[i]; - String id = aMatch.toString(); - EntityContent article = (EntityContent) contentModule.getById(id); + for (int i = 0; i < ids.size(); i++) { + EntityContent article = (EntityContent) contentModule.getById((String) ids.get(i)); if (!MirGlobal.localizer().openPostings().allowArticlePublication(article)) { throw new ServletModuleExc("Illegal article"); diff --git a/source/tool/ConfigTool.java b/source/tool/ConfigTool.java index d7e89932..1ead5825 100755 --- a/source/tool/ConfigTool.java +++ b/source/tool/ConfigTool.java @@ -29,12 +29,14 @@ */ package tool; -import gnu.regexp.RE; - import java.security.MessageDigest; import java.util.TimeZone; import mir.util.StringRoutines; +import org.apache.oro.text.regex.Perl5Compiler; +import org.apache.oro.text.regex.Pattern; +import org.apache.oro.text.regex.Perl5Matcher; +import org.apache.oro.text.regex.PatternMatcher; /** *

Title:

@@ -51,12 +53,13 @@ public class ConfigTool { public static void timezone(String aSpecification) { try { - RE specification = new RE(aSpecification); + PatternMatcher matcher = new Perl5Matcher(); + Pattern specification = new Perl5Compiler().compile(aSpecification); String[] timeZoneIds = TimeZone.getAvailableIDs(); System.out.println("ID\tOffset\tDST?\tName"); for (int i=0; i= 1) { command = anArguments[0]; - if (command.equals("timezone")) { + if ("timezone".equals(command)) { if (anArguments.length<=2) { if (anArguments.length==2) timezone(anArguments[1]); @@ -101,7 +104,7 @@ public class ConfigTool { return; } - else if (command.equals("digest")) { + else if ("digest".equals(command)) { if (anArguments.length == 3) { digest(anArguments[1], anArguments[2]);
- ${lang("posting.media.title")} 1: + ${lang("content.media.title")} 1:
${lang("posting.media.media")} 1${lang("content.media.media")} 1
- ${lang("posting.media.title")} 2: + ${lang("content.media.title")} 2:
${lang("posting.media.media")} 2${lang("content.media.media")} 2
- ${lang("posting.media.title")} 3: + ${lang("content.media.title")} 3:
${lang("posting.media.media")} 3${lang("content.media.media")} 3