support for CAPTCHAs
authorzapata <zapata>
Sat, 15 Dec 2007 00:24:41 +0000 (00:24 +0000)
committerzapata <zapata>
Sat, 15 Dec 2007 00:24:41 +0000 (00:24 +0000)
replaced gnu regexp with oro which is much faster

32 files changed:
bundles/admin_en.properties
etc/bundles/open_en.properties
etc/bundles/open_es.properties
etc/open/editarticle.template
etc/open/editcomment.template
lib/gnu-regexp-1.1.4.jar [deleted file]
lib/jcaptcha-all-1.0-RC6.jar [new file with mode: 0644]
lib/pja-2.5.jar [new file with mode: 0644]
lib/pjatools-2.5.jar [new file with mode: 0644]
source/mir/config/MirPropertiesConfiguration.java
source/mir/servlet/ServletModuleFailure.java
source/mir/session/HTTPAdapters.java
source/mir/session/Session.java
source/mir/util/FileRoutines.java
source/mir/util/ParameterExpander.java
source/mir/util/SimpleParser.java
source/mir/util/StringRoutines.java
source/mircoders/entity/EntityComment.java
source/mircoders/entity/EntityContent.java
source/mircoders/global/Abuse.java
source/mircoders/localizer/LocalizerCache.java
source/mircoders/localizer/MirOpenPostingLocalizer.java
source/mircoders/localizer/basic/MirBasicAdminInterfaceLocalizer.java
source/mircoders/localizer/basic/MirBasicArticlePostingHandler.java
source/mircoders/localizer/basic/MirBasicOpenPostingLocalizer.java
source/mircoders/localizer/basic/MirBasicPostingSessionHandler.java
source/mircoders/localizer/basic/MirBasicProducerAssistantLocalizer.java
source/mircoders/pdf/PDFGenerator.java
source/mircoders/servlet/ServletModuleAbuse.java
source/mircoders/servlet/ServletModuleFileEdit.java
source/mircoders/servlet/ServletModuleOpenIndy.java
source/tool/ConfigTool.java

