From a1273c2b26a5318d351c95d0d4a510ccfdd50065 Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Fri, 2 Aug 2019 08:48:13 +0100
Subject: [PATCH] Ship our own UI customizations

---
 Dockerfile         |   4 +-
 README.md          |  23 ++++++
 ai-lurker-ui.patch | 169 +++++++++++++++++++++++++++++++++++++++++++++
 build.sh           |  19 +++--
 logo.png           | Bin 0 -> 3314 bytes
 start.sh           |  29 +++++++-
 6 files changed, 235 insertions(+), 9 deletions(-)
 create mode 100644 ai-lurker-ui.patch
 create mode 100644 logo.png

diff --git a/Dockerfile b/Dockerfile
index 17f6250..be53c31 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -9,8 +9,10 @@ RUN go build -o smtpd smtpd.go
 FROM registry.git.autistici.org/ai3/docker/apache2-base:master
 COPY start.sh /start.sh
 COPY build.sh /tmp/build.sh
+COPY ai-lurker-ui.patch /tmp/ai-lurker-ui.patch
 COPY conf/ /etc/
 COPY --from=build /go/src/smtpd /usr/bin/smtpd
-RUN /tmp/build.sh && rm /tmp/build.sh
+RUN /tmp/build.sh && rm /tmp/build.sh /tmp/ai-lurker-ui.patch
+COPY logo.png /var/lib/lurker-www-orig/logo.png
 ENTRYPOINT ["/usr/local/bin/chaperone"]
 
diff --git a/README.md b/README.md
index 0db655f..0607386 100644
--- a/README.md
+++ b/README.md
@@ -8,3 +8,26 @@ instead of using two separate container images.
 Configuration and data storage must be mounted respectively in
 */etc/lurker* and */var/lib/lurker*.
 
