diff --git a/doxygen-1.8.10-SOURCE_DATE_EPOCH.patch b/doxygen-1.8.10-SOURCE_DATE_EPOCH.patch
new file mode 100644
index 0000000..2ed341b
--- /dev/null
+++ b/doxygen-1.8.10-SOURCE_DATE_EPOCH.patch
@@ -0,0 +1,154 @@
+diff --git a/qtools/qcstring.cpp b/qtools/qcstring.cpp
+index 45ccef9..35b9bb8 100644
+--- a/qtools/qcstring.cpp
++++ b/qtools/qcstring.cpp
+@@ -460,6 +460,12 @@ ulong QCString::toULong(bool *ok) const
+ return s.toULong(ok);
+ }
+
++uint64 QCString::toUInt64(bool *ok) const
++{
++ QString s(data());
++ return s.toUInt64(ok);
++}
++
+ QCString &QCString::setNum(short n)
+ {
+ return setNum((long)n);
+diff --git a/qtools/qcstring.h b/qtools/qcstring.h
+index d8ce074..4f15b18 100644
+--- a/qtools/qcstring.h
++++ b/qtools/qcstring.h
+@@ -288,6 +288,7 @@ public:
+ uint toUInt( bool *ok=0 ) const;
+ long toLong( bool *ok=0 ) const;
+ ulong toULong( bool *ok=0 ) const;
++ uint64 toUInt64( bool *ok=0 ) const;
+ QCString &setNum(short n);
+ QCString &setNum(ushort n);
+ QCString &setNum(int n);
+diff --git a/qtools/qstring.cpp b/qtools/qstring.cpp
+index f51c0d4..458fd53 100644
+--- a/qtools/qstring.cpp
++++ b/qtools/qstring.cpp
+@@ -13935,6 +13935,60 @@ bye:
+ }
+
+ /*!
++ Returns the string converted to an unsigned long
++ value.
++
++ If \a ok is non-null, \a *ok is set to TRUE if there are no
++ conceivable errors, and FALSE if the string is not a number at all,
++ or if it has trailing garbage.
++*/
++
++uint64 QString::toUInt64( bool *ok, int base ) const
++{
++ const QChar *p = unicode();
++ uint64 val=0;
++ int l = length();
++ const uint64 max_mult = 1844674407370955161ULL; // ULLONG_MAX/10, rounded down
++ bool is_ok = FALSE;
++ if ( !p )
++ goto bye;
++ while ( l && p->isSpace() ) // skip leading space
++ l--,p++;
++ if ( *p == '+' )
++ l--,p++;
++
++ // NOTE: toULong() code is similar
++ if ( !l || !ok_in_base(*p,base) )
++ goto bye;
++ while ( l && ok_in_base(*p,base) ) {
++ l--;
++ uint dv;
++ if ( p->isDigit() ) {
++ dv = p->digitValue();
++ } else {
++ if ( *p >= 'a' && *p <= 'z' )
++ dv = *p - 'a' + 10;
++ else
++ dv = *p - 'A' + 10;
++ }
++ if ( val > max_mult || (val == max_mult && dv > (ULLONG_MAX%base)) )
++ goto bye;
++ val = base*val + dv;
++ p++;
++ }
++
++ while ( l && p->isSpace() ) // skip trailing space
++ l--,p++;
++ if ( !l )
++ is_ok = TRUE;
++bye:
++ if ( ok )
++ *ok = is_ok;
++ return is_ok ? val : 0;
++}
++
++
++/*!
+ Returns the string converted to a short
value.
+
+ If \a ok is non-null, \a *ok is set to TRUE if there are no
+diff --git a/qtools/qstring.h b/qtools/qstring.h
+index a64fabf..df3873d 100644
+--- a/qtools/qstring.h
++++ b/qtools/qstring.h
+@@ -463,6 +463,7 @@ public:
+ uint toUInt( bool *ok=0, int base=10 ) const;
+ long toLong( bool *ok=0, int base=10 ) const;
+ ulong toULong( bool *ok=0, int base=10 ) const;
++ uint64 toUInt64( bool *ok=0, int base=10 ) const;
+ float toFloat( bool *ok=0 ) const;
+ double toDouble( bool *ok=0 ) const;
+
+diff --git a/src/util.cpp b/src/util.cpp
+index d367c40..db6a19c 100644
+--- a/src/util.cpp
++++ b/src/util.cpp
+@@ -18,6 +18,7 @@
+ #include
+ #include
+ #include
++#include
+
+ #include "md5.h"
+
+@@ -2472,6 +2473,35 @@ QCString fileToString(const char *name,bool filter,bool isSourceCode)
+ QCString dateToString(bool includeTime)
+ {
+ QDateTime current = QDateTime::currentDateTime();
++ QCString sourceDateEpoch = portable_getenv("SOURCE_DATE_EPOCH");
++ if (!sourceDateEpoch.isEmpty())
++ {
++ bool ok;
++ uint64 epoch = sourceDateEpoch.toUInt64(&ok);
++ if (!ok)
++ {
++ static bool warnedOnce=FALSE;
++ if (!warnedOnce)
++ {
++ warn_uncond("Environment variable SOURCE_DATE_EPOCH does not contain a valid number; value is '%s'\n",
++ sourceDateEpoch.data());
++ warnedOnce=TRUE;
++ }
++ }
++ else if (epoch>UINT_MAX)
++ {
++ static bool warnedOnce=FALSE;
++ if (!warnedOnce)
++ {
++ warn_uncond("Environment variable SOURCE_DATA_EPOCH must have a value smaller than or equal to %llu; actual value %llu\n",UINT_MAX,epoch);
++ warnedOnce=TRUE;
++ }
++ }
++ else // all ok, replace current time with epoch value
++ {
++ current.setTime_t((ulong)epoch); // TODO: add support for 64bit epoch value
++ }
++ }
+ return theTranslator->trDateTime(current.date().year(),
+ current.date().month(),
+ current.date().day(),
diff --git a/doxygen-1.8.10-angle-bracket.patch b/doxygen-1.8.10-angle-bracket.patch
new file mode 100644
index 0000000..ab748d0
--- /dev/null
+++ b/doxygen-1.8.10-angle-bracket.patch
@@ -0,0 +1,42 @@
+diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
+index 99d6fdd..d8913e1 100644
+--- a/src/htmldocvisitor.cpp
++++ b/src/htmldocvisitor.cpp
+@@ -1902,6 +1902,8 @@ void HtmlDocVisitor::filterQuotedCdataAttr(const char* str)
+ {
+ case '&': m_t << "&"; break;
+ case '"': m_t << """; break;
++ case '<': m_t << "<"; break;
++ case '>': m_t << ">"; break;
+ // For SGML compliance, and given the SGML declaration for HTML syntax,
+ // it's enough to replace these two, provided that the declaration
+ // for the HTML version we generate (and as supported by the browser)
+diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp
+index d8913e1..0ce4030 100644
+--- a/src/htmldocvisitor.cpp
++++ b/src/htmldocvisitor.cpp
+@@ -1904,24 +1904,6 @@ void HtmlDocVisitor::filterQuotedCdataAttr(const char* str)
+ case '"': m_t << """; break;
+ case '<': m_t << "<"; break;
+ case '>': m_t << ">"; break;
+- // For SGML compliance, and given the SGML declaration for HTML syntax,
+- // it's enough to replace these two, provided that the declaration
+- // for the HTML version we generate (and as supported by the browser)
+- // specifies that all the other symbols used in rawVal are
+- // within the right character class (i.e., they're not
+- // some multinational weird characters not in the BASESET).
+- // We assume that 1) the browser will support whatever is remaining
+- // in the formula and 2) the TeX formulae are generally governed
+- // by even stricter character restrictions so it should be enough.
+- //
+- // On some incompliant browsers, additional translation of
+- // '>' and '<' into ">" and "<", respectively, might be needed;
+- // but I'm unaware of particular modern (last 4 years) versions
+- // with such problems, so let's not do it for performance.
+- // Also, some brousers will (wrongly) not process the entity references
+- // inside the attribute value and show the &...; form instead,
+- // so we won't create entites unless necessary to minimize clutter there.
+- // --vassilii
+ default: m_t << c;
+ }
+ }
diff --git a/doxygen-1.8.10-bibtex.patch b/doxygen-1.8.10-bibtex.patch
new file mode 100644
index 0000000..7bfdc51
--- /dev/null
+++ b/doxygen-1.8.10-bibtex.patch
@@ -0,0 +1,46 @@
+diff --git a/src/commentscan.l b/src/commentscan.l
+index 3546277..406d966 100644
+--- a/src/commentscan.l
++++ b/src/commentscan.l
+@@ -920,7 +920,7 @@ FILEECHAR [a-z_A-Z0-9\x80-\xFF\-\+@]
+ FILE ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|("\""[^\n\"]*"\"")
+ ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
+ LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
+-CITESCHAR [a-z_A-Z\x80-\xFF]
++CITESCHAR [a-z_A-Z0-9\x80-\xFF]
+ CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/]*
+ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*
+ SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
+diff --git a/src/doctokenizer.l b/src/doctokenizer.l
+index 31d583c..efc058a 100644
+--- a/src/doctokenizer.l
++++ b/src/doctokenizer.l
+@@ -334,7 +334,7 @@ BLANK [ \t\r]
+ ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*
+ LABELID [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]*
+ PHPTYPE [\\:a-z_A-Z0-9\x80-\xFF\-]+
+-CITESCHAR [a-z_A-Z\x80-\xFF]
++CITESCHAR [a-z_A-Z0-9\x80-\xFF]
+ CITEECHAR [a-z_A-Z0-9\x80-\xFF\-\+:\/]*
+ CITEID {CITESCHAR}{CITEECHAR}*("."{CITESCHAR}{CITEECHAR}*)*
+ MAILADR ("mailto:")?[a-z_A-Z0-9.+-]+"@"[a-z_A-Z0-9-]+("."[a-z_A-Z0-9\-]+)+[a-z_A-Z0-9\-]+
+diff --git a/src/cite.cpp b/src/cite.cpp
+index 2ea6300..3125f35 100644
+--- a/src/cite.cpp
++++ b/src/cite.cpp
+@@ -226,13 +226,13 @@ void CiteDict::generatePage() const
+ else if (insideBib) doc+=line+"\n";
+ int i;
+ // determine text to use at the location of the @cite command
+- if (insideBib && (i=line.find("[");
+ int k=line.find("]");
+ if (j!=-1 && k!=-1)
+ {
+- QCString label = line.mid(i+17,j-i-17);
++ QCString label = line.mid(i+14,j-i-14);
+ QCString number = line.mid(j+2,k-j-1);
+ CiteInfo *ci = m_entries.find(label);
+ //printf("label='%s' number='%s' => %p\n",label.data(),number.data(),ci);
diff --git a/doxygen-1.8.10-fixspace.patch b/doxygen-1.8.10-fixspace.patch
new file mode 100644
index 0000000..f3259fb
--- /dev/null
+++ b/doxygen-1.8.10-fixspace.patch
@@ -0,0 +1,27 @@
+diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
+index a2dd473..dadbb4f 100644
+--- a/src/htmlgen.cpp
++++ b/src/htmlgen.cpp
+@@ -1952,11 +1952,6 @@ static void endQuickIndexItem(FTextStream &t,const char *l)
+ t << "\n";
+ }
+
+-static QCString fixSpaces(const QCString &s)
+-{
+- return substitute(s," "," ");
+-}
+-
+ static bool quickLinkVisible(LayoutNavEntry::Kind kind)
+ {
+ static bool showFiles = Config_getBool("SHOW_FILES");
+diff --git a/src/index.h b/src/index.h
+index 150d23f..ace3614 100644
+--- a/src/index.h
++++ b/src/index.h
+@@ -284,5 +284,6 @@ void initNamespaceMemberIndices();
+ void addClassMemberNameToIndex(MemberDef *md);
+ void addFileMemberNameToIndex(MemberDef *md);
+ void addNamespaceMemberNameToIndex(MemberDef *md);
++QCString fixSpaces(const QCString &s);
+
+ #endif
diff --git a/doxygen-1.8.10-latex.patch b/doxygen-1.8.10-latex.patch
new file mode 100644
index 0000000..35ab52b
--- /dev/null
+++ b/doxygen-1.8.10-latex.patch
@@ -0,0 +1,32 @@
+diff --git a/src/formula.cpp b/src/formula.cpp
+index ad37782..182ddaa 100644
+--- a/src/formula.cpp
++++ b/src/formula.cpp
+@@ -132,6 +132,7 @@ void FormulaList::generateBitmaps(const char *path)
+ {
+ err("Problems running dvips. Check your installation!\n");
+ portable_sysTimerStop();
++ QDir::setCurrent(oldDir);
+ return;
+ }
+ portable_sysTimerStop();
+@@ -192,6 +193,7 @@ void FormulaList::generateBitmaps(const char *path)
+ {
+ err("Problem running ghostscript %s %s. Check your installation!\n",portable_ghostScriptCommand(),gsArgs);
+ portable_sysTimerStop();
++ QDir::setCurrent(oldDir);
+ return;
+ }
+ portable_sysTimerStop();
+diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp
+index 7baaa3c..e10b638 100644
+--- a/src/rtfgen.cpp
++++ b/src/rtfgen.cpp
+@@ -2590,6 +2590,7 @@ bool RTFGenerator::preProcessFileInplace(const char *path,const char *name)
+ if (!outf.open(IO_WriteOnly))
+ {
+ err("Failed to open %s for writing!\n",combinedName.data());
++ QDir::setCurrent(oldDir);
+ return FALSE;
+ }
+ FTextStream outt(&outf);
diff --git a/doxygen-1.8.10-timestamp-latex.patch b/doxygen-1.8.10-timestamp-latex.patch
new file mode 100644
index 0000000..49bfeb0
--- /dev/null
+++ b/doxygen-1.8.10-timestamp-latex.patch
@@ -0,0 +1,64 @@
+diff --git a/src/config.xml b/src/config.xml
+index acbee8e..faad651 100644
+--- a/src/config.xml
++++ b/src/config.xml
+@@ -2647,6 +2647,16 @@ or
+ ]]>
+
+
++
+
+
+