diff --git a/public_html/linksearch.fcgi b/public_html/linksearch.fcgi index b193788..d65aee0 100755 --- a/public_html/linksearch.fcgi +++ b/public_html/linksearch.fcgi @@ -1,210 +1,210 @@ #!/data/project/shared/tcl/bin/tclsh8.7 # Special:LinkSearch with namespace filtering, internationalized version # Copyright 2010, 2011, 2012, 2013, 2014, 2016, 2017, 2019 Giftpflanze # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or (at your # option) any later version. package require TclCurl package require control namespace import control::do package require mysqltcl package require Fcgi package require ncgi package require htmlgen namespace import htmlgen::* package require json package require uri::urn package require http proc get-handle {wiki} { return $handle } proc post {handle args} { global headers foreach {/ name value} $args { lappend pairs "[curl::escape $name]=[curl::escape $value]" } do { array unset headers $handle configure -postfields [set string [join $pairs &]] -bodyvar body $handle perform } until { [catch {after [expr {[set replag $headers(Retry-After)]*1000}]}] } return [encoding convertfrom [encoding convertfrom [encoding convertto $body]]] } proc get-db {server {db {}}} { mysqlconnect -reconnect 1 -host $server.web.db.svc.eqiad.wmflabs -db [expr {[llength $db]?$db:"${server}_p"}] } proc l10n {msg args} { global api apiquery lang dict get [lindex [dict get [json::json2dict [post $api {*}$apiquery allmessages / amlang $lang / ammessages $msg / amenableparser 1 / amargs [join $args |]]] query allmessages] 0] * } proc paging_header {query limit offset} { global env mc p ! { set plink [l10n prevn $limit] set nlink [l10n nextn $limit] foreach num {20 50 100 250 500} { lappend list [a href=$env(PATH_INFO)?limit=$num&offset=$offset&$query . $num] } put [string map [list {$3} [join $list $mc(pipe-separator)]] [l10n viewprevnext [expr {$offset?[a href=$env(PATH_INFO)?limit=$limit&offset=[expr {$offset-$limit}]&$query\ . $plink]:$plink}] [a href=$env(PATH_INFO)?limit=$limit&offset=[expr {$offset+$limit}]&$query . $nlink]]] } } while {[FCGI_Accept] >= 0} { if [catch { ncgi::header {text/html; charset=utf-8} ncgi::reset ncgi::input ncgi::setDefaultValue lang en ncgi::setDefaultValue wiki en.wikipedia ncgi::setDefaultValue associated 0 ncgi::setDefaultValue offset 0 ncgi::setDefaultValue limit 100 ncgi::setDefaultValue submit 0 ncgi::importAll target namespace lang wiki associated offset limit submit set offset [expr {max(0,$offset)}] set namespaces_list {} set query [http::formatQuery target $target namespace $namespace associated $associated submit $submit lang $lang wiki $wiki] [set api [curl::init]] configure \ -useragent "Linksearch/0.0 ($env(HTTP_X_FORWARDED_PROTO)://$env(SERVER_NAME)$env(PATH_INFO); $tcl_platform(user)@$env(SERVER_NAME))" \ -encoding all \ -url https://$wiki.org/w/api.php \ -sslverifypeer 0 \ -sslsessionidcache 0 \ -headervar headers foreach dict [dict get [json::json2dict [post $api {*}[set apiquery {/ format json / maxlag 5 / utf8 true / action query / meta}] allmessages / amlang $lang / ammessages\ [join {linksearch linksearch-pat linksearch-ns namespace_association namespacesall blanknamespace linksearch-ok linksearch-line specialpage-empty pipe-separator\ - allmessages-language translate-translations-project botpasswords-label-update} |]]] query allmessages] { + allmessages-language translate-translations-project botpasswords-label-update upload-source} |]]] query allmessages] { dict with dict { set mc($name) ${*} } } dict set namespaces_list {} $mc(namespacesall) foreach {id dict} [dict get [json::json2dict [post $api {*}$apiquery siteinfo / siprop namespaces]] query namespaces] { if {$id < 0} continue dict with dict { dict set namespaces_list $id [expr {[string length ${*}]?${*}:$mc(blanknamespace)}] dict set namespaces_lookup $id ${*} } } html [expr {$lang in {ar arc arz azb ckb dv fa glk ha he lad mzn pnb ps sd ug ur yi}?{dir=rtl}:{}}] ! { head ! { title - [set title $mc(linksearch)] link rel=stylesheet href=linksearch.css media=screen - } body ! { h1 + $title div ! { switch $lang de { p - Dieses Tool benutzt im Suchmuster MySQL-Platzhalter, d.h.: ul ! { li - [code . _]: entspricht genau einem Zeichen li - [code . %]: entspricht null, einem oder mehreren Zeichen } p - Im Gegensatz zu Spezial:Weblinksuche muss die vollständige URL angegeben werden, das Protokoll [code http://] wird nicht ergänzt. p - Bitte beachte, dass manche URLs protokollrelativ sind, sie beginnen mit [code //]. } en { p - This tool uses MySQL LIKE wildcards in the search pattern, i.e.: ul ! { li - [code . _]: exactly one character li - [code . %]: zero, one, or multiple characters } p - Unlike Special:Linksearch, the URL has to be complete, [code http://] is not added to it. p - Please note that some URLs are protocol relative and start with [code //]. } default { div dir=ltr ! { p - I'm terribly sorry, there's no translation of this help text for this language. If you know one, please contact me on\ [a href=https://de.wikipedia.org/wiki/Benutzerin_Diskussion:Giftpflanze my talk page]. p - This tool uses MySQL LIKE wildcards in the search pattern, i.e.: ul ! { li - [code . _]: exactly one character li - [code . %]: zero, one, or multiple characters } p - Unlike Special:Linksearch, the URL has to be complete, [code http://] is not added to it. p - Please note that some URLs are protocol relative and start with [code //]. } } form method=get action=$env(PATH_INFO) ! { fieldset ! { label for=lang - $mc(allmessages-language) put { } input name=lang size=7 value=$lang dir=ltr - put { } label for=wiki - $mc(translate-translations-project) put { } input name=wiki size=25 value=$wiki dir=ltr - put { } button name=submit value=0 - $mc(botpasswords-label-update) } fieldset ! { label for=target - $mc(linksearch-pat) put { } input name=target size=50 value=$target dir=ltr - put { } label for=namespace - $mc(linksearch-ns) put { } select name=namespace ! { foreach {value ns} $namespaces_list { option value=$value {*}[expr {$value==$namespace?{selected=}:{}}] - $ns } } put { } input name=associated type=checkbox value=1 {*}[expr {$associated?{checked=}:{}}] - put { } label for=associated - $mc(namespace_association) put { } button name=submit value=1 - $mc(linksearch-ok) } } if {[string length $target] && $submit} { set url https://$wiki.org set db [get-db [mysqlsel [set meta [get-db meta]] "select dbname from wiki where url = '[mysqlescape $url]'" -flatlist]] mysqlclose $meta if [catch { set resultnum [mysqlsel $db "select distinct el_to, page_namespace, page_title from externallinks, page where el_from = page_id and\ el_to like '[mysqlescape $target]' [expr {[string length $namespace]?($associated?"and page_namespace in ([expr {[mysqlescape\ $namespace]/2*2}],[expr {[mysqlescape $namespace]/2*2+1}])":"and page_namespace = [mysqlescape $namespace]"):{}}] limit [mysqlescape $limit]\ offset [mysqlescape $offset]"] }] { after 300000 exit } div ! { if $resultnum { p - [l10n showingresultsinrange $resultnum [expr {$offset+1}] [expr {$offset+$resultnum}]] paging_header $query $limit $offset ol start=[expr {$offset+1}] ! { mysqlmap $db {to ns title} { li - [l10n linksearch-line [a href=$to $to] [a href=$url/wiki/[uri::urn::quote [set title [set ns [dict get\ $namespaces_lookup $ns]][expr {[llength $ns]?{:}:{}}]$title]] . [string map {_ { }} $title]]] } } paging_header $query $limit $offset } else { p - $mc(specialpage-empty) } } mysqlclose $db } $api cleanup p ! { - #a href=https://gerrit.wikimedia.org/r/plugins/gitiles/labs/tools/giftbot/+/master/public_html/weblinksuche.fcgi - Source code + a href=https://phabricator.wikimedia.org/source/tool-linksearch/browse/master/public_html/linksearch.fcgi - $mc(upload-source) } } }} }] { pre - $errorInfo } }