<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">Initially, JSword only accepted Major.Minor, converting that into a decimal. That was based on a poor understanding of the CrossWire wiki. That was changed to match SWORD’s 4 part “number” with a minor modification.</div><div class=""><br class=""></div>JSword will reject any version that doesn’t match the pattern:&nbsp;^(\d+)(?:.(\d+))?(?:.(\d+))?(?:.(\d+))?$<div class=""><br class=""></div><div class="">I think I encoded this to allow pretty much any single non-digit separator. The . will match any single character and \d+ is greedy. So it will accept Karl’s encoding.<br class=""><div class=""><div class=""><br class=""></div><div class="">The wiki on the conf clearly states: “Do not use non-numbers, such as 1.4a”</div><div class="">(See:&nbsp;<a href="http://wiki.crosswire.org/DevTools:conf_Files" class="">http://wiki.crosswire.org/DevTools:conf_Files</a>)</div><div class=""><br class=""></div><div class="">The conf also documents that the third part should be incremented when only the conf is affected. The first or second when the module is different.</div><div class=""><br class=""></div><div class="">Here is JSword's code:<br class=""><div><div>/**</div><div>&nbsp;* Distribution License:</div><div>&nbsp;* JSword is free software; you can redistribute it and/or modify it under</div><div>&nbsp;* the terms of the GNU Lesser General Public License, version 2.1 or later</div><div>&nbsp;* as published by the Free Software Foundation. This program is distributed</div><div>&nbsp;* in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even</div><div>&nbsp;* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.</div><div>&nbsp;* See the GNU Lesser General Public License for more details.</div><div>&nbsp;*</div><div>&nbsp;* The License is available on the internet at:</div><div>&nbsp;* &nbsp; &nbsp; &nbsp;<a href="http://www.gnu.org/copyleft/lgpl.html" class="">http://www.gnu.org/copyleft/lgpl.html</a></div><div>&nbsp;* or by writing to:</div><div>&nbsp;* &nbsp; &nbsp; &nbsp;Free Software Foundation, Inc.</div><div>&nbsp;* &nbsp; &nbsp; &nbsp;59 Temple Place - Suite 330</div><div>&nbsp;* &nbsp; &nbsp; &nbsp;Boston, MA 02111-1307, USA</div><div>&nbsp;*</div><div>&nbsp;* © CrossWire Bible Society, 2011 - 2016</div><div>&nbsp;*</div><div>&nbsp;*/</div><div>package org.crosswire.common.util;</div><div><br class=""></div><div>import java.util.regex.Matcher;</div><div>import java.util.regex.Pattern;</div><div><br class=""></div><div>/**</div><div>&nbsp;* Version is an immutable representation of dotted "number" consisting of 1 to 4 parts.</div><div>&nbsp;*&nbsp;</div><div>&nbsp;* &lt;p&gt;</div><div>&nbsp;* Here is the grammar for version strings:</div><div>&nbsp;* &lt;/p&gt;</div><div>&nbsp;* &lt;pre&gt;</div><div>&nbsp;* version ::= major('.'minor('.'micro('.'nano)?)?)?</div><div>&nbsp;* major ::= [0-9]+</div><div>&nbsp;* minor ::= [0-9]+</div><div>&nbsp;* micro ::= [0-9]+</div><div>&nbsp;* nano &nbsp;::= [0-9]+</div><div>&nbsp;* &lt;/pre&gt;</div><div>&nbsp;*&nbsp;</div><div>&nbsp;* @see gnu.lgpl.License The GNU Lesser General Public License for details.</div><div>&nbsp;* @author DM Smith</div><div>&nbsp;*/</div><div>public class Version implements Comparable&lt;Version&gt; {</div><div>&nbsp; &nbsp; public static final Pattern VERSION_PATTERN = Pattern.compile("^(\\d+)(?:.(\\d+))?(?:.(\\d+))?(?:.(\\d+))?$");</div><div><br class=""></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Created a version identifier from the specified string.</div><div>&nbsp; &nbsp; &nbsp;*&nbsp;</div><div>&nbsp; &nbsp; &nbsp;* @param version String representation of the version identifier.</div><div>&nbsp; &nbsp; &nbsp;* @throws IllegalArgumentException If &lt;code&gt;version&lt;/code&gt; is improperly</div><div>&nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; formatted.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; public Version(String version) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (version == null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException("Null version not allowed.");</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; this.original = version;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; this.parts = new int[] { -1, -1, -1, -1 };</div><div>&nbsp; &nbsp; &nbsp; &nbsp; Matcher matcher = VERSION_PATTERN.matcher(this.original);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (matcher.matches()) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int count = matcher.groupCount();</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 1; i &lt;= count; i++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String part = matcher.group(i);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (part == null) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parts[i - 1] = Integer.parseInt(part);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; } else {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalArgumentException("invalid: " + version);</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Returns the original string representation of this version identifier.</div><div>&nbsp; &nbsp; &nbsp;*</div><div>&nbsp; &nbsp; &nbsp;* @return The original string representation of this version identifier.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; @Override</div><div>&nbsp; &nbsp; public String toString() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return original;</div><div>&nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; @Override</div><div>&nbsp; &nbsp; public int hashCode() {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; return original.hashCode();</div><div>&nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Compares this &lt;code&gt;Version&lt;/code&gt; object to another object.</div><div>&nbsp; &nbsp; &nbsp;*&nbsp;</div><div>&nbsp; &nbsp; &nbsp;* &lt;p&gt;</div><div>&nbsp; &nbsp; &nbsp;* A version is considered to be equal to another version if all the</div><div>&nbsp; &nbsp; &nbsp;* parts are equal.&lt;/p&gt;</div><div>&nbsp; &nbsp; &nbsp;*&nbsp;</div><div>&nbsp; &nbsp; &nbsp;* @param object The &lt;code&gt;Version&lt;/code&gt; object to be compared.</div><div>&nbsp; &nbsp; &nbsp;* @return true if the two objects are equal.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; @Override</div><div>&nbsp; &nbsp; public boolean equals(Object object) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (!(object instanceof Version)) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; &nbsp; &nbsp; Version that = (Version) object;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (that == this) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt; parts.length; i++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (parts[i] != that.parts[i]) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; &nbsp; &nbsp; return true;</div><div>&nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; /**</div><div>&nbsp; &nbsp; &nbsp;* Compares this &lt;code&gt;Version&lt;/code&gt; object to another object.</div><div>&nbsp; &nbsp; &nbsp;*&nbsp;</div><div>&nbsp; &nbsp; &nbsp;* &lt;p&gt;</div><div>&nbsp; &nbsp; &nbsp;* The comparison considers each of the parts (major, minor, micro, nano) in turn,</div><div>&nbsp; &nbsp; &nbsp;* comparing like with like. At any point the comparison is not equal, a result is</div><div>&nbsp; &nbsp; &nbsp;* known.</div><div>&nbsp; &nbsp; &nbsp;* &lt;/p&gt;</div><div>&nbsp; &nbsp; &nbsp;*&nbsp;</div><div>&nbsp; &nbsp; &nbsp;* @param object The &lt;code&gt;Version&lt;/code&gt; object to be compared.</div><div>&nbsp; &nbsp; &nbsp;* @return A negative integer, zero, or a positive integer if this object is</div><div>&nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; less than, equal to, or greater than the specified</div><div>&nbsp; &nbsp; &nbsp;* &nbsp; &nbsp; &nbsp; &nbsp; &lt;code&gt;Version&lt;/code&gt; object.</div><div>&nbsp; &nbsp; &nbsp;* @throws ClassCastException If the specified object is not a &lt;code&gt;Version&lt;/code&gt;.</div><div>&nbsp; &nbsp; &nbsp;*/</div><div>&nbsp; &nbsp; public int compareTo(Version object) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; if (object == this) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 0;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i &lt; parts.length; i++) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int result = parts[i] - object.parts[i];</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (result != 0) {</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp; &nbsp; &nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; &nbsp; &nbsp; return 0;</div><div>&nbsp; &nbsp; }</div><div><br class=""></div><div>&nbsp; &nbsp; private final String &nbsp; &nbsp; &nbsp; &nbsp; original;</div><div>&nbsp; &nbsp; private final int[] &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;parts;</div><div><br class=""></div><div>}</div><div class=""><br class=""></div><blockquote type="cite" class=""><div class="">On Sep 25, 2018, at 7:07 AM, David Haslam &lt;<a href="mailto:dfhdfh@protonmail.com" class="">dfhdfh@protonmail.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Thanks Peter,</div>
<div class="">
<br class="">
</div>
<div class="">We should therefore also&nbsp;encourage Karl to review and update any such modules in the Xiphos repository.</div>
<div class="">
<br class="">
</div>
<div class="">The reason I added my aside was that version values are clearly used for comparison purposes to determine whether a module has been updated.</div>
<div class="">Version is&nbsp;one of maybe only a few configuration&nbsp;keys upon which calculations are made.</div>
<div class="">This logically led me to pose the question about potential buffer overflows, even though I'm not part of the SWORD coding team.</div>
<div class="">cf.&nbsp;My awareness of what can be exploited from a buffer overflow or the like has been honed by 13 years of watching the Security Now! webcasts on <a href="http://twit.tv" class="">twit.tv</a></div>
<div class="">
<br class="">
</div>
<div class="">Further aside: How does JSword process the same key?</div>
<div class="">
<br class="">
</div>
<div class="">David</div>
<div class="">
<br class="">
</div>
<div id="protonmail_mobile_signature_block" class="">Sent from ProtonMail Mobile</div>
<div class="">
<br class="">
<div class="">
<div class="">
<br class="">
</div>On Tue, Sep 25, 2018 at 11:54, Peter Von Kaehne &lt;<a href="mailto:refdoc@gmx.net" class="">refdoc@gmx.net</a>&gt; wrote:</div>
<blockquote class="protonmail_quote" type="cite">I think there are two aspects then - version numbers should be correct in current modules. I think the bulk of the modules you listed are Xiphos, not CrossWire, but at least one is issued by CrossWire, maybe more. I will fix CrossWire's set.
<br class="">
<br class="">The other is - wrong version numbers should not crash the engine or produce unreliable/undefined results. Or at least the engine should go down with a decent error message. In essence all places where wrong module conf file entries can cause grief in
        the engine, I guess some level of sanity checking should happen - Particularly if we want to encourage other publishers to take up offering repositories.
