Index: trunk/phase3/includes/LinkFilter.php |
— | — | @@ -50,7 +50,7 @@ |
51 | 51 | * @param $filterEntry String: domainparts |
52 | 52 | * @param $prot String: protocol |
53 | 53 | */ |
54 | | - function makeLike( $filterEntry , $prot = 'http' ) { |
| 54 | + function makeLike( $filterEntry , $prot = 'http://' ) { |
55 | 55 | if ( substr( $filterEntry, 0, 2 ) == '*.' ) { |
56 | 56 | $subdomains = true; |
57 | 57 | $filterEntry = substr( $filterEntry, 2 ); |
— | — | @@ -76,18 +76,32 @@ |
77 | 77 | $path = '/'; |
78 | 78 | $host = $filterEntry; |
79 | 79 | } |
80 | | - $host = strtolower( implode( '.', array_reverse( explode( '.', $host ) ) ) ); |
81 | | - if ( substr( $host, -1, 1 ) !== '.' ) { |
82 | | - $host .= '.'; |
| 80 | + // Reverse the labels in the hostname, convert to lower case |
| 81 | + // For emails reverse domainpart only |
| 82 | + if ( $prot == 'mailto:' && strpos($host, '@') ) { |
| 83 | + // complete email adress |
| 84 | + $mailparts = explode( '@', $host ); |
| 85 | + $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) ); |
| 86 | + $host = $domainpart . '@' . $mailparts[0]; |
| 87 | + $like = "$prot$host%"; |
| 88 | + } elseif ( $prot == 'mailto:' ) { |
| 89 | + // domainpart of email adress only. do not add '.' |
| 90 | + $host = strtolower( implode( '.', array_reverse( explode( '.', $host ) ) ) ); |
| 91 | + $like = "$prot$host%"; |
| 92 | + } else { |
| 93 | + $host = strtolower( implode( '.', array_reverse( explode( '.', $host ) ) ) ); |
| 94 | + if ( substr( $host, -1, 1 ) !== '.' ) { |
| 95 | + $host .= '.'; |
| 96 | + } |
| 97 | + $like = "$prot$host"; |
| 98 | + |
| 99 | + if ( $subdomains ) { |
| 100 | + $like .= '%'; |
| 101 | + } |
| 102 | + if ( !$subdomains || $path !== '/' ) { |
| 103 | + $like .= $path . '%'; |
| 104 | + } |
83 | 105 | } |
84 | | - $like = "$prot://$host"; |
85 | | - |
86 | | - if ( $subdomains ) { |
87 | | - $like .= '%'; |
88 | | - } |
89 | | - if ( !$subdomains || $path !== '/' ) { |
90 | | - $like .= $path . '%'; |
91 | | - } |
92 | 106 | return $like; |
93 | 107 | } |
94 | 108 | } |
Index: trunk/phase3/includes/GlobalFunctions.php |
— | — | @@ -1932,22 +1932,45 @@ |
1933 | 1933 | * Make a URL index, appropriate for the el_index field of externallinks. |
1934 | 1934 | */ |
1935 | 1935 | function wfMakeUrlIndex( $url ) { |
| 1936 | + global $wgUrlProtocols; // Allow all protocols defined in DefaultSettings/LocalSettings.php |
| 1937 | + $bits = parse_url( $url ); |
1936 | 1938 | wfSuppressWarnings(); |
1937 | | - $bits = parse_url( $url ); |
1938 | | - $prots = array( 'http', 'https', 'ftp', 'irc', 'news' ); |
1939 | 1939 | wfRestoreWarnings(); |
1940 | | - if ( !$bits || !in_array( $bits['scheme'], $prots ) ) { |
| 1940 | + if ( !$bits ) { |
1941 | 1941 | return false; |
1942 | 1942 | } |
| 1943 | + // most of the protocols are followed by ://, but mailto: and sometimes news: not, check for it |
| 1944 | + $delimiter = ''; |
| 1945 | + if ( in_array( $bits['scheme'] . '://' , $wgUrlProtocols ) ) { |
| 1946 | + $delimiter = '://'; |
| 1947 | + } elseif ( in_array( $bits['scheme'] .':' , $wgUrlProtocols ) ) { |
| 1948 | + $delimiter = ':'; |
| 1949 | + // parse_url detects for news: and mailto: the host part of an url as path |
| 1950 | + // We have to correct this wrong detection |
| 1951 | + if ( isset ( $bits['path'] ) ) { |
| 1952 | + $bits['host'] = $bits['path']; |
| 1953 | + $bits['path'] = ''; |
| 1954 | + } |
| 1955 | + } else { |
| 1956 | + return false; |
| 1957 | + } |
| 1958 | + |
1943 | 1959 | // Reverse the labels in the hostname, convert to lower case |
1944 | | - $reversedHost = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) ); |
| 1960 | + // For emails reverse domainpart only |
| 1961 | + if ( $bits['scheme'] == 'mailto' ) { |
| 1962 | + $mailparts = explode( '@', $bits['host'] ); |
| 1963 | + $domainpart = strtolower( implode( '.', array_reverse( explode( '.', $mailparts[1] ) ) ) ); |
| 1964 | + $reversedHost = $domainpart . '@' . $mailparts[0]; |
| 1965 | + } else { |
| 1966 | + $reversedHost = strtolower( implode( '.', array_reverse( explode( '.', $bits['host'] ) ) ) ); |
| 1967 | + } |
1945 | 1968 | // Add an extra dot to the end |
1946 | 1969 | if ( substr( $reversedHost, -1, 1 ) !== '.' ) { |
1947 | 1970 | $reversedHost .= '.'; |
1948 | 1971 | } |
1949 | 1972 | // Reconstruct the pseudo-URL |
1950 | 1973 | $prot = $bits['scheme']; |
1951 | | - $index = "$prot://$reversedHost"; |
| 1974 | + $index = "$prot$delimiter$reversedHost"; |
1952 | 1975 | // Leave out user and password. Add the port, path, query and fragment |
1953 | 1976 | if ( isset( $bits['port'] ) ) $index .= ':' . $bits['port']; |
1954 | 1977 | if ( isset( $bits['path'] ) ) { |
Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -274,12 +274,11 @@ |
275 | 275 | * (bug 5546) Watchlist reflects logged actions like move, protection, undelete |
276 | 276 | * (bug 9019) No warning during upload if image description page exists, but no |
277 | 277 | image |
| 278 | +* Support protocols other than HTTP in LinkFilter, use $wgUrlProtocols |
278 | 279 | * (bug 8582) Allow thumbnailing when imagesize has a space. |
279 | 280 | * (bug 8716) Change math_inputhash and math_outputhash to byte for Postgres |
280 | 281 | * (bug 8558) Correct display of timestamps on some pages when using Postgres |
281 | 282 | |
282 | | -Support protocols other than HTTP in LinkFilter |
283 | | - |
284 | 283 | == Languages updated == |
285 | 284 | |
286 | 285 | * Arabic (ar) |
Index: trunk/extensions/LinkSearch/LinkSearch.i18n.php |
— | — | @@ -12,9 +12,7 @@ |
13 | 13 | 'linksearch-pat' => 'Search pattern:', |
14 | 14 | 'linksearch-ns' => 'Namespace:', |
15 | 15 | 'linksearch-ok' => 'Search', |
16 | | - 'linksearch-text' => 'Wildcards such as " *.wikipedia.org " may be used. |
17 | | - |
18 | | -The default protocol is http. Other possible protocols: https, ftp, irc, news.', |
| 16 | + 'linksearch-text' => 'Wildcards such as " *.wikipedia.org " may be used.', |
19 | 17 | 'linksearch-line' => '$1 linked from $2', |
20 | 18 | 'linksearch-error' => 'Wildcards may appear only at the start of the hostname.', |
21 | 19 | ); |
— | — | @@ -29,10 +27,7 @@ |
30 | 28 | 'linksearch-pat' => 'Suchmuster:', |
31 | 29 | 'linksearch-ns' => 'Namensraum:', |
32 | 30 | 'linksearch-ok' => 'Suche', |
33 | | - '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. |
34 | | - |
35 | | - Standardmäßig wird nur nach http:// gesucht. Weitere unterstützte Protokolle: https, ftp, irc und news.', |
36 | | - 'linksearch-line' => '$1 ist verlinkt von $2', |
| 31 | + '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.', 'linksearch-line' => '$1 ist verlinkt von $2', |
37 | 32 | 'linksearch-error' => 'Wildcards können nur am Anfang der URL verwendet werden.', |
38 | 33 | ); |
39 | 34 | $wgLinkSearchMessages['fi'] = array( |
— | — | @@ -55,9 +50,7 @@ |
56 | 51 | 'linksearch-pat' => 'קישור לחיפוש:', |
57 | 52 | 'linksearch-ns' => 'מרחב שם:', |
58 | 53 | 'linksearch-ok' => 'חיפוש', |
59 | | - 'linksearch-text' => 'ניתן להשתמש בתווים כללים, לדוגמה "*.wikipedia.org". |
60 | | - |
61 | | -פרוטוקול ברירת המחדל הוא HTTP. פרוטוקולים אפשריים אחרים: HTTPS, FTP, IRC, NEWS.', |
| 54 | + 'linksearch-text' => 'ניתן להשתמש בתווים כללים, לדוגמה "*.wikipedia.org"', |
62 | 55 | 'linksearch-line' => '$1 מקושר מהדף $2', |
63 | 56 | 'linksearch-error' => 'תווים כלליים יכולים להופיע רק בתחילת שם השרת.', |
64 | 57 | ); |
Index: trunk/extensions/LinkSearch/LinkSearch.php |
— | — | @@ -28,9 +28,10 @@ |
29 | 29 | /*function*/ false, /*file*/ false ); |
30 | 30 | |
31 | 31 | class LinkSearchPage extends QueryPage { |
32 | | - function __construct( $query , $ns ) { |
| 32 | + function __construct( $query , $ns , $prot ) { |
33 | 33 | $this->mQuery = $query; |
34 | 34 | $this->mNs = $ns; |
| 35 | + $this->mProt = $prot; |
35 | 36 | } |
36 | 37 | |
37 | 38 | function getName() { |
— | — | @@ -47,37 +48,20 @@ |
48 | 49 | /** |
49 | 50 | * Return an appropriately formatted LIKE query |
50 | 51 | */ |
51 | | - static function mungeQuery( $query ) { |
52 | | - $prot = 'http'; // use http as standard |
53 | | - if( substr( $query, 0, 7 ) == 'http://' ) { |
54 | | - $query = substr( $query, 7 ); |
55 | | - } elseif( substr( $query, 0, 8 ) == 'https://' ) { |
56 | | - $query = substr( $query, 8 ); |
57 | | - $prot = 'https'; |
58 | | - } elseif( substr( $query, 0, 6 ) == 'ftp://' ) { |
59 | | - $query = substr( $query, 6 ); |
60 | | - $prot = 'ftp'; |
61 | | - } elseif( substr( $query, 0, 6 ) == 'irc://' ) { |
62 | | - $query = substr( $query, 6 ); |
63 | | - $prot = 'irc'; |
64 | | - } elseif( substr( $query, 0, 7 ) == 'news://' ) { |
65 | | - $query = substr( $query, 7 ); |
66 | | - $prot = 'news'; |
67 | | - } |
| 52 | + static function mungeQuery( $query , $prot ) { |
68 | 53 | return LinkFilter::makeLike( $query , $prot ); |
69 | 54 | } |
70 | 55 | |
71 | 56 | function linkParameters() { |
72 | | - return array( 'target' => $this->mQuery, 'namespace' => $this->mNs ); |
| 57 | + return array( 'target' => $this->mQuery, 'namespace' => $this->mNs , 'protocol' => $this->mProt ); |
73 | 58 | } |
74 | 59 | |
75 | 60 | function getSQL() { |
76 | 61 | $dbr = wfGetDB( DB_SLAVE ); |
77 | 62 | $page = $dbr->tableName( 'page' ); |
78 | 63 | $externallinks = $dbr->tableName( 'externallinks' ); |
79 | | - $encSearch = $dbr->addQuotes( self::mungeQuery( $this->mQuery ) ); |
| 64 | + $encSearch = $dbr->addQuotes( self::mungeQuery( $this->mQuery, $this->mProt ) ); |
80 | 65 | $encSQL = ''; |
81 | | - |
82 | 66 | if ( isset ($this->mNs) ) $encSQL = 'AND page_namespace=' . $this->mNs; |
83 | 67 | return |
84 | 68 | "SELECT |
— | — | @@ -108,7 +92,7 @@ |
109 | 93 | */ |
110 | 94 | function doQuery( $offset, $limit ) { |
111 | 95 | global $wgOut; |
112 | | - $this->mMungedQuery = LinkSearchPage::mungeQuery( $this->mQuery ); |
| 96 | + $this->mMungedQuery = LinkSearchPage::mungeQuery( $this->mQuery, $this->mProt ); |
113 | 97 | if( $this->mMungedQuery === false ) { |
114 | 98 | $wgOut->addWikiText( wfMsg( 'linksearch-error' ) ); |
115 | 99 | } else { |
— | — | @@ -131,27 +115,36 @@ |
132 | 116 | |
133 | 117 | function wfSpecialLinksearch( $par=null, $ns=null ) { |
134 | 118 | list( $limit, $offset ) = wfCheckLimits(); |
135 | | - global $wgOut, $wgRequest; |
| 119 | + global $wgOut, $wgRequest, $wgUrlProtocols; |
136 | 120 | $target = $GLOBALS['wgRequest']->getVal( 'target', $par ); |
137 | 121 | $namespace = $GLOBALS['wgRequest']->getIntorNull( 'namespace', $ns ); |
| 122 | + $protocol = $GLOBALS['wgRequest']->getVal( 'protocol', $prot ); |
138 | 123 | $self = Title::makeTitle( NS_SPECIAL, 'Linksearch' ); |
139 | 124 | |
140 | | - |
141 | | - $wgOut->addWikiText( wfMsg( 'linksearch-text' ) ); |
142 | | - $wgOut->addHtml( |
143 | | - Xml::openElement( 'form', array( 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . |
| 125 | + $wgOut->addWikiText( wfMsg( 'linksearch-text', '<nowiki>' . implode( ', ', $wgUrlProtocols) . '</nowiki>' ) ); |
| 126 | + $s = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $GLOBALS['wgScript'] ) ) . |
144 | 127 | Xml::hidden( 'title', $self->getPrefixedDbKey() ) . |
145 | 128 | '<fieldset>' . |
146 | 129 | Xml::element( 'legend', array(), wfMsg( 'linksearch' ) ) . |
147 | | - Xml::inputLabel( wfMsg( 'linksearch-pat' ), 'target', 'target', 50 , $target ) . '<br />' . |
| 130 | + Xml::label( wfMsg( 'linksearch-pat' ), 'target' ) . ' ' . |
| 131 | + "<select id='protocol' name='protocol' class='protocolselector'>"; |
| 132 | + foreach( $wgUrlProtocols as $prot ) { |
| 133 | + if ( $prot == $protocol ) { |
| 134 | + $s .= Xml::option( $prot, $prot, true ); |
| 135 | + } else { |
| 136 | + $s .= Xml::option( $prot, $prot ); |
| 137 | + } |
| 138 | + } |
| 139 | + $s .= Xml::input( 'target', 50 , $target ) . '<br />' . |
148 | 140 | Xml::label( wfMsg( 'linksearch-ns' ), 'namespace' ) . |
149 | 141 | XML::namespaceSelector( $namespace, '' ) . |
150 | 142 | Xml::submitButton( wfMsg( 'linksearch-ok' ) ) . |
151 | 143 | '</fieldset>' . |
152 | | - Xml::closeElement( 'form' ) ); |
| 144 | + Xml::closeElement( 'form' ); |
| 145 | + $wgOut->addHtml( $s ); |
153 | 146 | |
154 | 147 | if( $target != '' ) { |
155 | | - $searcher = new LinkSearchPage( $target, $namespace ); |
| 148 | + $searcher = new LinkSearchPage( $target, $namespace, $protocol ); |
156 | 149 | $searcher->doQuery( $offset, $limit ); |
157 | 150 | } |
158 | 151 | } |