index 5462196..7b5c9e5 100755 (executable)
@@ -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
index 97ed4a0..f48be85 100755 (executable)
@@ -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 <b>before</b> you enter data into the other fields.)
-posting.nr_of_media.submit=define number (max 20)
-posting.form.title=Publishing Form
-posting.title=<b>title</b> of your article
-posting.title.info=(Please use a clear and meaningful title)
-posting.topic=<b>Topic</b> of your Posting
-posting.topic.info=(multiple selection is possible. use the [Ctrl] key)
-posting.author=<b>author</b> of this article
-posting.abstract=A short <b>abstract</b> 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 <b>5 lines</b>)
-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 <b>article</b>
-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 <b>only once</b>!<br>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 <b>before</b> you enter data into the other fields.)
+content.nr_of_media.submit=define number (max 20)
+content.form.title=Publishing Form
+content.title=<b>title</b> of your article
+content.title.info=(Please use a clear and meaningful title)
+content.topic=<b>Topic</b> of your Posting
+content.topic.info=(multiple selection is possible. use the [Ctrl] key)
+content.creator=<b>author</b> of this article
+content.abstract=A short <b>abstract</b> 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 <b>5 lines</b>)
+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 <b>article</b>
+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 <b>only once</b>!<br>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
+
index ef00957..7ee9e12 100755 (executable)
@@ -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, <b>bevor</b> Du weitere Felder ausfüllst.)
-posting.nr_of_media.submit=Anzahl festlegen
-posting.form.title=Formulario de publicación
-posting.title=<b>Título</b> de su artículo
-posting.title.info=(Bitte wähle einen möglichst klaren, aussagekräftigen Titel.)
-posting.topic=<b>Thema</b> Deines Beitrags
-posting.topic.info=(Mehrfachwahl ist möglich. Bitte dazu die [Strg]- bzw [Ctrl]-Taste benutzen)
-posting.author=<b>autor</b> de este artículo
-posting.abstract=Descripción <b>breve</b> 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 <b>5 líneas</b>)
-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 <b>artículo</b>
-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<b> nur einmal</b>!<br> In wenigen Minuten erscheind Dein Beitrag dann auf der <a href="http://de.indymedia.org/html" target="_blank"> <b>"Open Posting"</b></a> - Seite. &nbsp; Das ist nicht die Startseite.<br> Manchmal kann es aber aufgrund technischer Probleme etwas dauern bis er erscheint.
-posting.criteria=Die <b>Moderationskriterien</b> kannst Du <a href="http://de.indymedia.org/static/moderation.html" target="_blank"><b>hier nachlesen</b></a>
-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, <b>bevor</b> Du weitere Felder ausfüllst.)
+content.nr_of_media.submit=Anzahl festlegen
+content.form.title=Formulario de publicación
+content.title=<b>Título</b> de su artículo
+content.title.info=(Bitte wähle einen möglichst klaren, aussagekräftigen Titel.)
+content.topic=<b>Thema</b> Deines Beitrags
+content.topic.info=(Mehrfachwahl ist möglich. Bitte dazu die [Strg]- bzw [Ctrl]-Taste benutzen)
+content.creator=<b>autor</b> de este artículo
+content.abstract=Descripción <b>breve</b> 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 <b>5 líneas</b>)
+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 <b>artículo</b>
+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<b> nur einmal</b>!<br> In wenigen Minuten erscheind Dein Beitrag dann auf der <a href="http://de.indymedia.org/html" target="_blank"> <b>"Open Posting"</b></a> - Seite. &nbsp; Das ist nicht die Startseite.<br> Manchmal kann es aber aufgrund technischer Probleme etwas dauern bis er erscheint.
+content.criteria=Die <b>Moderationskriterien</b> kannst Du <a href="http://de.indymedia.org/static/moderation.html" target="_blank"><b>hier nachlesen</b></a>
+content.submit=Enviar (la paciencia es una virtud!!)
+content.reset=Limpiar formulario
 
 postingdone.htmltitle=open posting
 postingdone.title=Hurra, Du hast Deinen Artikel abgeschickt!
index 5bd19d7..67356bc 100755 (executable)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//DE">
 <html>
 <head>
-<title>${lang("posting.htmltitle")}</title>
+<title>${lang("content.htmltitle")}</title>
 <style type="text/css"> body {background-image: none;} </style>
 
 
@@ -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;
   <if errors>
     <list errors as e>
       <if e.field==aField>
-        ${lang(e.message + "." + e.field)}
+        ${lang(e.message)}
       </if>
     </list>
   </if>
 </function>
 
+<div class="pformbox">
+
+<h1>
+${lang("content.form.title")}
+</h1>
+
     <if errors>
+<div class="pformerrors">
           Your input had the following errors:<br><br>
           <list errors as e>
             <font color="red">
@@ -203,75 +235,50 @@ color: red;
               </list>
             </font>
           </list>
-    </if>
-
-
-<comment>
-
-<div class="pdiscl">
-<include "disclaimer.inc.de">
 </div>
-
-</comment>
-
-<div class="pformbox">
-
-<h1>
-${lang("posting.form.title")}
-</h1>
-
-    <if errors>
-<p class="error">${lang("posting.errors")}</p>
     </if>
 
 <h2>
-${lang("posting.step00")}
+${lang("content.step00")}
+
 </h2>
 
-<div class="pformstep01">
-${lang("posting.readhowtos")}
+<div class="pformstep00">
+${lang("content.readhowtos")}
+
 </div>
 <form enctype="multipart/form-data" action="${actionURL}&do=opensession&sessiontype=article" method="post">
 <h2>
-${lang("posting.step01")}
+${lang("content.step01")}
 </h2>
 
 
 
 <div class="pformstep01">
 <h4>
-${lang("posting.nr_of_media")}
+${lang("content.nr_of_media")}
 </h4>
 <p>
-${lang("posting.nr_of_media.info")}
+${lang("content.nr_of_media.info")}
 </p>
 <p>
 <input type="text" name="nrmediaitems" size="8" value="${utility.encodeHTML(nrmediaitems)}"> 