<br class="">
<br class="">Peter
<br class="">
<br class="">
<br class="">
<br class="">&gt; Gesendet: Dienstag, 25. September 2018 um 10:56 Uhr
<br class="">&gt; Von: "Jaak Ristioja" &lt;<a href="mailto:jaak@ristioja.ee" class="">jaak@ristioja.ee</a>&gt;
<br class="">&gt; An: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a>
<br class="">&gt; Betreff: Re: [sword-devel] Module version numbers
<br class="">&gt;
<br class="">&gt; &gt; Aside: Are there any limits to the number of dot separators in the
<br class="">&gt; Version value, or to the number of digits in total or in any part?
<br class="">&gt; &gt; Would SWORD crash with a buffer overflow were it to encounter an
<br class="">&gt; inordinately long Version?
<br class="">&gt;
<br class="">&gt; The relevant code to parse the version string is in the SWVersion
<br class="">&gt; constructor:
<br class="">&gt;
<br class="">&gt; SWVersion::SWVersion(const char *version) {
<br class="">&gt; char *buf = new char[ strlen(version) + 1 ];
<br class="">&gt; char *tok;
<br class="">&gt; major = minor = minor2 = minor3 = -1;
<br class="">&gt;
<br class="">&gt; strcpy(buf, version);
<br class="">&gt; tok = strtok(buf, ".");
<br class="">&gt; if (tok)
<br class="">&gt; major = atoi(tok);
<br class="">&gt; tok = strtok(0, ".");
<br class="">&gt; if (tok)
<br class="">&gt; minor = atoi(tok);
<br class="">&gt; tok = strtok(0, ".");
<br class="">&gt; if (tok)
<br class="">&gt; minor2 = atoi(tok);
<br class="">&gt; tok = strtok(0, ".");
<br class="">&gt; if (tok)
<br class="">&gt; minor3 = atoi(tok);
<br class="">&gt; delete [] buf;
<br class="">&gt; }
<br class="">&gt;
<br class="">&gt; Very long version strings can only crash it if this runs out of memory.
<br class="">&gt; Other than that, it will just return an incorrect version. There are no
<br class="">&gt; limits to the number of dot separators, but only up to 4 version
<br class="">&gt; components separated by dots are actually parsed. AFAIK, the behavior of
<br class="">&gt; atoi() is undefined for invalid input. On my system, the results are as
<br class="">&gt; follows:
<br class="">&gt;
<br class="">&gt; "9.1" -&gt; 9.1
<br class="">&gt; "99.1" -&gt; 99.1
<br class="">&gt; "999.1" -&gt; 999.1
<br class="">&gt; "9999.1" -&gt; 9999.1
<br class="">&gt; "99999.1" -&gt; 99999.1
<br class="">&gt; "999999.1" -&gt; 999999.1
<br class="">&gt; "9999999.1" -&gt; 9999999.1
<br class="">&gt; "99999999.1" -&gt; 99999999.1
<br class="">&gt; "999999999.1" -&gt; 999999999.1
<br class="">&gt; "9999999999.1" -&gt; 1410065407.1
<br class="">&gt; "99999999999.1" -&gt; 1215752191.1
<br class="">&gt; "999999999999.1" -&gt; -727379969.1
<br class="">&gt; "9999999999999.1" -&gt; 1316134911.1
<br class="">&gt; "99999999999999.1" -&gt; 276447231.1
<br class="">&gt; "999999999999999.1" -&gt; -1530494977.1
<br class="">&gt; "9999999999999999.1" -&gt; 1874919423.1
<br class="">&gt; "99999999999999999.1" -&gt; 1569325055.1
<br class="">&gt; "999999999999999999.1" -&gt; -1486618625.1
<br class="">&gt; "9999999999999999999.1" -&gt; -1.1
<br class="">&gt; "99999999999999999999.1" -&gt; -1.1
<br class="">&gt;
<br class="">&gt;
<br class="">&gt; J
<br class="">&gt;
<br class="">&gt; On 25.09.2018 12:03, David Haslam wrote:
<br class="">&gt; &gt; Ignoring the spurious SwordVersion hit, it seems that the string after the dash is a date in six digit format.
<br class="">&gt; &gt;
<br class="">&gt; &gt; IMHO, these modules should simply be re-issued with the dates recorded in the respective History key.
<br class="">&gt; &gt;
<br class="">&gt; &gt; It's not worth the effort to make the API parse these as they are now.
<br class="">&gt; &gt; The dash is a nonconformance to what should be in the Version key.
<br class="">&gt; &gt;
<br class="">&gt; &gt; Aside: Are there any limits to the number of dot separators in the Version value, or to the number of digits in total or in any part?
<br class="">&gt; &gt; Would SWORD crash with a buffer overflow were it to encounter an inordinately long Version?
<br class="">&gt; &gt;
<br class="">&gt; &gt; Best regards,
<br class="">&gt; &gt;
<br class="">&gt; &gt; David
<br class="">&gt; &gt;
<br class="">&gt; &gt; Sent from ProtonMail Mobile
<br class="">&gt; &gt;
<br class="">&gt; &gt; On Tue, Sep 25, 2018 at 09:44, Jaak Ristioja &lt;<a href="mailto:jaak@ristioja.ee" class="">jaak@ristioja.ee</a>&gt; wrote:
<br class="">&gt; &gt;
<br class="">&gt; &gt;&gt; Hello!
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; Most modules include version numbers matching the regular expression
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; ^[0-9]+(.[0-9]+)*$
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; However, looking at the .conf files, there are version fields with
<br class="">&gt; &gt;&gt; values also containing dashes:
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; ~/.sword/mods.d $ grep -E 'Version=.*-' *
<br class="">&gt; &gt;&gt; 2tgreek.conf:Version=2.7-120109
<br class="">&gt; &gt;&gt; invstrongsrealgreek.conf:Version=1.4-090107
<br class="">&gt; &gt;&gt; jesermons.conf:SwordVersion=2017-05-24
<br class="">&gt; &gt;&gt; strongsrealgreek.conf:Version=1.5-150704
<br class="">&gt; &gt;&gt; tischmorph.conf:Version=2.7-120109
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; How should these be interpreted? Should 1.2-3.4 be interpreted as
<br class="">&gt; &gt;&gt; (1).(2-3).(4) or (1.2)-(3.4)? It seems that SWVersion interprets such as
<br class="">&gt; &gt;&gt; just 1.2.4 (without the -3 entirely).
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; God bless!
<br class="">&gt; &gt;&gt; J
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; _______________________________________________
<br class="">&gt; &gt;&gt; sword-devel mailing list: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a>
<br class="">&gt; &gt;&gt; <a href="http://www.crosswire.org/mailman/listinfo/sword-devel" class="">http://www.crosswire.org/mailman/listinfo/sword-devel</a>
<br class="">&gt; &gt;&gt; Instructions to unsubscribe/change your settings at above page
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt;
<br class="">&gt; &gt;&gt; _______________________________________________
<br class="">&gt; &gt;&gt; sword-devel mailing list: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a>
<br class="">&gt; &gt;&gt; <a href="http://www.crosswire.org/mailman/listinfo/sword-devel" class="">http://www.crosswire.org/mailman/listinfo/sword-devel</a>
<br class="">&gt; &gt;&gt; Instructions to unsubscribe/change your settings at above page
<br class="">&gt;
<br class="">&gt;
<br class="">&gt; _______________________________________________
<br class="">&gt; sword-devel mailing list: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a>
<br class="">&gt; <a href="http://www.crosswire.org/mailman/listinfo/sword-devel" class="">http://www.crosswire.org/mailman/listinfo/sword-devel</a>
<br class="">&gt; Instructions to unsubscribe/change your settings at above page
<br class="">&gt;
<br class="">
<br class="">_______________________________________________
<br class="">sword-devel mailing list: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a>
<br class=""><a href="http://www.crosswire.org/mailman/listinfo/sword-devel" class="">http://www.crosswire.org/mailman/listinfo/sword-devel</a>
<br class="">Instructions to unsubscribe/change your settings at above page
<br class="">
</blockquote>
</div>_______________________________________________<br class="">sword-devel mailing list: <a href="mailto:sword-devel@crosswire.org" class="">sword-devel@crosswire.org</a><br class=""><a href="http://www.crosswire.org/mailman/listinfo/sword-devel" class="">http://www.crosswire.org/mailman/listinfo/sword-devel</a><br class="">Instructions to unsubscribe/change your settings at above page</div></blockquote></div><br class=""></div></div></div></body></html>