+Instead of running a full-blown Postfix instance, this container runs
+a very simple [SMTP server](smtpd.go) that is only suitable for internal
+traffic.
+
+The image expects /var/lib/lurker to be mounted externally with the
+right permissions, and to contain the *www* and *data* subdirectories.
+
+## Environment variables
+
+* `DOMAIN`: domain for the HTTP website, minus the *lists* prefix
+* `APACHE_PORT`: port for the HTTP service
+* `SMTP_PORT`: port for the SMTP service
+* `SMTP_EHLO_HOSTNAME`: hostname to use for SMTP EHLO
+* `LURKER_ADDR_RX`: regular expression to match SMTP recipients and
+  extract the list name from it. It should include a single regexp
+  group (the list name). The default handles plus-extension addresses
+  using the *lurker* username (`lurker\\+([^@]+)@.*`), but it is
+  recommended to extend it to match the expected domain name as well.
+* `LURKER_DATA_DIR`: data directory for Lurker (default */var/lib/lurker/data*).
+
+When Lurker is performing maintenance on its database, incoming
+SMTP reception is temporarily suspended.
+
diff --git a/ai-lurker-ui.patch b/ai-lurker-ui.patch
new file mode 100644
index 0000000..e534542
--- /dev/null
+++ b/ai-lurker-ui.patch
@@ -0,0 +1,169 @@
+diff -urN ui_/common.xsl ui/common.xsl
+--- ui_/common.xsl	2016-12-20 12:02:51.000000000 +0000
++++ ui/common.xsl	2017-09-16 13:59:48.788481408 +0000
+@@ -313,7 +313,7 @@
+ <xsl:template name="navbar">
+  <table>
+   <tr>
+-   <td><xsl:call-template name="link-to-top"/></td>
++   <td></td>
+    <td nowrap="NOWRAP"><xsl:call-template name="language-dropdown"/></td>
+   </tr>
+  </table>
+diff -urN ui_/default.css ui/default.css
+--- ui_/default.css	2016-12-20 12:02:51.000000000 +0000
++++ ui/default.css	2017-09-16 13:59:48.428473648 +0000
+@@ -1,9 +1,9 @@
+ body {
+   padding: 0px;
+-  margin: 0px;
+-  background-color: #BBF;
++  margin: 5px;
++  background-color: #FFF;
+   color: black;
+-  font-family: serif;
++  font-family: Arial, Helvetica, sans-serif;
+ }
+ 
+ form {
+@@ -11,13 +11,13 @@
+ }
+ 
+ div.header {
+-  background-color: #BBF;
++  background-color: #FFF;
+   padding: 4px 0.25em 0.25em 0.25em;
+-  border-bottom: 1px solid #434399;
+ }
+ 
+ div.footer {
+-  background-color: #BBF;
++display: none;
++  background-color: #FFF;
+   padding: 0.25em 0.25em 1px 0.25em;
+   border-top: 1px solid #434399;
+ }
+@@ -57,8 +57,8 @@
+   font-size: 100%;
+ }
+ 
+-a:link    { color:#11F }
+-a:visited { color:#00B }
++a:link    { color:#000 }
++a:visited { color:#000 }
+ a:hover   { color:#F00 }
+ a:active  { color:#A00 }
+ h1 a:visited { color:#11F }
+@@ -113,7 +113,7 @@
+ tr.lit  { background-color:#77F }  /* even rows in mindex/thread/search tables */
+ tr.row1 { background-color:#DDD }  /* even rows in mindex/thread/search tables */
+ tr.row2 { background-color:#EEE }  /* odd rows in mindex/thread/search tables  */
+-tr.rowover { background-color:#CAC } /* active (= mouseOver) rows in mindex/thread/search tables */
++tr.rowover { background-color:#FFF } /* active (= mouseOver) rows in mindex/thread/search tables */
+ 
+ div.body {
+   padding: 1em;
+@@ -171,7 +171,7 @@
+ table.navigation {
+   width: 100%;
+   font-size: 80%;
+-  background-color: #e8e8e8;
++  background-color: #FFF;
+ 
+ /* disabled until mozilla fixes the progressive render bug with images
+   border-top: 1px solid #969696;
+@@ -183,7 +183,7 @@
+ 
+ table.navigation th {
+   font-size: 100%;
+-  background-color: #969696;
++  background-color: #FFF;
+   padding: 3px;
+ }
+ 
+@@ -214,10 +214,13 @@
+ }
+ 
+ ul {
++  list-style-type: none;
+   margin-bottom: 0em;
+   margin-top: 0em;
+ }
+ 
++li { padding: 1px; }
++
+ h1.group {
+   margin: 0px;
+ }
+@@ -309,3 +312,7 @@
+ .url { }     /* "url" elements used inside of message's mime contents */
+ .quote { }   /* "quote" elements used inside of message's mime contents */
+ .art { margin: 0em; } /* "art" elements used inside of message's mime contents */
++
++
++input { padding: 3px; font-size: 12px; margin: 1px; border: 1px solid #CCC; }
++select { padding: 3px; font-size: 10px; margin: 1px; border: 1px solid #CCC; }
+diff -urN ui_/list.xsl ui/list.xsl
+--- ui_/list.xsl	2016-12-20 12:02:51.000000000 +0000
++++ ui/list.xsl	2017-09-16 13:59:48.476474682 +0000
+@@ -107,7 +107,7 @@
+     </table>
+     
+     <table class="navigation">
+-     <tr><th align="left" colspan="2"><xsl:value-of select="$jump-to-date"/></th></tr>
++     <tr><th align="left" colspan="2"></th></tr>
+      <tr>
+       <td>
+         <!-- make this the same height as mindex -->
+diff -urN ui_/message.xsl ui/message.xsl
+--- ui_/message.xsl	2016-12-20 12:02:51.000000000 +0000
++++ ui/message.xsl	2017-09-16 13:59:48.280470457 +0000
+@@ -274,7 +274,7 @@
+     <img src="../imgs/trash.png" alt="{$delete-message}" title="{$delete-message}"/>
+    </a>
+    <xsl:if test="mbox/list/email/@address">
+-    <br/><xsl:call-template name="reply-link"/>
++    <br/><br/><xsl:call-template name="reply-link"/>
+    </xsl:if>
+   </td>
+  </tr></table>
+diff -urN ui_/mindex.xsl ui/mindex.xsl
+--- ui_/mindex.xsl	2016-12-20 12:02:51.000000000 +0000
++++ ui/mindex.xsl	2017-09-16 13:59:48.692479338 +0000
+@@ -62,7 +62,7 @@
+     </table>
+     
+     <table class="navigation">
+-     <tr><th align="left" colspan="3"><xsl:value-of select="$jump-to-date"/></th></tr>
++     <tr><th align="left" colspan="3"></th></tr>
+      <tr>
+       <td>
+        <xsl:choose>
+diff -urN ui_/splash.xsl ui/splash.xsl
+--- ui_/splash.xsl	2016-12-20 12:02:51.000000000 +0000
++++ ui/splash.xsl	2017-09-16 13:59:48.548476235 +0000
+@@ -39,7 +39,7 @@
+    </xsl:otherwise>
+   </xsl:choose>
+   <xsl:text> &#8212; </xsl:text>
+-  <i><xsl:value-of select="description"/></i>
++  <xsl:value-of select="description"/>
+  </li>
+  <xsl:text>&#10;</xsl:text>
+ </xsl:template>
+@@ -75,13 +75,13 @@
+    <div class="header">
+     <table class="external">
+      <tr>
+-      <td align="left"><h1><xsl:value-of select="server/archive"/></h1></td>
++      <td align="left"><img src="/logo.png"/></td>
+       <td align="right"><xsl:call-template name="navbar"/></td>
+      </tr>
+     </table>
+     
+     <table class="navigation">
+-     <tr><th align="left"><xsl:value-of select="$search-menu"/></th></tr>
++     <tr><th align="left"></th></tr>
+      <tr><td nowrap="NOWRAP" align="center">
+       <form action="{server/cgi-url}/keyword.cgi" accept-charset="UTF-8" onsubmit="form_timezone(this)">
+        <input type="hidden" name="doc-url" value="{server/doc-url}"/>
diff --git a/build.sh b/build.sh
index 6b12278..7269705 100755
--- a/build.sh
+++ b/build.sh
@@ -3,9 +3,12 @@
 # Install script for Lurker inside a Docker container.
 #
 
+BUILD_PACKAGES="
+	patch
+"
+
 PACKAGES="
 	lurker
-	python3-aiosmtpd
 "
 
 install_packages() {
@@ -20,10 +23,8 @@ die() {
 set -x
 
 # Install packages (aiosmtpd comes from backports in stretch).
-echo "deb http://deb.debian.org/debian stretch-backports main" \
-    > /etc/apt/sources.list.d/backports.list
 apt-get -q update
-install_packages ${PACKAGES} \
+install_packages ${BUILD_PACKAGES} ${PACKAGES} \
     || die "could not install packages"
 
 # Enable the apache modules we need.
@@ -39,15 +40,19 @@ mkdir -p /var/lib/lurker
 # so the original files would disappear "below" the mount. To
 # prevent this, we copy the files to a well-known location
 # beforehand, and set up links at run-time.
-mkdir -p /var/lib/lurker-www
-mv /etc/lurker/ui /var/lib/lurker-www/ui
-mv /var/lib/lurker/www/index.html /var/lib/lurker-www/index.html
+mkdir -p /var/lib/lurker-www-orig
+mv /etc/lurker/ui /var/lib/lurker-www-orig/ui
+mv /var/lib/lurker/www/index.html /var/lib/lurker-www-orig/index.html
+
+# Apply our UI patch.
+(cd /var/lib/lurker-www-orig/ui && patch -p1 </tmp/ai-lurker-ui.patch)
 
 # Clear the existing default config
 # (this will be mounted externally).
 rm -fr /etc/lurker/*
 
 # Clean up.
+apt-get --purge remove ${BUILD_PACKAGES}
 apt-get autoremove -y
 apt-get clean
 rm -fr /var/lib/apt/lists/*
diff --git a/logo.png b/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..064cb4f6ecccedb6608ac5e830118f0af7235d2b
GIT binary patch
literal 3314
zcmeAS@N?(olHy`uVBq!ia0y~yU`%FUU@+rgVqjpHJ0;(Zfq_A?#5JNMI6tkVJh3R1
z!7(L2DOJHUH!(dmC^a#qvhZZ84Fdzu6i*k&kcwMx=34uR-W5Ck@R`~LM&6PR-Vhs|
z4a$eaUn+Pl5>;_nve;qcZr%$KT4E(?2~DO#FANU4v$JYVHCZs%EQ$T>@xON?3-9mT
z{Qb<$&lZO#?*7MWc`n)h`mgs}uSZp{*}r4QieL?qE|)*f?G6hAG=eomxKg=Vofi5m
z4A7XODZ<ri)atY_U|E2M$SD!*;-;PTRd(C=?fduk_VyD;zkU1G*~$6&yt@Cq8~S`K
zE3)M4{{H&<@9*z<^X6q=U-z=ds<5hR*PcCh?%etF;o;#EYmXj1x^$`P@2Nt4eCyV(
z-CO&6+Wv2AfBmZZ{pipkrnS1;cuf*AGF}AjT5slBX<==B`{vEa$Vf{Yn=3ne9&>D2
zy?8OR)r0chEnI(>cwWAISzTS-%02wlvK5YfH}2oRfBUwzz5Vq_pAE_kX5nwQaP>9p
zytlV{x$qL7z|xu@9~>=}Br}rN79Kg?FMsp5hPy`alv5&B#U~4P$?1u&kKZ3QD`43V
z{$t0FzwJJI_N>*ZtvxGOt~_|~U{v<ickkBKZd|;0@rSNozkbar)m(K#<fapU{QkPL
z@g4T(&Yjy=|6fjR)3RmDv~o`<3q{Uea#K*@ZL~ULk=Ue$GfzbGB$&@_P`5vC9IEQ2
z%x2g7@#ev~^X94bZ(F(XMxE$Mk=L(Ze>*yl!OXhm-=Ci^UYvNDosp5zp#SUlZ{;-`
zH*XdW`^2&1_Kh1F``g>wZ{NCg=#9eFn~iadDHm_vv@|eC@H)}9b*pJk&N8iYjt>1Z
z?4KLy-Tu+lbJ*A>Q@`i*>C=VfhtC=>{kVtYT~tHY*K4eLL6tu)FZVz9sk*xQ{k^^3
z(ud|`{Cdh$TyUMI^`+~aDgLY*)_Wg*RA$bZ{LcPO=FP6Y3-eBBY4j#`WcbKr-{_r^
zxUhN4<rAXLdw1;c2z<zPd)=ex?RkY0jplBaF`pNj&b3_5ZHw&EyZ7$7WeT5awCiIk
zDKGEu>znoZg3Fv$&GPnjE!mv=SzA?i+s|zH`?vN6OV`HAv+Nw&p9PmYC3e+FCKMGJ
z85K`?u({WLldzokzTc(|E6;Uo_1`P#S^6lL;fT~q(^(Vl=yR3aD~&5zWmT&9Zkyk&
z<i1-Mx=&=iv3&C{sUgj-{-4c4!}H8{b{4lEyOFkRv*CnuU%r&2tk{_`qe*Z<^SMMB
zDXFN4h=OTzPQB2up3k(@cUh+aA3y*0ZQDMDJa-mOY->6yl%nToKXHGTi6GnOtZV0Q
zwR@~eS7|*iaFFHlG6#dUjHc&P7HWM6|0<=n+Lg(-W#i7BFK<e8m9G2qOo`{+63*tO
zOI6bh(%*Zfa*4hDaO%CMm}H3g9@Wm<5030*id?dG>7%6AEZyhlPbz=1<^1H6N^iAq
z#xV5D*?QeJ5LqK7nK92T^~k;tnLMetF16OGh%q)lIPAMps_duF!!2s>?(Y7+p5gK1
z$9}A7@e|fs9lL&St%<4W*>mUY>i$&J)&2YS_V&5$30p#D2Q5G9;aXf=EG;d)diClV
zv(9yWGOp!JxV!nJl;_`{pPwH+di3K*!@DJV4?<0~CBA*oyDPuRepOrPWJl>r)#$oi
zh8kX*eZ0>u=h)4ENGjDvYVqR587nQ6e{vU^n3+l4U-I+em#{6{wn^15`BSi|G?=0C
z*|W2=S7@)D^fsxwx;pk(2FEXl)48!p;!^kAK1nxUuG@Y?(Cl8L#r=6Vm;Po?nsfMu
z%mTfRDup#KbnTxk+H&wn)er8q9eKAG9|@Rkww#N1L4u$4y6xMif7@^`NcQ#G%Xc0(
zCY|p$a5={!R^{%xMN!dMw7Y@bM%le*$&H0=nmG%NignM6Ol>ItIWzqA>(_JV&OIUA
z#buh1bi~%u#zx0}j{C(O(jVtpF-vYZ(=D#QYuBz8BZclcftPkOy2QAAewtr#bn=5~
z#fdsKsgvc;35Rv~1xhL1&iSPwX#J{pa;e;8i>A*Svv$rtSo$c0-^*CUt^TL2nVHx%
zlZQqNw=HVBD`~^EUd%w8H+jmO+p52U3OA=oTu5Jfu+8+b^T{oW`>$^cS$05U!`a5q
zpFf}YsTU%C&0%KZggI9oZMV&T<lgW>bd~dos;a6_8`?V0oQ{vYJi|ME%Nu^DJ3;yr
z`%ZMJ?}_XcS;=wO>iS8KhOi$|LaR@C&g!@jmQwHX`9fK=#F1|+PxO3SaqOqXA-Mpy
z7O(s}J3gu#vT|F@?(Uk%(el86p~~9GXp*{kw^VJ={{5^EJa=?T8K;LD%nfK3aPghH
z^8~X?ZeHHG<GJ7T7*4C5Pj(E^zpQgktawrsr{oI1-cmER-0d?LEeaOq@^jrcQSbTr
zAFH%)F7ABh@8h#&+qNpZ{!M$UzG|IsvN14tP!fIY;fog?cPCt)A5?f-r%jK|>{d}~
z#-W@n6}9)A8LG2)8>(k%>E2yA|K=34x6xN0yx8<v^M;^<*x$c@|E*8qh;}>E#m+DH
zBVYT*j3vF>3?>S=Fj;TN7g--Sb=rC%2GOKrzi*dcNWJrJ?~|>6Hw7$6*IN6`{f~Gn
z&uP^PlZ|iN+uI}Gsy-K*{4l(M<#f|hyZ-Y`RkP;KT`KeHmz;v)b>TN}-~Rn>9b5Qs
z+x^qxT2FZT5BiqZJIkGZ7MgVJ@Xx-V%#SO>a#;Q*Gn7S$PPX3Y@@H}@x1)u*%^p>e
z)YCN<s^=8v<{YxP+k4c=HKzPU(G4C=6^Z)Hjr>0zMKN6TwA{g}Y;nCfFEoW~o@d<0
zfV&0Dwh6E=Nl<V8+pqp~{r)>g|NbpMWD+25Bxw0>!p-lAX?w*kS^Z{`;1YOLkS6?N
zLe#dz&dtX*CMn%It#jeZ2P>7rn<4IUkL*?_?pxsA_>DQH(<S1^@?syYyjhQac|SbI
zvDcDCWk0vz>`yZerI^gTJZI8r17qXEPb42b@Y?2ocjn>bKNHSySGena3XkERA!N|U
zlGJMP<N2vmUi11NSv-$>RGe6Q;*7|f?39%yyUrS~={3;_?GgAodFln7wJ#3bxija)
zd;#{eyX*c|nXQ~~Y!2Ip9MRYpZ{Kcp|M&Ft^dgBfGZF-6t@vGgX~~TmuB^hU8bfv8
zE7Oi0`I-0WM@hx?b+hdBSRGDu7tNe{TqJ&9O<|kjwr$%2VmZwhoIlss%HMX3v96Kh
z$=9DhE4l96yt&c4*-k+xImSWB%=d|Xd!J&$oc|}dE=Lv~68g4iHe-<K0Zk<lrBx@^
z-n|>^|9`%5CFjd0rOJ=|<i3=gbuipyAocBIPUw>hQyRKOl(eL_TTZ&X^ysa~l56Yu
z^d@iNQ;b>8^C4;84VK3O;hTI)0&8{pHFxdWb#G5)a=iQA`F6Fp?%m__weW8}G4aEP
zsn@QBJ)fKwlcLTfYq2x4x>{POv38D0p!l3A-``I!E_8ku9Tg?e^rRp&;-J8Erf`Pk
zwsU+-E?7NhT(WVaq35rj*U3lr_+Mb(I5lWytVmy*#qSLDsvBWJ4<G4f27a?BP*pr|
zrssK1&yu~Co|_}4i2qIq5VCvDAAdwv&Uod_ho%RYAN%+3-;NF)7RO${Sr4X$ES$-5
zd1KNJlcMX-Lqv~E*&LcF%fgW~XJTvH@vjrh+-5BLAfVPZ`*}vo#tj<+dK0v4W;i~7
z8~owsH@nrVS99{K++S<CYz6lw>0P^b|DB(oks%=|xv_TUl*x0ZC@$nRQ&@S)yhZKZ
z{r&T`K6k~sxf)CRCU2X=B7QAmhEn7gb#-;yx5Zsvc~k43^yCUot63#08G1Xjd&*>;
zO_{Nlmo|hve4c)Op6EaOww9YeA3QivEcw__PEYGK%ccbDOm6=06-y^@gxvfovUu_0
z$B!S2GD{Y)%rP=Hetd`HM{t7;=jITRl9TMB-?MJ{DXu^Fd5T-^g+`0?>WI(6F7v|_
zpRNpB`$W||v?rF&YlBp{j7(MwUyro@)mPIK(^Zt+W{UQ5dwl!xW5=!ZhfgO9^Mo+P
z7j&~9I{4m6;Xcd4{@wczzGuo_xqr=nZBHeIZOa|_@+yUlujQ*4FIu~{_xfD902aZo
z8;mt?F+KU76tv?>Vf$0I6a#(L#Df~26B=^XR!J);oi)+i%y7}{<f;v-SB(=L{f@L4
zb3eHfcFw=|6z5)#^rcU{Pu`u<5dI{4@ujm&*@EvT=N)_6V_>AKt9!0@#{SmO_5WAT
za{Bn3NodR6T@N=edBj_|%f{Ty?9X=lU-lB(BH_HVXU~3i`}8NqD;Cp!GMCA7wJw@)
zxBdBaYvm35f3ERa7!VUVXU?22U%xIbWxKtcx8(c6fS6Q|XQ5HEI=KBbgEd6L#e#!_
z+1c6WRjTG#9pUke?tW({(xuHLyxe?#iKqudX+eR3zf9Cjr-cD8-Z|s!1pN4aXg{k2
aLocIcKkKDqXBik67(8A5T-G@yGywplfn5gx

literal 0
HcmV?d00001

diff --git a/start.sh b/start.sh
index 8a01ede..c4f2f38 100755
--- a/start.sh
+++ b/start.sh
@@ -1,7 +1,27 @@
 #!/bin/sh
+#
+# Setup script for the Lurker Docker container.
+#
+# Since /var/lib/lurker is mounted externally, ensure that it
+# has the required structure, and that all the contents that
+# were originally installed by the lurker package in those
+# directories are correctly symlinked to $static_dir.
+#
 
+data_dir=/var/lib/lurker/data
 www_dir=/var/lib/lurker/www
-static_dir=/var/lib/lurker-www
+static_dir=/var/lib/lurker-www-orig
+
+umask 077
+set -e
+
+echo "Checking dirs..." >&2
+
+mkdir -p ${data_dir}
+mkdir -p ${www_dir}
+for sub in attach list mbox message mindex search splash thread zap; do
+    mkdir -p ${www_dir}/${sub}
+done
 
 echo "Fixing symlinks..." >&2
 
@@ -18,4 +38,11 @@ if [ ! -e ${www_dir}/lurker.docroot ]; then
     touch ${www_dir}/lurker.docroot
 fi
 
+# The logo.png symlink switches between custom / builtin.
+logo_src=${static_dir}/logo.png
+if [ -e /etc/lurker/logo.png ]; then
+    logo_src=/etc/lurker/logo.png
+fi
+ln -sf ${logo_src} ${www_dir}/logo.png
+
 exit 0
-- 
GitLab