-<input type="submit" value="${lang("posting.nr_of_media.submit")}">
+<input type="submit" value="${lang("content.nr_of_media.submit")}">
 </p>
 </div>
 
-<if password>
-<div class="ppassword">
-${password}
-
-<p>${lang("posting.password")}</p>
-
-<p><input type="text" name="password" size="10">
-</if>
-
 <h2>
-${lang("posting.step02")}
+${lang("content.step02")}
 </h2>
 
 <div class="pformstep02">
 
 <!-- TITEL -->
 <h4>
-${lang("posting.title")}
+${lang("content.title")}
 </h4>
 <p>
-<small>${lang("posting.title.info")}</small>
+<small>${lang("content.title.info")}</small>
 </p>
 <p>
 <input type="text" class="preq" name="title" size="45" maxlength="45" value="${utility.encodeHTML(title)}">
@@ -284,10 +291,10 @@ ${lang("posting.title")}
 
 <!-- TOPIC -->
 <h4>
-${lang("posting.topic")}
+${lang("content.topic")}
 </h4>
 <p>
-${lang("posting.topic.info")}
+${lang("content.topic.info")}
 </p>
 <select name="to_topic" size="10" multiple>
 <list topics as t>
@@ -298,7 +305,7 @@ ${lang("posting.topic.info")}
 
 <!-- AUTOR -->
 <h4>
-${lang("posting.author")}
+${lang("content.creator")}
 </h4>
 
 <input type="text" class="preq" name="creator" value="${utility.encodeHTML(creator)}" size="45" maxlength="45"> 
@@ -311,10 +318,10 @@ ${lang("posting.author")}
 
 <!-- ABSTRACT -->
 <h4>
-${lang("posting.abstract")}
+${lang("content.abstract")}
 </h4>
 <p>
-${lang("posting.abstract.info")}
+${lang("content.abstract.info")}
 </p>
 <textarea name="description" class="preq" rows="10" cols="74" wrap=virtual>${utility.encodeHTML(description)}</textarea>
 <if errors>
@@ -323,57 +330,57 @@ ${lang("posting.abstract.info")}
 <small><strong>(${lang("required")})</strong></small>
 </if>
 <p>
-<strong>${lang("posting.abstract.constraint")}</strong>
+<strong>${lang("content.abstract.constraint")}</strong>
 </p>
 
 </div>
 
 <h2>
-${lang("posting.step03")}
+${lang("content.step03")}
 </h2>
 
 <div class="pformstep03">
 <p>
-${lang("posting.contact.info")}
+${lang("content.contact.info")}
 </p>
 
 <!--  EMAIL -->
 <h4>
-${lang("posting.email")}
+${lang("content.email")}
 </h4>
 <input type="text" name="creator_email" size="55" maxlength="80" value="${utility.encodeHTML(creator_email)}">
 <small>(${lang("optional")})</small>
 
 <!-- URL -->
 <h4>
-${lang("posting.url")}
+${lang("content.url")}
 </h4>
 <input type="text" name="creator_main_url" size="55" maxlength="160" value="${utility.encodeHTML(creator_main_url)}">
 <small>(${lang("optional")})</small>
 
 <!-- ADRESS -->
 <h4>
-${lang("posting.address")}
+${lang("content.address")}
 </h4>
 <input type="text" name="creator_address" size="55" maxlength="160" value="${utility.encodeHTML(creator_address)}">
 <small>(${lang("optional")})</small>
 
 <!-- PHONE -->
 <h4>
-${lang("posting.phone")}
+${lang("content.phone")}
 </h4>
 <input type="text" name="creator_phone" size="20" maxlength="20" value="${utility.encodeHTML(creator_address)}">
 <small>(${lang("optional")})</small>
 </div>
 
 <h2>
-${lang("posting.step04")}
+${lang("content.step04")}
 </h2>
 
 <div class="pformstep04">
 <!-- LANG -->
 <h4>
-${lang("posting.language")}
+${lang("content.language")}
 </h4>
 <select name="to_language">
 <list languages as l>
