Index: trunk/extensions/LinkSearch/LinkSearch.i18n.php |
— | — | @@ -10,7 +10,10 @@ |
11 | 11 | |
12 | 12 | $wgLinkSearchMessages['en'] = array( |
13 | 13 | 'linksearch' => 'Search web links', |
14 | | - 'linksearch-text' => 'Wildcards such as "*.wikipedia.org" may be used.', |
| 14 | + 'linksearch-pat' => 'Search pattern:', |
| 15 | + 'linksearch-ns' => 'Namespace:', |
| 16 | + 'linksearch-ok' => 'Search', |
| 17 | + 'linksearch-text' => 'Wildcards such as "*.wikipedia.org" may be used.<br />Supported protocols: <tt>$1</tt>', |
15 | 18 | 'linksearch-line' => '$1 linked from $2', |
16 | 19 | 'linksearch-error' => 'Wildcards may appear only at the start of the hostname.', |
17 | 20 | ); |
— | — | @@ -22,7 +25,10 @@ |
23 | 26 | ); |
24 | 27 | $wgLinkSearchMessages['de'] = array( |
25 | 28 | 'linksearch' => 'Weblink-Suche', |
26 | | - 'linksearch-text' => 'Diese Spezialseite ermöglicht die Suche nach Seiten, in denen bestimmte Weblinks enthalten sind. Dabei können Wildcards wie beispielsweise <tt>*.example.com</tt> benutzt werden. ', |
| 29 | + 'linksearch-pat' => 'Suchmuster:', |
| 30 | + 'linksearch-ns' => 'Namensraum:', |
| 31 | + 'linksearch-ok' => 'Suche', |
| 32 | + 'linksearch-text' => 'Diese Spezialseite ermöglicht die Suche nach Seiten, in denen bestimmte Weblinks enthalten sind. Dabei können Wildcards wie beispielsweise <tt>*.example.com</tt> benutzt werden.<br />Unterstützte Protokolle: <tt>$1</tt>', |
27 | 33 | 'linksearch-line' => '$1 ist verlinkt von $2', |
28 | 34 | 'linksearch-error' => 'Wildcards können nur am Anfang der URL verwendet werden.', |
29 | 35 | ); |
Index: trunk/extensions/LinkSearch/LinkSearch.php |
— | — | @@ -27,49 +27,51 @@ |
28 | 28 | $GLOBALS['wgSpecialPages']['Linksearch'] = array( /*class*/ 'SpecialPage', |
29 | 29 | /*name*/ 'Linksearch', /* permission */'', /*listed*/ true, |
30 | 30 | /*function*/ false, /*file*/ false ); |
31 | | - |
| 31 | + |
32 | 32 | class LinkSearchPage extends QueryPage { |
33 | | - function __construct( $query ) { |
| 33 | + function __construct( $query , $ns , $prot ) { |
34 | 34 | $this->mQuery = $query; |
| 35 | + $this->mNs = $ns; |
| 36 | + $this->mProt = $prot; |
35 | 37 | } |
36 | | - |
| 38 | + |
37 | 39 | function getName() { |
38 | 40 | return 'Linksearch'; |
39 | 41 | } |
40 | | - |
| 42 | + |
41 | 43 | /** |
42 | 44 | * Disable RSS/Atom feeds |
43 | 45 | */ |
44 | 46 | function isSyndicated() { |
45 | 47 | return false; |
46 | 48 | } |
47 | | - |
| 49 | + |
48 | 50 | /** |
49 | 51 | * Return an appropriately formatted LIKE query |
50 | | - * @fixme Fix up LinkFilter to work with non-http links as well |
51 | 52 | */ |
52 | | - static function mungeQuery( $query ) { |
53 | | - if( substr( $query, 0, 7 ) == 'http://' ) { |
54 | | - $query = substr( $query, 7 ); |
55 | | - } |
56 | | - return LinkFilter::makeLike( $query ); |
| 53 | + static function mungeQuery( $query , $prot ) { |
| 54 | + return LinkFilter::makeLike( $query , $prot ); |
57 | 55 | } |
58 | | - |
| 56 | + |
59 | 57 | function linkParameters() { |
60 | | - return array( 'target' => $this->mQuery ); |
| 58 | + return array( 'target' => $this->mQuery, 'namespace' => $this->mNs ); |
61 | 59 | } |
62 | | - |
| 60 | + |
63 | 61 | function getSQL() { |
| 62 | + global $wgMiserMode; |
64 | 63 | $dbr = wfGetDB( DB_SLAVE ); |
65 | | - |
66 | 64 | $page = $dbr->tableName( 'page' ); |
67 | 65 | $externallinks = $dbr->tableName( 'externallinks' ); |
68 | | - |
| 66 | + |
69 | 67 | /* strip everything past first wildcard, so that index-based-only lookup would be done */ |
70 | | - $munged = self::mungeQuery( $this->mQuery ); |
| 68 | + $munged = self::mungeQuery( $this->mQuery, $this->mProt ); |
71 | 69 | $stripped = substr($munged,0,strpos($munged,'%')+1); |
72 | 70 | $encSearch = $dbr->addQuotes( $stripped ); |
73 | | - |
| 71 | + |
| 72 | + $encSQL = ''; |
| 73 | + if ( isset ($this->mNs) && !$wgMiserMode ) $encSQL = 'AND page_namespace=' . $this->mNs; |
| 74 | + |
| 75 | + |
74 | 76 | return |
75 | 77 | "SELECT |
76 | 78 | page_namespace AS namespace, |
— | — | @@ -81,25 +83,25 @@ |
82 | 84 | $externallinks FORCE INDEX (el_index) |
83 | 85 | WHERE |
84 | 86 | page_id=el_from |
85 | | - AND el_index LIKE $encSearch"; |
| 87 | + AND el_index LIKE $encSearch |
| 88 | + $encSQL"; |
86 | 89 | } |
87 | | - |
| 90 | + |
88 | 91 | function formatResult( $skin, $result ) { |
89 | 92 | $title = Title::makeTitle( $result->namespace, $result->title ); |
90 | 93 | $url = $result->url; |
91 | | - |
92 | 94 | $pageLink = $skin->makeKnownLinkObj( $title ); |
93 | 95 | $urlLink = $skin->makeExternalLink( $url, $url ); |
94 | | - |
| 96 | + |
95 | 97 | return wfMsgHtml( 'linksearch-line', $urlLink, $pageLink ); |
96 | 98 | } |
97 | | - |
| 99 | + |
98 | 100 | /** |
99 | 101 | * Override to check query validity. |
100 | 102 | */ |
101 | 103 | function doQuery( $offset, $limit ) { |
102 | 104 | global $wgOut; |
103 | | - $this->mMungedQuery = LinkSearchPage::mungeQuery( $this->mQuery ); |
| 105 | + $this->mMungedQuery = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt ); |
104 | 106 | if( $this->mMungedQuery === false ) { |
105 | 107 | $wgOut->addWikiText( wfMsg( 'linksearch-error' ) ); |
106 | 108 | } else { |
— | — | @@ -108,7 +110,7 @@ |
109 | 111 | parent::doQuery( $offset, $limit ); |
110 | 112 | } |
111 | 113 | } |
112 | | - |
| 114 | + |
113 | 115 | /** |
114 | 116 | * Override to squash the ORDER BY. |
115 | 117 | * We do a truncated index search, so the optimizer won't trust |
— | — | @@ -118,27 +120,61 @@ |
119 | 121 | function getOrder() { |
120 | 122 | return ''; |
121 | 123 | } |
122 | | - |
123 | 124 | } |
124 | | - |
125 | | - function wfSpecialLinksearch( $par=null ) { |
| 125 | + |
| 126 | + function wfSpecialLinksearch( $par=null, $ns=null ) { |
126 | 127 | list( $limit, $offset ) = wfCheckLimits(); |
| 128 | + global $wgOut, $wgRequest, $wgUrlProtocols, $wgMiserMode; |
127 | 129 | $target = $GLOBALS['wgRequest']->getVal( 'target', $par ); |
128 | | - |
| 130 | + $namespace = $GLOBALS['wgRequest']->getIntorNull( 'namespace', $ns ); |
| 131 | + |
| 132 | + $protocols_list[] = ''; |
| 133 | + foreach( $wgUrlProtocols as $prot ) { |
| 134 | + $protocols_list[] = $prot; |
| 135 | + } |
| 136 | + |
| 137 | + $target2 = $target; |
| 138 | + $protocol = ''; |
| 139 | + $pr_sl = strpos($target2, '//' ); |
| 140 | + $pr_cl = strpos($target2, ':' ); |
| 141 | + if ( $pr_sl ) { |
| 142 | + // For protocols with '//' |
| 143 | + $protocol = substr( $target2, 0 , $pr_sl+2 ); |
| 144 | + $target2 = substr( $target2, $pr_sl+2 ); |
| 145 | + } elseif ( !$pr_sl && $pr_cl ) { |
| 146 | + // For protocols without '//' like 'mailto:' |
| 147 | + $protocol = substr( $target2, 0 , $pr_cl+1 ); |
| 148 | + $target2 = substr( $target2, $pr_cl+1 ); |
| 149 | + } elseif ( $protocol == '' && $target2 != '' ) { |
| 150 | + // default |
| 151 | + $protocol = 'http://'; |
| 152 | + } |
| 153 | + if ( !in_array( $protocol, $protocols_list ) ) { |
| 154 | + // unsupported protocol, show original search request |
| 155 | + $target2 = $target; |
| 156 | + $protocol = ''; |
| 157 | + } |
| 158 | + |
129 | 159 | $self = Title::makeTitle( NS_SPECIAL, 'Linksearch' ); |
130 | | - |
131 | | - global $wgOut; |
132 | | - $wgOut->addWikiText( wfMsg( 'linksearch-text' ) ); |
133 | | - $wgOut->addHtml( |
134 | | - wfOpenElement( 'form', |
135 | | - array( 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . |
136 | | - wfHidden( 'title', $self->getPrefixedDbKey() ) . |
137 | | - wfInput( 'target', 50, $target ) . |
138 | | - wfSubmitButton( wfMsg( 'search' ) ) . |
139 | | - wfCloseElement( 'form' ) ); |
140 | 160 | |
| 161 | + $wgOut->addWikiText( wfMsg( 'linksearch-text', '<nowiki>' . implode( ', ', $wgUrlProtocols) . '</nowiki>' ) ); |
| 162 | + $s = Xml::openElement( 'form', array( 'id' => 'mw-linksearch-form', 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . |
| 163 | + Xml::hidden( 'title', $self->getPrefixedDbKey() ) . |
| 164 | + '<fieldset>' . |
| 165 | + Xml::element( 'legend', array(), wfMsg( 'linksearch' ) ) . |
| 166 | + Xml::label( wfMsg( 'linksearch-pat' ), 'target' ) . ' ' . |
| 167 | + Xml::input( 'target', 50 , $target ) . ' '; |
| 168 | + if ( !$wgMiserMode ) { |
| 169 | + $s .= Xml::label( wfMsg( 'linksearch-ns' ), 'namespace' ) . |
| 170 | + XML::namespaceSelector( $namespace, '' ); |
| 171 | + } |
| 172 | + $s .= Xml::submitButton( wfMsg( 'linksearch-ok' ) ) . |
| 173 | + '</fieldset>' . |
| 174 | + Xml::closeElement( 'form' ); |
| 175 | + $wgOut->addHtml( $s ); |
| 176 | + |
141 | 177 | if( $target != '' ) { |
142 | | - $searcher = new LinkSearchPage( $target ); |
| 178 | + $searcher = new LinkSearchPage( $target2, $namespace, $protocol ); |
143 | 179 | $searcher->doQuery( $offset, $limit ); |
144 | 180 | } |
145 | 181 | } |