diff options
-rw-r--r-- | adapter/format/ansi2html.nim | 32 | ||||
-rwxr-xr-x | bonus/git.cgi | 13 | ||||
-rw-r--r-- | res/mailcap | 2 | ||||
-rw-r--r-- | src/config/mailcap.nim | 1 | ||||
-rw-r--r-- | src/utils/twtstr.nim | 38 |
5 files changed, 58 insertions, 28 deletions
diff --git a/adapter/format/ansi2html.nim b/adapter/format/ansi2html.nim index 4266a3ba..9abc6925 100644 --- a/adapter/format/ansi2html.nim +++ b/adapter/format/ansi2html.nim @@ -356,11 +356,39 @@ proc processData(state: var State, buf: openArray[char]) = of '\0': state.puts("\uFFFD") # HTML eats NUL, so replace it here else: state.putc(c) +proc usage() = + stderr.write("Usage: ansihtml [-s] [-t title]\n") + quit(1) + proc main() = var state = State() - let standalone = paramCount() >= 1 and paramStr(1) == "-s" + # parse args + let H = paramCount() + var i = 1 + var standalone = false + var title = "" + while i <= H: + let s = paramStr(i) + if s == "": + inc i + if s[0] != '-': + usage() + for j in 1 ..< s.len: + case s[j] + of 's': + standalone = true + of 't': + inc i + if i > H: usage() + title = paramStr(i).percentDecode() + else: discard + inc i + if standalone: + state.puts("<!DOCTYPE html>\n") + if title != "": + state.puts("<title>" & title.htmlEscape() & "</title>\n") if standalone: - state.puts("<!DOCTYPE html>\n<body>") + state.puts("<body>\n") state.puts("<pre style='margin: 0'>\n") let ofl = fcntl(STDIN_FILENO, F_GETFL, 0) doAssert ofl != -1 diff --git a/bonus/git.cgi b/bonus/git.cgi index 1f93862a..387f3a64 100755 --- a/bonus/git.cgi +++ b/bonus/git.cgi @@ -27,12 +27,7 @@ for (const p of std.getenv("QUERY_STRING").split('&')) { } function startGitCmd(config, params) { - const titleParams = params.join(' ').replace(/[&<>]/g, - x => ({'&': '&', '<': '<', '>': '>'}[x])); - std.out.puts(`Content-Type: text/html - -<!DOCTYPE html> -<title>git ${titleParams}</title>`); + std.out.puts("Content-Type: text/html\n\n"); std.out.flush(); const [read_fd, write_fd] = os.pipe(); const [read_fd2, write_fd2] = os.pipe(); @@ -43,7 +38,8 @@ function startGitCmd(config, params) { os.close(write_fd); const libexecDir = std.getenv("CHA_LIBEXEC_DIR") ?? '/usr/local/libexec/chawan'; - os.exec([libexecDir + "/ansi2html"], { + const title = encodeURIComponent('git ' + params.join(' ')); + os.exec([libexecDir + "/ansi2html", "-st", title], { stdin: read_fd, stdout: write_fd2, block: false @@ -78,7 +74,8 @@ if (params[0] == "log") { } f.close(); } else { - std.out.puts("Content-Type: text/x-ansi\n\n"); + const title = encodeURIComponent('git ' + params.join(' ')); + std.out.puts(`Content-Type: text/x-ansi;title=${title}\n\n`); std.out.flush(); const pid = os.exec(["git", ...config, ...params], { block: false, diff --git a/res/mailcap b/res/mailcap index 4d6619d7..56c6582e 100644 --- a/res/mailcap +++ b/res/mailcap @@ -3,4 +3,4 @@ text/gopher; "$CHA_LIBEXEC_DIR"/gopher2html -u "$MAILCAP_URL"; x-htmloutput text/gemini; "$CHA_LIBEXEC_DIR"/gmi2html; x-htmloutput text/markdown; "$CHA_LIBEXEC_DIR"/md2html; x-htmloutput -text/x-ansi; "$CHA_LIBEXEC_DIR"/ansi2html -s; x-htmloutput +text/x-ansi; "$CHA_LIBEXEC_DIR"/ansi2html -st '%{title}'; x-htmloutput diff --git a/src/config/mailcap.nim b/src/config/mailcap.nim index b108ca20..41575ca8 100644 --- a/src/config/mailcap.nim +++ b/src/config/mailcap.nim @@ -308,6 +308,7 @@ proc unquoteCommand*(ecmd, contentType, outpath: string; url: URL; let s = contentType.getContentTypeAttr(attrname) cmd &= quoteFile(s, qs) attrname = "" + state = STATE_NORMAL elif c == '\\': state = STATE_ATTR_QUOTED else: diff --git a/src/utils/twtstr.nim b/src/utils/twtstr.nim index 6f40ae7b..f0a64546 100644 --- a/src/utils/twtstr.nim +++ b/src/utils/twtstr.nim @@ -678,22 +678,26 @@ func strictParseEnum*[T: enum](s: string): Opt[T] = return err() proc getContentTypeAttr*(contentType, attrname: string): string = - let kvs = contentType.after(';') - var i = kvs.find(attrname) + var i = contentType.find(';') + if i == -1: + return "" + i = contentType.find(attrname, i) + if i == -1: + return "" + i = contentType.skipBlanks(i + attrname.len) + if i >= contentType.len or contentType[i] != '=': + return "" + i = contentType.skipBlanks(i + 1) + var q = false var s = "" - if i != -1 and kvs.len > i + attrname.len and - kvs[i + attrname.len] == '=': - i += attrname.len + 1 - while i < kvs.len and kvs[i] in AsciiWhitespace: - inc i - var q = false - for j, c in kvs.toOpenArray(i, kvs.high): - if q: - s &= c - elif c == '\\': - q = true - elif c == ';' or c in AsciiWhitespace: - break - else: - s &= c + for c in contentType.toOpenArray(i, contentType.high): + if q: + s &= c + q = false + elif c == '\\': + q = true + elif c in AsciiWhitespace + {';'}: + break + else: + s &= c return s |