@@ -384,10 +391,10 @@ ${lang("posting.language")}
 
 <!-- CONTENT -->
 <h4>
-${lang("posting.text")}
+${lang("content.content_data")}
 </h4>
 <p>
-${lang("posting.text.info")}
+${lang("content.content_data.info")}
 </p>
 <textarea name="content_data" class="preq" rows="35" cols="74" wrap="soft">${utility.encodeHTML(content_data)}</textarea>
 <if errors>
@@ -395,7 +402,7 @@ ${lang("posting.text.info")}
 <else>
 <small><strong>(${lang("required")})</strong></small>
 </if>
-<p>${lang("posting.html")}</p>
+<p>${lang("content.html")}</p>
 <select name="is_html">
 <option value="0" <if is_html!="1">selected</if>>plain text</option>
 <option value="1" <if is_html=="1">selected</if>>html</option>
@@ -404,12 +411,12 @@ ${lang("posting.text.info")}
 </div>
 
 <h2>
-${lang("posting.step05")}
+${lang("content.step05")}
 </h2>
 <div class="pformstep05">
 
 <h4>
-${lang("posting.media")}
+${lang("content.media")}
 </h4>
 <p>
 <small>${lang("optional")}</small>
@@ -419,30 +426,30 @@ ${lang("posting.media")}
     <h4>
       ${utility.encodeHTML(a.filename)}
     </h4>
-    <input type="checkbox" name="${a.fieldname}_cancel"> ${lang("posting.media.cancel")}
+    <input type="checkbox" name="${a.fieldname}_cancel"> ${lang("content.media.cancel")}
 
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="${a.fieldname}_title" size="40" maxlength="80" value="${utility.encodeHTML(a.title)}">
 </list>
 
 <p>
-${lang("posting.media.info")}
+${lang("content.media.info")}
 </p>
 <p>
-${lang("posting.media.howto")}
+${lang("content.media.howto")}
 </p>
 
 <list mediaitems as m>
     <hr>
     <h4>
-    ${lang("posting.media.media")} ${m}
+    ${lang("content.media.media")} ${m}
     </h4>
     <input type="file" name="media${m}">
     
     <h4>
-    ${lang("posting.media.title")} ${m}
+    ${lang("content.media.title")} ${m}
     </h4>
     <input type="text" class="preq" name="media${m}_title" size="40" maxlength="80" value="">
 </list>
@@ -451,7 +458,7 @@ ${lang("posting.media.howto")}
   <if config["Localizer.OpenSession.AllowFTPUploadSelection"]!="0" && ftpfiles>
     <hr>
     <h4>
-      ${lang("posting.media.ftpmedia")}
+      ${lang("content.media.ftpmedia")}
     </h4>
     <select name="ftpupload">
       <option value="">&nbsp;</option>
@@ -461,17 +468,17 @@ ${lang("posting.media.howto")}
     </select>
     
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="ftpupload_title" size="40" maxlength="80" value="">
   <else>
     <hr>
     <h4>
-      ${lang("posting.media.ftpmedia")}
+      ${lang("content.media.ftpmedia")}
     </h4>
     <input type="text" name="ftpupload"  size="40" maxlength="80" value="">
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="ftpupload_title" size="40" maxlength="80" value="">
   </if>  
@@ -481,18 +488,28 @@ ${lang("posting.media.howto")}
 </div>
 
 <h2>
-${lang("posting.step06")}
+${lang("content.step06")}
 </h2>
 <div class="pformstep06">
 <p>
-${lang("posting.submit.info")}
+${lang("content.submit.info")}
 </p>
 <p>
-${lang("posting.criteria")}
+${lang("content.criteria")}
 </p>
+<if password>
+<div class="ppassword">
+<img src="${actionURL}&amp;do=captcha"/>
+
+<p>${lang("content.password")}</p>
+
+<p><input type="text" name="password" size="10">
+<call showErrors("title")>
+</if>
+
 <div class="pbuttons">
-<input type="submit" name="post" class="psubmit" value="${lang("posting.submit")}">
-<input type="reset" class="preset" value="${lang("posting.reset")}">
+<input type="submit" name="post" class="psubmit" value="${lang("content.submit")}">
+<input type="reset" class="preset" value="${lang("content.reset")}">
 </div>
 </div>
 </form>
