home
readme
diff
tree
note
docs
0commit fa2536aba2f6d82ca86aed91e50c31598145cde1
1Author: lakefox <mason@lakefox.net>
2Date: Thu Dec 25 11:39:08 2025 -0700
3
4 Added QA
5
6diff --git a/cgi-bin/qa.awk b/cgi-bin/qa.awk
7new file mode 100755
8index 0000000..796f63c
9--- /dev/null
10+++ b/cgi-bin/qa.awk
11@@ -0,0 +1,161 @@
12+#!/usr/bin/awk -f
13+
14+BEGIN {
15+ split(ENVIRON["QUERY_STRING"], pairs, "&")
16+ for (i in pairs) {
17+ split(pairs[i], kv, "=")
18+
19+ if (kv[1] == "action") {
20+ # reply, view, new, grep
21+ action = kv[2]
22+ } else if (kv[1] == "type") {
23+ type = kv[2]
24+ } else if (kv[1] == "site") {
25+ site = kv[2]
26+ } else if (kv[1] == "name") {
27+ name = kv[2]
28+ gsub(/\+/, " ", name)
29+ gsub(/%20/, " ", name)
30+ } else if (kv[1] == "body") {
31+ body = kv[2]
32+ gsub(/\+/, " ", body)
33+ }
34+ }
35+
36+ if (action == "") action = "view"
37+ if (name == "") name = "all"
38+
39+ print "Content-Type: text/html\r\n"
40+ print "<!DOCTYPE html>"
41+ print "<html>"
42+ print "<head>"
43+
44+ print "<title>QA: " name "</title>"
45+ print "<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'>"
46+ print "<meta name='viewport' content='width=device-width, initial-scale=1'>"
47+ print "</head>"
48+ print "<body>"
49+
50+ if (site == "") {
51+ cmd = "ls /var/qa"
52+
53+ print "<h1>QA: Sites</h1>"
54+ print "<ul>"
55+ while (cmd | getline sites) {
56+ print "<li><a href='/cgi-bin/qa.awk?site=" sites "&action=view&name=all'>" sites "/</a></li>"
57+ }
58+ close(cmd)
59+ print "</ul>"
60+ } else if (action == "view") {
61+ if (name == "all") {
62+ cmd = "ls /var/qa/" site
63+
64+ print "<h1>QA: " site "</h1>"
65+ print "<p>Select a question to view.</p>"
66+ print "<a href='/cgi-bin/qa.awk?site=" site "&action=new'>New</a>"
67+
68+ print "<ul>"
69+ while (cmd | getline file) {
70+ split(file, b, ".")
71+ if (b[2] != "comment") {
72+ print "<li><a href='/cgi-bin/qa.awk?action=view&site=" site "&name=" b[1] "'>/" b[1] "</a></li>"
73+ }
74+ }
75+ close(cmd)
76+ print "</ul>"
77+ } else {
78+ print "<h1>" name "</h1>"
79+ print "<p>"
80+
81+ file = "/var/qa/" site "/" name ".txt"
82+ while (getline line < file) {
83+ print escape_html(line)
84+ }
85+
86+ cmd = "ls -l \"" file "\""
87+ cmd | getline date
88+ close(cmd)
89+ split(date, d, " ")
90+ print "<br/><b>" d[6] " " d[7] " " d[8] "</b>"
91+
92+ print "</p>"
93+ print "<a href='/cgi-bin/qa.awk?site=" site "&action=reply&name=" name "'>Reply</a>"
94+ print "<hr/>"
95+ print "<br/>"
96+
97+ cmd = "find /var/qa/" site " -name \"" name ".comment*\""
98+
99+ n = 0
100+ while (cmd | getline comment) {
101+ n += 1
102+ }
103+ close(cmd)
104+
105+ if (n > 0) {
106+ print "<h4>Replies</h4>"
107+
108+ for (i = 0; i < n; i++) {
109+ cmd = "cat \"/var/qa/" site "/" name ".comment." i ".txt\""
110+ print "<p>"
111+ while (cmd | getline line) {
112+ print escape_html(line)
113+ }
114+ close(cmd)
115+ cmd = "ls -l \"/var/qa/" site "/" name ".comment." i ".txt\""
116+ cmd | getline date
117+ close(cmd)
118+ split(date, d, " ")
119+ print "<br/><b>" d[6] " " d[7] " " d[8] "</b>"
120+ print "</p>"
121+ }
122+ }
123+ }
124+ } else if (action == "new") {
125+ print "<h1>" site ":new</h1>"
126+
127+ print "<form action='/cgi-bin/qa.awk'>"
128+ print "<input name='site' type='text' value='" site "' hidden>"
129+ print "<input name='action' type='text' value='save_post' hidden>"
130+ print "<label for='name'>Title</label><br/>"
131+ print "<input type='text' name='name' id='name' placeholder='Your Question'/><br/><br/>"
132+ print "<textarea id='body' name='body'></textarea><br/><br/>"
133+ print "<input type='submit'>"
134+ print "</form>"
135+ } else if (action == "save_post") {
136+ file = "/var/qa/" site "/" name ".txt"
137+ print body > file
138+ print "<script>window.location = '/cgi-bin/qa.awk?site=" site "&action=view&name=" name "';</script>"
139+ } else if (action == "reply") {
140+ print "<h1> Reply to: " name "</h1>"
141+
142+ print "<form action='/cgi-bin/qa.awk'>"
143+ print "<input name='site' type='text' value='" site "' hidden>"
144+ print "<input name='action' type='text' value='save_reply' hidden>"
145+ print "<input name='name' type='text' value='" name "' hidden>"
146+ print "<textarea id='body' name='body'></textarea><br/><br/>"
147+ print "<input type='submit'>"
148+ print "</form>"
149+ } else if (action == "save_reply") {
150+ cmd = "find /var/qa/" site " -name \"" name ".comment*\""
151+
152+ count = 0
153+ while (cmd | getline comment) {
154+ count += 1;
155+ }
156+ close(cmd)
157+
158+ print body > "/var/qa/" site "/" name ".comment." count ".txt"
159+ print "<script>window.location = '/cgi-bin/qa.awk?site=" site "&action=view&name=" name "';</script>"
160+ }
161+ print "</body>"
162+ print "</html>"
163+}
164+
165+function escape_html(str) {
166+ gsub(/&/, "\\&", str)
167+ gsub(/</, "\\<", str)
168+ gsub(/>/, "\\>", str)
169+ gsub(/"/, "\\"", str)
170+ gsub(/'/, "\\'", str)
171+ return str
172+}
173diff --git a/index.html b/index.html
174index f16df0c..25ae8ff 100644
175--- a/index.html
176+++ b/index.html
177@@ -1,5 +1,5 @@
178 <!DOCTYPE html>
179-<html>
180+<html lang="en-US">
181 <head>
182 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
183 <title>git.ws</title>
184@@ -17,7 +17,7 @@
185 </head>
186 <body style="max-width: 900px;">
187 <h1>git.ws</h1>
188- <a href="/cgi-bin/mailto.awk">Mailing Lists</a> <a href="/cgi-bin/git.awk">Git</a>
189+ <a href="/cgi-bin/mailto.awk">Mailing Lists</a> <a href="/cgi-bin/git.awk">Git</a> <a href="/cgi-bin/qa.awk">QA</a>
190 <p>
191 git.ws is a project sharing website.
192 </p>
193@@ -45,6 +45,12 @@
194 <td><a target="_blank" href="https://web.libera.chat/gamja/?autojoin=#gitws">#gitws</a></td>
195 <td><a href="http://git.ws/repo/gitws.git">http://git.ws/repo/gitws.git</a></td>
196 </tr>
197+ <tr>
198+ <td><a href="http://spectre.git.ws/">spectre/</a></td>
199+ <td>Fast router OS</td>
200+ <td><a target="_blank" href="https://web.libera.chat/gamja/?autojoin=#spectre">#spectre</a></td>
201+ <td><a href="http://git.ws/repo/gitws.git">http://git.ws/repo/spectre.git</a></td>
202+ </tr>
203 </tbody>
204 </table>
205 <hr>