The cache is at the coordinates above. These coords will get
+you to the correct park and within 1/2 mile of the cache. The cache
+is within 35 feet of the trail. It is not handicapped accessible.
+It is a nice walk in the woods that is practical for all ages.
+There is no space in the container for trading items. You should
+bring a writing stick and bug spray is recommended.
+
So if the cache isn't at the above coordinates, where is it?
+
+
Too bad I hid a boot
+
Too hot to hoot
+
Never odd or even
+
Do geese see God?
+
"Do nine men interpret?" "Nine men," I nod
+
Rats live on no evil star
+
Go hang a salami, I'm a lasagna hog
+Now that it's intuitively obvious to even the most casual observer
+where the cache is, turn on your geo-mojo and go find it.
+
+
+
+
+
+
+
+
diff --git a/reference/gc/GCGCA8~vcard.vcf b/reference/gc/GCGCA8~vcard.vcf
index 1d94b1408..3ea25b265 100644
--- a/reference/gc/GCGCA8~vcard.vcf
+++ b/reference/gc/GCGCA8~vcard.vcf
@@ -3,5 +3,5 @@ VERSION:3.0
N:Oozy rat in a sanitary zoo;GCGCA8;;;
ADR:N35 55.300 W86 51.700
URL:https://www.geocaching.com/geocache/GCGCA8
-NOTE:The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.\nSo if the cache isn't at the above coordinates\, where is it? Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men\," I nod Rats live on no evil star Go hang a salami\, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is\, turn on your geo-mojo and go find it. \n [IMG]\n \n\n\nHINT:\n
+NOTE:The cache is not at the coordinates above. These coords will get you to the correct park and within 1/2 mile of the cache. The cache is within 35 feet of the trail. It is not handicapped accessible. It is a nice walk in the woods that is practical for all ages. There is no space in the container for trading items. You should bring a writing stick and bug spray is recommended.\nSo if the cache isn't at the above coordinates\, where is it? Too bad I hid a boot Too hot to hoot Never odd or even Do geese see God? "Do nine men interpret?" "Nine men\," I nod Rats live on no evil star Go hang a salami\, I'm a lasagna hog Now that it's intuitively obvious to even the most casual observer where the cache is\, turn on your geo-mojo and go find it. \n [IMG]\n \n\n\nHINT:\n
END:VCARD
diff --git a/testo b/testo
index fc5550162..5083eead1 100755
--- a/testo
+++ b/testo
@@ -189,4 +189,5 @@ if [ -z "${VALGRIND}" ]; then
fi
fi
+echo "Total Errors: $errorcount"
exit $errorcount
diff --git a/testo.d/text.test b/testo.d/text.test
index e89b52226..4307260bb 100644
--- a/testo.d/text.test
+++ b/testo.d/text.test
@@ -16,3 +16,7 @@ gpsbabel -i gpx -f ${REFERENCE}/gc/GC7FA4.gpx \
-o text,logs -F ${TMPDIR}/GC7FA4.text
compare ${REFERENCE}/gc/GC7FA4.html ${TMPDIR}/GC7FA4.html
compare ${REFERENCE}/gc/GC7FA4.text ${TMPDIR}/GC7FA4.text
+
+# GCGC8_nasty.gpx is hand modifed to test strip_nasty_html
+gpsbabel -i gpx -f ${REFERENCE}/gc/GCGCA8_nasty.gpx -o html -F ${TMPDIR}/GCGCA8_nasty.html
+compare ${REFERENCE}/gc/GCGCA8_nasty.html ${TMPDIR}/GCGCA8_nasty.html
diff --git a/tools/Dockerfile_f37 b/tools/Dockerfile_f37
index 426f2e5a2..bd03210df 100644
--- a/tools/Dockerfile_f37
+++ b/tools/Dockerfile_f37
@@ -20,3 +20,7 @@ RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebeng
# tools to build the docs
RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+ dnf debuginfo-install --assumeyes qt6-qtbase && \
+ dnf clean all
diff --git a/tools/Dockerfile_f38 b/tools/Dockerfile_f38
index d1aa6cbd0..bd26dbde5 100644
--- a/tools/Dockerfile_f38
+++ b/tools/Dockerfile_f38
@@ -20,3 +20,7 @@ RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebeng
# tools to build the docs
RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+ dnf debuginfo-install --assumeyes qt6-qtbase && \
+ dnf clean all
diff --git a/tools/Dockerfile_f39 b/tools/Dockerfile_f39
index 5d89d175f..c172680ac 100644
--- a/tools/Dockerfile_f39
+++ b/tools/Dockerfile_f39
@@ -13,10 +13,12 @@ RUN dnf install --assumeyes git make valgrind diffutils findutils langpacks-en n
RUN dnf install --assumeyes libusb1-devel zlib-devel shapelib-devel && \
dnf clean all
# Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
- dnf clean all
RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebengine-devel qt6-linguist qt6-qttranslations qt6-qt5compat-devel qt6-qttools-devel libxkbcommon-devel && \
dnf clean all
# tools to build the docs
RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+ dnf debuginfo-install --assumeyes qt6-qtbase && \
+ dnf clean all
diff --git a/tools/Dockerfile_f40 b/tools/Dockerfile_f40
index fe9e83448..0f037c2c4 100644
--- a/tools/Dockerfile_f40
+++ b/tools/Dockerfile_f40
@@ -13,10 +13,12 @@ RUN dnf install --assumeyes git make valgrind diffutils findutils langpacks-en n
RUN dnf install --assumeyes libusb1-devel zlib-devel shapelib-devel && \
dnf clean all
# Qt used by gpsbabel, gpsbabelfe
-RUN dnf install --assumeyes qt5-qtbase-devel qt5-qtserialport-devel qt5-qtwebengine-devel qt5-linguist qt5-qttranslations && \
- dnf clean all
RUN dnf install --assumeyes qt6-qtbase-devel qt6-qtserialport-devel qt6-qtwebengine-devel qt6-linguist qt6-qttranslations qt6-qt5compat-devel qt6-qttools-devel libxkbcommon-devel && \
dnf clean all
# tools to build the docs
RUN dnf install --assumeyes expat desktop-file-utils libxslt docbook-style-xsl fop docbook5-style-xsl docbook5-schemas && \
dnf clean all
+# debuginfo for valgrind suppressions (or use DEBUGINFOD server)
+RUN dnf install --assumeyes 'dnf-command(debuginfo-install)' && \
+ dnf debuginfo-install --assumeyes qt6-qtbase && \
+ dnf clean all
diff --git a/tools/Dockerfile_jammy b/tools/Dockerfile_jammy
index bd6b75b9b..59671c317 100644
--- a/tools/Dockerfile_jammy
+++ b/tools/Dockerfile_jammy
@@ -89,6 +89,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
qt6-wayland \
&& rm -rf /var/lib/apt/lists/*
+# dbgsyms for "libqt6core6/jammy-updates,now 6.2.4+dfsg-2ubuntu1.1 amd64" needed for gpsbabel.supp
+# these aren't on the debuginfod server, or on http://ddebs.ubuntu.com
+RUN curl -L http://launchpadlibrarian.net/638061995/libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb -o libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb \
+ && apt-get install ./libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64.ddeb \
+ && rm -f ./libqt6core6-dbgsym_6.2.4+dfsg-2ubuntu1.1_amd64
+
# pkgs needed to generate coverage report:
RUN apt-get update && apt-get install -y --no-install-recommends \
gcovr \
diff --git a/tools/Dockerfile_noble b/tools/Dockerfile_noble
index a96fa1683..ac01c7e92 100644
--- a/tools/Dockerfile_noble
+++ b/tools/Dockerfile_noble
@@ -71,6 +71,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
qt6-wayland \
&& rm -rf /var/lib/apt/lists/*
+# dbgsyms for "libqt6core6t64/noble,now 6.4.2+dfsg-21.1build5 amd64" needed for gpsbabel.supp
+RUN apt-get update && apt-get install -y --no-install-recommends ubuntu-dbgsym-keyring \
+ && echo "deb http://ddebs.ubuntu.com noble main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && echo "deb http://ddebs.ubuntu.com noble-updates main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && echo "deb http://ddebs.ubuntu.com noble-proposed main restricted universe multiverse" >> /etc/apt/sources.list.d/ddebs.list \
+ && apt-get update && apt-get install -y --no-install-recommends libqt6core6t64-dbgsym \
+ && rm -rf /var/lib/apt/lists/*
+
# pkgs needed to generate coverage report:
RUN apt-get update && apt-get install -y --no-install-recommends \
gcovr \
diff --git a/util.cc b/util.cc
index 7840d5268..4259d345f 100644
--- a/util.cc
+++ b/util.cc
@@ -20,7 +20,7 @@
*/
#include // for sort
-#include // for isspace, tolower
+#include // for assert
#include // for errno
#include // for INT_MAX, INT_MIN
#include // for fabs, floor
@@ -35,6 +35,9 @@
#include // for QDateTime
#include // for QFileInfo
#include // for QList
+#include // for QRegularExpression
+#include // for QRegularExpressionMatch
+#include // for QRegularExpressionMatchIterator
#include // for QString
#include // for QTextBoundaryFinder, QTextBoundaryFinder::Grapheme
#include // for QTextCodec
@@ -734,92 +737,29 @@ pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html)
/*
* Get rid of potentially nasty HTML that would influence another record
* that includes;
- * - to stop backgrounds/background colours from being loaded
+ * - to stop backgrounds/background colors from being loaded
* and - stop processing altogether
* - stop overriding styles for everything
*/
QString
strip_nastyhtml(const QString& in)
{
- char* returnstr = xstrdup(in);
- char* lcstr = xstrdup(in.toLower());
-
- while (char* lcp = strstr(lcstr, "")) {
- char* sp = returnstr + (lcp - lcstr) ; /* becomes */
- sp++;
- *sp++ = '!';
- *sp++ = ' ';
- *sp++ = ' ';
- *sp++ = ' ';
- *lcp = '*'; /* so we wont find it again */
- }
- while (char* lcp = strstr(lcstr, " */
- char* sp = returnstr + (lcp - lcstr) ;
- sp++;
- *sp++ = '!';
- *sp++ = '-';
- *sp++ = '-';
- while ((*sp) && (*sp != '>')) {
- sp++;
- }
- *--sp = '-';
- *--sp = '-';
- *lcp = '*'; /* so we wont find it again */
- }
- while (char* lcp = strstr(lcstr, "")) {
- char* sp = returnstr + (lcp - lcstr) ; /* becomes */
- *sp++ = ' ';
- *sp++ = ' ';
- *sp++ = ' ';
- *sp++ = ' ';
- *sp++ = ' ';
- *sp++ = '-';
- *sp++ = '-';
- *lcp = '*'; /* so we wont find it again */
- }
- while (char* lcp = strstr(lcstr, "", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+ assert(htmlre.isValid());
+ static const QRegularExpression bodyre("", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+ assert(bodyre.isValid());
+ static const QRegularExpression stylere(".*?", QRegularExpression::CaseInsensitiveOption | QRegularExpression::DotMatchesEverythingOption);
+ assert(stylere.isValid());
+ QString out(in);
+
+ out.replace(bodyre, "");
+ out.replace("", "", Qt::CaseInsensitive);
+ out.replace(htmlre, "");
+ out.replace("", "", Qt::CaseInsensitive);
+ out.replace(stylere, "");
+ out.replace("[^ >]*).*?>)|(?:&(?.*?);)|(?[^<&]+)|(?.+)",
+ QRegularExpression::DotMatchesEverythingOption);
+ assert(re.isValid());
+ static const QRegularExpression newlinespace_re(R"(\s*\n\s*)");
+ assert(newlinespace_re.isValid());
+ QString out;
+
+ QRegularExpressionMatchIterator it = re.globalMatch(utfstring);
+ while (it.hasNext()) {
+ auto match = it.next();
+ //qDebug() << match.capturedTexts();
+ // TODO: Qt >= 6.3 use match.hasCaptured(...) instead of !match.captured(...).isNull()
+ if (!match.captured(u"tag").isNull()) {
+ QString tag = match.captured(u"tag");
+ //qDebug() << "tag match:" << tag;
+ if ((tag.compare("p", Qt::CaseInsensitive) == 0) ||
+ (tag.compare("br", Qt::CaseInsensitive) == 0) ||
+ (tag.compare("/tr", Qt::CaseInsensitive) == 0)) {
+ out.append('\n');
+ } else if (tag.compare("/td", Qt::CaseInsensitive) == 0) {
+ out.append(' ');
+ } else if (tag.startsWith("img", Qt::CaseInsensitive)) {
+ out.append("[IMG]");
+ } // else eat the tag
+ } else if (!match.captured(u"entity").isNull()) {
+ QString entity = match.captured(u"entity");
+ //qDebug() << "entity match:" << entity;
+ if (entity == "amp") {
+ out.append('&');
+ } else if (entity == "lt") {
+ out.append('<');
+ } else if (entity == "gt") {
+ out.append('>');
+ } else if (entity == "quot") {
+ out.append('"');
+ } else if (entity == "nbsp") {
+ out.append(' ');
+ } else if (entity == "deg") {
+ out.append("deg");
+ } // else eat the entity
+ } else if (!match.captured(u"other").isNull()) {
+ //qDebug() << "other match:" << match.capturedTexts();
+ out.append(match.captured(u"other").replace(newlinespace_re, " "));
+ //} else {
+ // qDebug() << "unexpected fragment:" << match.capturedTexts();
}
-
- if (! tag[0]) {
- if (*instr == '\n') {
- *out++ = ' ';
- do {
- instr++;
- } while (isspace(*instr));
- continue;
- } else {
- *out++ = *instr;
- }
- } else {
- if (taglen < (sizeof(tag)-1)) {
- tag[taglen++] = tolower(*instr);
- tag[taglen] = 0;
- }
- }
-
- if (((tag[0] == '<') && (*instr == '>')) ||
- ((tag[0] == '&') && (*instr == ';'))) {
- if (! strcmp(tag, "&")) {
- *out++ = '&';
- } else if (! strcmp(tag, "<")) {
- *out++ = '<';
- } else if (! strcmp(tag, ">")) {
- *out++ = '>';
- } else if (! strcmp(tag, """)) {
- *out++ = '"';
- } else if (! strcmp(tag, " ")) {
- *out++ = ' ';
- } else if (! strcmp(tag, "°")) {
- *out++ = 'd';
- *out++ = 'e';
- *out++ = 'g';
- } else if ((tag[0]=='<') && (tag[1]=='p')) {
- *out++ = '\n';
- } else if ((tag[0]=='<') && (tag[1]=='b') && (tag[2]=='r')) {
- *out++ = '\n';
- } else if ((tag[0]=='<') && (tag[1]=='/') && (tag[2]=='t') && (tag[3]=='r')) {
- *out++ = '\n';
- } else if ((tag[0]=='<') && (tag[1]=='/') && (tag[2]=='t') && (tag[3]=='d')) {
- *out++ = ' ';
- } else if ((tag[0]=='<') && (tag[1]=='i') && (tag[2]=='m') && (tag[3]=='g')) {
- *out++ = '[';
- *out++ = 'I';
- *out++ = 'M';
- *out++ = 'G';
- *out++ = ']';
- }
-
- tag[0] = 0;
- }
- instr++;
}
- *out++ = 0;
- xfree(incopy);
- QString rv(outstring);
- xfree(outstring);
- return rv;
+
+ return out;
#endif
}