index 7932a9d..c5624f8 100755 (executable)
@@ -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
 <if errors>
 <list errors as e>
 <if e.field==aField>       
-${lang(e.message + "." + e.field)}
+${lang(e.message)}
 </if>
 </list>
 </if>
@@ -163,12 +177,19 @@ ${lang("comment.note")}
 ${lang("comment.formtitle")}
 </h1>
 
+<form enctype="multipart/form-data" action="${actionURL}&do=opensession&sessiontype=comment" method="post">
+<input type="hidden" name="to_media" value="${utility.encodeHTML(to_media)}">
+
     <if errors>
+<h2>
+${lang("content.errors")}
+</h2>
+<div class="pformstep01">
           Your input had the following errors:<br><br>
           <list errors as e>
             <font color="red">
               <if e.field>
-                ${lang("content."+e.field)}:
+                ${lang("comment."+e.field)}:
               </if>
               ${lang(e.message)} <br>
               <list e.parameters as p>
@@ -176,13 +197,11 @@ ${lang("comment.formtitle")}
               </list>
             </font>
           </list>
+</div>
    </if>
 
-<form enctype="multipart/form-data" action="${actionURL}&do=opensession&sessiontype=comment" method="post">
-<input type="hidden" name="to_media" value="${utility.encodeHTML(to_media)}">
-
 <h2>
-${lang("posting.step01")}
+${lang("content.step01")}
 </h2>
 <div class="pformstep01">
 
@@ -210,7 +229,7 @@ ${lang("comment.name")}
 
 <!-- CONTENT -->
 <h4>
-${lang("comment.text")}
+${lang("comment.description")}
 </h4>
 <textarea name="description" class="preq" rows="20" cols="74" wrap=virtual>${utility.encodeHTML(description)}</textarea>
 <if errors>
@@ -221,7 +240,7 @@ ${lang("comment.text")}
 </div>
 
 <h2>
-${lang("posting.step02")}
+${lang("content.step02")}
 </h2>
 <div class="pformstep02">
 <!-- EMAIL -->
@@ -266,7 +285,7 @@ ${lang("comment.language")}
 </div>
 
 <h2>
-${lang("posting.step03")}
+${lang("content.step03")}
 </h2>
 
 
@@ -277,10 +296,10 @@ ${lang("posting.step03")}
     <h4>
       ${utility.encodeHTML(a.filename)}
     </h4>
-    <input type="checkbox" name="${a.fieldname}_cancel"> ${lang("posting.media.cancel")}
+    <input type="checkbox" name="${a.fieldname}_cancel"> ${lang("content.media.cancel")}
 
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="${a.fieldname}_title" size="40" maxlength="80" value="${utility.encodeHTML(a.title)}">
 </list>
@@ -290,42 +309,42 @@ ${lang("posting.step03")}
 <table>
   <tr>
     <td>
-    ${lang("posting.media.title")} 1:
+    ${lang("content.media.title")} 1:
     </td>
     <td colspan="2">
       <input type="text" name="media1_title" size="40" maxlength="80" value=""><br>
     </td>
   </tr>
   <tr>
-    <td>${lang("posting.media.media")} 1</td>
+    <td>${lang("content.media.media")} 1</td>
     <td colspan="2">
       <INPUT TYPE="file" NAME="media1">
     </td>
   </tr>
   <tr>
     <td>
-    ${lang("posting.media.title")} 2:
+    ${lang("content.media.title")} 2:
     </td>
     <td colspan="2">
       <input type="text" name="media2_title" size="40" maxlength="80" value=""><br>
     </td>
   </tr>
   <tr>
-    <td>${lang("posting.media.media")} 2</td>
+    <td>${lang("content.media.media")} 2</td>
     <td colspan="2">
       <INPUT TYPE="file" NAME="media2">
     </td>
   </tr>
   <tr>
     <td>
