kisscommunity

kisscommunity.bvnf.space site sources
git clone git://bvnf.space/home/kiss/kisscommunity.git
Log | Files | Refs | Submodules | README | LICENSE

search (3697B)


      1
      2
      3
      4
      5
      6
      7
      8
      9
     10
     11
     12
     13
     14
     15
     16
     17
     18
     19
     20
     21
     22
     23
     24
     25
     26
     27
     28
     29
     30
     31
     32
     33
     34
     35
     36
     37
     38
     39
     40
     41
     42
     43
     44
     45
     46
     47
     48
     49
     50
     51
     52
     53
     54
     55
     56
     57
     58
     59
     60
     61
     62
     63
     64
     65
     66
     67
     68
     69
     70
     71
     72
     73
     74
     75
     76
     77
     78
     79
     80
     81
     82
     83
     84
     85
     86
     87
     88
     89
     90
     91
     92
     93
     94
     95
     96
     97
     98
     99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
#!/usr/local/bin/tclsh8.6

proc htmlize str {
	string map {< &lt; > &gt; \x22 &quot; \x26 &amp;} $str
	string map {< &lt; > &gt; \x22 &quot; \x26 &amp;} $str
}

proc url-decode str {
	# adapted from https://wiki.tcl-lang.org/page/url%2Dencoding
    set str [string map [list + { }] $str]
	
    set pos 0
	while { -1 != [set pos [string first "%" $str $pos]]} {
		set hexNumber "[string range $str $pos+1 $pos+2]"
		set str [string range $str 0 $pos-1][binary decode hex $hexNumber][string range $str $pos+3 end]
		incr pos
	}
	return [encoding convertfrom utf-8 $str]
}

proc query {db} {
	set q $::searchterm
	set e {select list(path, snippet(files, 0, '<b>', '</b>', '', 40), snippet(files, 1, '<b>', '</b>', '&nbsp;…&nbsp;', 40)) from files where files MATCH :q ORDER BY RANK LIMIT 200;}
	if {[catch { set ll [$db eval $e] }]} {
		set x ""
		foreach word [split $q " "] {
			append x " \"[string map [list "\"" "\"\""] $word]\""
		}
		set q [string trim $x]
		set ::searchterm $q
		set ll [$db eval $e]
	}
	return $ll
}

proc format_results {r t} {
	set x ""
	append x "<p>[llength $r] results in $t</p>"
	if {[llength $r] == 0} {
		append x "<p>No results.</p>"
		return $x
	}
	append x {<table border=0>}
	foreach res $r {
		lassign $res path title snippet
		append x "<tr><td><a href=\"$path\">$title</a><br /><p>$snippet<td></tr>\n"
	}
	append x {</table>}
	return $x
}

proc main {} {
	set t0 [clock milliseconds]
	set doc {}

	if {[info exists ::env(QUERY_STRING)]} {
		set qs [split $::env(QUERY_STRING) &]
		foreach q $qs {
			lassign [split $q =] key val
			if {$key == "query"} {
				set ::searchterm $val
				break
			}
		}
	}

	if {![info exists ::searchterm] || $::searchterm eq {}} {
		# no query, print plain searchbox
		set ::status "200 OK"
		set ::title Search
		return {<h1>Search</h1><p><form><input type="text" name="query" /><input type="submit" value="Search" /></form></p>}
	}

	set ::searchterm [url-decode $::searchterm]

	# do the search
	package require sqlite3
	sqlite3 db -create false "../db.sqlite"
	db function list ::list
	db timeout 2000 ;# does this do anything?

	set results [query db]
	db close

	set htmlsearchterm [htmlize $::searchterm]

	set t1 [clock milliseconds]
	set t "[expr {($t1-$t0)/1000.}]s"

	set ::status "200 OK"
	set ::title "$htmlsearchterm - search results"
	set doc "<p>Search results for: <b>$htmlsearchterm</b></p><p><form><input type=\"text\" name=\"query\" value=\"$htmlsearchterm\" /><input type=\"submit\" value=\"Search\" /></form></p>"

	append doc [format_results $results $t]
	return $doc
}

if {0==[catch main res]} {
	set document "<!DOCTYPE html><html><head><meta charset=\"utf-8\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>$::title</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\"/><link rel=\"icon\" href=\"data:image/gif;base64,R0lGODlhEAAQAPEDAAAAAP8AAP///wAAACH5BAX//wMALAAAAAAQABAAAAImnB+ni8kf4mNRzmbvqE5zPQDiqI3kBQhmqZ5TuqKtyMavCZT4UgAAOw==\"/></head>"
	append document {<body><div id="menu"><a href="/"><b>KISS Community Wiki</b></a>
        <span class="right">
                <a href="/cgi-bin/search">Search</a>
                <a href="https://codeberg.org/kiss-community">Codeberg</a>
                <a href="https://kisslinux.github.io">Official site</a>
        </span></div><div id="content"><div id="main">
	}
	append document $res {</div></div></body></html>}
} else {
	set ::status 500
	set ::title Error
	set document "<!DOCTYPE html><pre>Error: $res</pre>"
}

puts "Status: $::status\r"
puts "Content-Type: text/html\r"
puts "Content-Length: [string length $document]\r"
puts "\r"
puts -nonewline $document
flush stdout
close stdout
exit