-    ${lang("posting.media.title")} 3:
+    ${lang("content.media.title")} 3:
     </td>
     <td colspan="2">
       <input type="text" name="media3_title" size="40" maxlength="80" value=""><br>
     </td>
   </tr>
   <tr>
-    <td>${lang("posting.media.media")} 3</td>
+    <td>${lang("content.media.media")} 3</td>
     <td colspan="2">
       <INPUT TYPE="file" NAME="media3">
     </td>
@@ -336,7 +355,7 @@ ${lang("posting.step03")}
   <if config["Localizer.OpenSession.AllowFTPUploadSelection"]!="0" && ftpfiles>
     <hr>
     <h4>
-      ${lang("posting.media.ftpmedia")}
+      ${lang("content.media.ftpmedia")}
     </h4>
     <select name="ftpupload">
       <option value="">&nbsp;</option>
@@ -346,17 +365,17 @@ ${lang("posting.step03")}
     </select>
     
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="ftpupload_title" size="40" maxlength="80" value="">
   <else>
     <hr>
     <h4>
-      ${lang("posting.media.ftpmedia")}
+      ${lang("content.media.ftpmedia")}
     </h4>
     <input type="text" name="ftpupload"  size="40" maxlength="80" value="">
     <h4>
-      ${lang("posting.media.title")} 
+      ${lang("content.media.title")} 
     </h4>
     <input type="text" class="preq" name="ftpupload_title" size="40" maxlength="80" value="">
   </if>  
@@ -366,9 +385,19 @@ ${lang("posting.step03")}
 
 
 <h2>
-${lang("posting.step04")}
+${lang("content.step04")}
 </h2>
 <div class="pformstep06">
+<if password>
+<div class="ppassword">
+<img src="${actionURL}&amp;do=captcha"/>
+
+<p>${lang("content.password")}</p>
+
+<p><input type="text" name="password" size="10">
+<call showErrors("title")>
+</if>
+
 <div class="pbuttons">
 <input type="submit" name="post" class="psubmit" value="${lang("comment.submit")}">
 <input type="reset" class="preset" value="${lang("comment.reset")}">
diff --git a/lib/gnu-regexp-1.1.4.jar b/lib/gnu-regexp-1.1.4.jar
deleted file mode 100755 (executable)
index c3c8770..0000000
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 (file)
index 0000000..6be71a3
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 (file)
index 0000000..9d0cbf2
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 (file)
index 0000000..3365df4
Binary files /dev/null and b/lib/pjatools-2.5.jar differ
index 71d4132..dff0561 100755 (executable)
@@ -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() {
index b869984..c3a2f1d 100755 (executable)
@@ -38,4 +38,8 @@ public class ServletModuleFailure extends Failure {
   public ServletModuleFailure(Throwable aCause) {
     this (aCause.getMessage(), aCause);
   }
+
+  public ServletModuleFailure(String aMessage) {
+    super(aMessage, null);
+  }
 }
index 4b50f56..cbeead5 100755 (executable)
@@ -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);
     }
index 37ddd69..315cae9 100755 (executable)
@@ -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);
index ac1d4c1..06de92a 100755 (executable)
  */
 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. <code>getExtension("example.txt")</code> will
+   * Returns the extension of a path. (e.g. <code>getExtension("example.txt")</code> will
    * return <code>"txt"</code>
    */
   public static String getExtension(String aPath) {
     int position = aPath.lastIndexOf('.');
+
     if (position >= 0) {
       return aPath.substring(position + 1);
     }
+
     return "";
   }
 
+  /**
+   * Returns <code>true</code> 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
index 3077611..0dbd4b3 100755 (executable)
@@ -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());
     }
index 4b0b148..92a806b 100755 (executable)
 
 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 <code>String</code> 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 <code>SimpleParser</code>, with <code>aData</code>
+   * Initialize a new <code>SimpleParser</code>, with <code>someData</code>
    * 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 <code>aMessage</code> 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. <code>aMessage</code> 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 <code>true</code> 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 <code>true</code> 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 <code>true</code> 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 <code>anExpression</code>.
    * 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 <code>true</code> 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 <code>SimpleParser</code>
    */
-  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
index 6757bdf..55d5edf 100755 (executable)
@@ -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);
     }
   }
 
index 2e9e8db..b2b0f49 100755 (executable)
@@ -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 {
index 96ab2dc..64488d4 100755 (executable)
 
 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);
-  }
 }
index 697d6e2..ea72ded 100755 (executable)
@@ -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()));
index 647e1e5..f6a0952 100755 (executable)
@@ -125,7 +125,6 @@ public class LocalizerCache implements MirLocalizer {
 
       return adapterModel;
     }
-
   }
 
   private static class MirCachingGeneratorLocalizer implements MirGeneratorLocalizer {
index 875309d..023837a 100755 (executable)
@@ -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 {
    * <emph>not</emph> 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);
+  }
 }
index ccdb4a8..8d09adc 100755 (executable)
@@ -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());
index c3f42e4..6fad3a4 100755 (executable)
@@ -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);
index 82b36e9..688f130 100755 (executable)
@@ -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
index 31822f5..7483a78 100755 (executable)
@@ -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 {
    * <code>aResults</code> 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();
index 9fbaa04..f79f4d4 100755 (executable)
@@ -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+|&#x0A;|&#x0D;", 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+|&#x0A;|&#x0D;");
-      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 <code>true</code> 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 <br/>. Some browsers
+          //    treat <br></br> 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, "&lt;");
-          value = regularExpressionGT.substituteAll(value, "&gt;");
-        }
-        catch (Throwable t) {
-          value = "";
+        if (keepNode) {
+          out.write("</");
+          out.write(node.getNodeName());
+          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("</");
-      out.write(node.getNodeName());
-      out.write('>');
+        break;
     }
 
     out.flush();
index 8405ae0..4514d00 100755 (executable)
  */
 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("</?h[1-6][^>]*>", Perl5Compiler.READ_ONLY_MASK +
+                                                     Perl5Compiler.CASE_INSENSITIVE_MASK );
+      ListItemTag = compiler.compile("<li[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
+      ListTag = compiler.compile("<(u|o)l[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
+      DivTag = compiler.compile("</?div[^>]*>", Perl5Compiler.CASE_INSENSITIVE_MASK);
+      PTag = compiler.compile("<(p|P)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
+      PTagClose = compiler.compile("</(p|P)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
+      BRTag = compiler.compile("<(br|BR)([:space:]+[^>]*)?>", Perl5Compiler.READ_ONLY_MASK);
+      ATagAll = compiler.compile("<a[^>]*href=(?:\"|\')([^#\"\'][^\'\"]+)(?:\"|\')[^>]*>(.*?)</a>",
+                                                     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("</?h[1-6][^>]*>", RE.REG_ICASE);
-        theContent = HxTag.substituteAll(theContent, "\n\n");
-        theDescription = HxTag.substituteAll(theDescription, "\n\n");
-
-        RE ListItemTag = new RE("<li[^>]*>", 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("</?div[^>]*>", 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("</(p|P)([:space:]+[^>]*)?>");
-        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("<a[^>]*href=(?:\"|\')([^#\"\'][^\'\"]+)(?:\"|\')[^>]*>(.*?)</a>", 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();
index 5cb0ded..f2b8b0a 100755 (executable)
@@ -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()));
index 6543c11..e275250 100755 (executable)
@@ -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;
     }
 
index 6769e42..0bb03aa 100755 (executable)
 
 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");
index d7e8993..1ead582 100755 (executable)
  */
 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;
 
 /**
  * <p>Title: </p>
@@ -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<timeZoneIds.length; i++) {
-        if (specification.isMatch(timeZoneIds[i])) {
+        if (matcher.contains(timeZoneIds[i], specification)) {
           TimeZone timeZone = TimeZone.getTimeZone(timeZoneIds[i]);
           long offset = timeZone.getRawOffset()/(1000*60);
           String sign = "";
@@ -86,12 +89,12 @@ public class ConfigTool {
   }
 
   public static void main(String[] anArguments) {
-    String command = "help";
+    String command;
 
     if (anArguments.length >= 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]);