├── .gitignore ├── LICENSE ├── README.md ├── autotest.php ├── class ├── controller.php ├── hcardvalidator.php ├── loader.php ├── validationresult.php └── vcard.php ├── compilelangs.sh ├── encode └── index.php ├── examples ├── acid.html ├── example 1.html ├── example 10.html ├── example 11.html ├── example 2.html ├── example 3.html ├── example 4.html ├── example 5.html ├── example 6.html ├── example 7.html ├── example 8.html ├── example 9.html ├── geo 1.html ├── geo 2.html ├── hcard in atom.atom ├── ignored_classes.html ├── im invalid.html ├── im valid.html ├── implied n.html ├── include 2.html ├── include 3.html ├── include.html ├── missing_fields.html ├── nested.html ├── obfuscated_email.html ├── orphan_adr.html ├── value_problems 1.html ├── value_problems 2.html ├── values.html ├── xhtml_multi_profile.html ├── xhtml_no_head.html ├── xhtml_no_profile.html ├── xhtml_wrong_profile.html └── xhtml_xmlns.html ├── i ├── error.png ├── favicon.png ├── grad.png ├── info.png ├── invalid.png ├── logo.png ├── style.css ├── valid.png └── warn.png ├── index.php ├── locale ├── cs │ └── LC_MESSAGES │ │ ├── errors.po │ │ ├── main.po │ │ └── props.po ├── en │ └── LC_MESSAGES │ │ ├── errors.po │ │ ├── main.po │ │ └── props.po ├── fr │ └── LC_MESSAGES │ │ ├── errors.po │ │ ├── main.po │ │ └── props.po └── pl │ └── LC_MESSAGES │ ├── errors.po │ ├── main.po │ └── props.po ├── referrer └── index.php ├── robots.txt ├── tpl └── main.html ├── xmlcatalog.xml ├── xmlcatalog ├── xhtml-attribs-1.mod ├── xhtml-charent-1.mod ├── xhtml-datatypes-1.mod ├── xhtml-events-1.mod ├── xhtml-framework-1.mod ├── xhtml-inlstyle-1.mod ├── xhtml-lat1.ent ├── xhtml-qname-1.mod ├── xhtml-special.ent ├── xhtml-symbol.ent ├── xhtml1-strict.dtd ├── xhtml1-trans.dtd ├── xhtml11-model-1.mod └── xhtml11.dtd └── xslt ├── COPYING ├── hcard.xslt ├── html2xhtml.xslt └── include.xslt /.gitignore: -------------------------------------------------------------------------------- 1 | *.mo 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2010 Kornel Lesiński. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without modification, 4 | are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | * Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | * Neither the name of the the copyright holder nor the names of its contributors 14 | may be used to endorse or promote products derived from this software 15 | without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 19 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [](http://unmaintained.tech/ "This project is not actively maintained") 2 | 3 | #hCard Validator 4 | 5 | Conformance checker for the [hCard microformat](http://microformats.org/wiki/hcard). 6 | 7 | It's a tool written in a mix of PHP and XSLT that checks hCards against the specification. 8 | 9 | ##Live demo 10 | 11 | You can use live version at [hcard.geekhood.net](http://hcard.geekhood.net/). 12 | 13 | ##TODO 14 | 15 | * hCard validator doesn't support latest version of the spec with value class pattern. 16 | * other microformats are not supported. I'd like this project to evolve into conformance checker for all microformats. 17 | 18 | [See issues](http://github.com/pornel/hCardValidator/issues) 19 | 20 | ##Running 21 | 22 | [Setup instructions](http://github.com/pornel/hCardValidator/wiki/Installation) 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /autotest.php: -------------------------------------------------------------------------------- 1 | validator = new hCardValidator(); 20 | } 21 | 22 | private $unexpected_errors = 0; 23 | 24 | function testFile($file, array $expected = []) 25 | { 26 | if (!is_file($file)) return; 27 | 28 | echo '
Expected error $notfound not found".($x > 1 ? " ×$x":"")."
"; 40 | foreach($result->vcards as $vcard) 41 | { 42 | echo ''.htmlspecialchars(print_r($vcard->data,true)).''; 43 | $this->unexpected_errors++; 44 | } 45 | } 46 | echo '
'.ucwords($e['type']).' ['.$e['class'].']: '.call_user_func_array('sprintf',$args)." ".$e['location']."
"; 101 | } 102 | } 103 | 104 | foreach($result->vcards as $vcard) 105 | { 106 | if ($this->checkResult($vcard->result, $expected)) 107 | { 108 | $hadUnexpectedErrors = true; 109 | echo ''.htmlspecialchars(print_r($vcard->data,true)).''; 110 | $this->unexpected_errors++; 111 | } 112 | } 113 | 114 | return $hadUnexpectedErrors; 115 | } 116 | 117 | function testAll() 118 | { 119 | header("Content-Type:text/html;charset=UTF-8"); 120 | ?>
'.$e.''); 153 | } 154 | $total = max(0.001,microtime(true) - $start); 155 | 156 | echo '
Done '.$filesnum.' files at '.round($filesnum / $total).' files/s
'; 157 | } 158 | } 159 | 160 | $c = new Controller(); 161 | $c->init(true); 162 | 163 | $t = new AutoTest(); 164 | $t->testAll(); 165 | -------------------------------------------------------------------------------- /class/loader.php: -------------------------------------------------------------------------------- 1 | url;} 8 | 9 | /** 10 | * i18nable messages must pass variable bits separately 11 | * @return array(i18n key, array(vars)) 12 | */ 13 | function getMessageArgs(){return [$this->msg_class,$this->args];} 14 | 15 | function __construct($default_msg, $msg_class, array $args = [],$url = NULL) 16 | { 17 | parent::__construct($default_msg); 18 | $this->url = $url; 19 | $this->args = $args; 20 | $this->msg_class = $msg_class; 21 | } 22 | } 23 | 24 | class LoaderURL 25 | { 26 | function __construct($url) 27 | { 28 | list($hostname,$ip,$path) = $this->paranoidURLSanitization($url); 29 | 30 | $this->hostname = $hostname; 31 | $this->ip = $ip; 32 | $this->path = $path; 33 | } 34 | 35 | private $hostname, $ip, $path; 36 | 37 | function __toString(){return $this->getURL();} 38 | 39 | function getURL() 40 | { 41 | return 'http://'.$this->hostname.$this->path; 42 | } 43 | 44 | function getIPURL() 45 | { 46 | return 'http://'.$this->ip.$this->path; 47 | } 48 | 49 | function getHost() 50 | { 51 | return $this->hostname; 52 | } 53 | 54 | function getPath() 55 | { 56 | return $this->path; 57 | } 58 | 59 | /** 60 | * @return array($hostname,$ip,$path) 61 | */ 62 | private function paranoidURLSanitization($url) 63 | { 64 | $standard_excuse = "URL not allowed\nPardon me being paranoid about security, but this URL doesn't look innocent enough (HTTP with hostname and without authentication or ports please)."; 65 | 66 | $url = trim($url); 67 | $url = preg_replace_callback('/([\x00-\x20\x7f-\xff]+)/',function($m){return rawurlencode($m[0]);},$url); 68 | 69 | if (!preg_match('/https?:\/\//',$url)) $url = 'http://'.$url; 70 | 71 | // PHP's built-in filter is rather weak, so don't stop there 72 | $url = filter_var($url,FILTER_SANITIZE_URL); 73 | $url = filter_var($url,FILTER_VALIDATE_URL,FILTER_FLAG_HOST_REQUIRED|FILTER_FLAG_SCHEME_REQUIRED); 74 | 75 | if (!preg_match('/^https?:\/\/((?:[a-z0-9][a-z0-9-]*\.)+[a-z]{2,6})\.?(\/[^#]*)?(?:#.*)?$/i',$url,$m)) 76 | { 77 | throw new LoaderException($standard_excuse,"invalid_url",[],$url); 78 | } 79 | 80 | $hostname = strtolower($m[1]); 81 | $path = isset($m[2]) ? $m[2] : '/'; 82 | 83 | if (preg_match('/\.sblam\.com$|api\.geekhood.net$|\.local$/',$hostname)) 84 | { 85 | throw new LoaderException($standard_excuse,"invalid_url",[],$url); 86 | } 87 | 88 | $ip = gethostbyname($hostname); 89 | if (!$ip || $ip == $m[1]) 90 | { 91 | throw new LoaderException("Can't find hostname.","dns_error",[$hostname],'http://'.$hostname.$path); 92 | } 93 | 94 | if (!($ip = filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4|FILTER_FLAG_NO_PRIV_RANGE|FILTER_FLAG_NO_RES_RANGE))) 95 | { 96 | throw new LoaderException($standard_excuse,"invalid_url",[],'http://'.$hostname.$path); 97 | } 98 | 99 | return [$hostname,$ip,$path]; 100 | } 101 | } 102 | 103 | class Loader 104 | { 105 | /** 106 | * get URL content from teh internets 107 | * 108 | * @return array($content,$response_headers,$url); 109 | */ 110 | function fetchURL($url) 111 | { 112 | $lurl = new LoaderURL($url); 113 | 114 | // send XFF header 115 | $xff = $_SERVER['REMOTE_ADDR']; 116 | 117 | // if there's existing one, append 118 | if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && preg_match('/^[ ,0-9.]+$/',$_SERVER['HTTP_X_FORWARDED_FOR'])) 119 | { 120 | $xff .= ', '.trim($_SERVER['HTTP_X_FORWARDED_FOR']); 121 | } 122 | 123 | $headers = [ 124 | 'Accept' => 'application/xhtml+xml, application/xml;q=0.9, text/html;q=0.1', // Apache with Multiviews doesn't seem to like it. Poor baby. 125 | 'User-Agent' => 'hCardValidator/1 PHP/5 (http://hcard.geekhood.net)', 126 | 'Referer' => 'http://'.$_SERVER['HTTP_HOST'].'/', 127 | 'X-Forwarded-For' => $xff, 128 | ]; 129 | 130 | return $this->performURLFetch($lurl,$headers); 131 | } 132 | 133 | /** 134 | * HTTP response parser 135 | */ 136 | private function getHeaders($wrapper_data) 137 | { 138 | $response_headers = []; 139 | 140 | if ($wrapper_data && is_array($wrapper_data)) foreach($wrapper_data as $h) 141 | { 142 | if (preg_match('/^([^\s]+)\s*:\s*(.*)$/i',$h,$m)) 143 | { 144 | $response_headers[strtolower($m[1])] = $m[2]; 145 | } 146 | else if (preg_match('/^HTTP\/1\..\s+(\d+)/',$h,$m)) 147 | { 148 | $response_headers['status'] = $m[1]; 149 | } 150 | } 151 | 152 | return $response_headers; 153 | } 154 | 155 | private function throwError(LoaderURL $lurl,array $response_headers) 156 | { 157 | if (empty($response_headers['status'])) 158 | { 159 | throw new LoaderException("Server may be down.","request_failed",[$lurl->getHost()],$lurl->getURL()); 160 | } 161 | 162 | if ($response_headers['status'] == 404 || $response_headers['status'] == 410) 163 | { 164 | throw new LoaderException("File not found","file_not_found",[$lurl->getPath(),$lurl->getHost()],$lurl->getURL()); 165 | } 166 | 167 | if ($response_headers['status'] >= 300 && $response_headers['status'] < 400) 168 | { 169 | throw new LoaderException("Invalid redirect","invalid_redirect",[],$lurl->getURL()); 170 | } 171 | 172 | throw new LoaderException("HTTP error","http_error",[$response_headers['status']],$lurl->getURL()); 173 | } 174 | 175 | private function performURLFetch(LoaderURL $lurl,array $request_headers, $redirects_allowed = 5) 176 | { 177 | global $http_response_header; // PHP is crap. This is automagic variable that's used instead of something that makes sense to sober people. 178 | 179 | $headers_string = ''; 180 | $request_headers['Host'] = $lurl->getHost(); 181 | foreach($request_headers as $k => $v) 182 | { 183 | $headers_string .= "$k: ".preg_replace('/\s+/',' ',$v)."\r\n"; 184 | } 185 | 186 | $ctx = stream_context_create([ 187 | 'http'=>[ 188 | 'method'=>'GET', 189 | 'max_redirects'=>0, // I want to handle redirects myself 190 | 'timeout'=>10, 191 | 'header'=>$headers_string, 192 | ]]); 193 | 194 | $http_response_header = NULL; // PHP is crap² 195 | $fp = @fopen($lurl->getIPURL(),"rb",false,$ctx); 196 | if (!$fp) 197 | { 198 | $response_headers = $this->getHeaders($http_response_header); 199 | } 200 | else 201 | { 202 | $metadata = stream_get_meta_data($fp); 203 | if (empty($metadata['wrapper_data'])) throw new Exception("PHP Sucks"); 204 | $response_headers = $this->getHeaders($metadata['wrapper_data']); 205 | } 206 | 207 | if (empty($response_headers['status']) || $response_headers['status'] < 100 || $response_headers['status'] >= 400) 208 | { 209 | $this->throwError($lurl,$response_headers); 210 | } 211 | elseif ($response_headers['status'] >= 300 && $response_headers['status'] < 400) 212 | { 213 | if (empty($response_headers['location']) || $redirects_allowed <= 0) 214 | { 215 | $this->throwError($lurl,$response_headers); 216 | } 217 | $newurl = new LoaderURL($response_headers['location']); 218 | return $this->performURLFetch($newurl, $request_headers, $redirects_allowed - 1); 219 | } 220 | else 221 | { 222 | $maxlen = 800000; 223 | $file = stream_get_contents($fp,$maxlen); 224 | if (strlen($file) >= $maxlen) 225 | { 226 | throw new LoaderException("File larger than maximum size","maximum_file_size",[round($maxlen/1000)],$url); 227 | } 228 | return [$file,$response_headers,$lurl->getURL()]; 229 | } 230 | } 231 | 232 | } 233 | -------------------------------------------------------------------------------- /class/validationresult.php: -------------------------------------------------------------------------------- 1 | isValid = true; 24 | $this->fileName = $fileName; 25 | } 26 | 27 | /** 28 | * hcard.xslt creates bunch of nice elements, which aren't very useful in their Node'ish form. 29 | * Cram everything into arrays and objects instead! 30 | * 31 | * @return void 32 | */ 33 | function addFromDoc(DOMDocument $doc) 34 | { 35 | $xp = new DOMXPath($doc); 36 | $xp->registerNamespace('v','http://pornel.net/hcard-validator'); // my hacks 37 | $xp->registerNamespace('c','http://www.w3.org/2006/03/hcard'); // let's pretend this is real 38 | 39 | // first get all errors that don't belong to any particular vcard 40 | foreach($xp->query('(//v:error|//v:warn|//v:info)[not(ancestor::c:vcard)]') as $node) 41 | { 42 | $args = []; 43 | foreach($xp->query('v:arg',$node) as $arg) 44 | { 45 | $args[] = $arg->textContent; 46 | } 47 | $this->add($node->localName,$node->getAttribute('id'),Controller::escapeXML($node->textContent),$args,$node->getAttribute('href')); 48 | $node->parentNode->removeChild($node); // clean up errors 49 | } 50 | 51 | // then extract vcards and their errors 52 | foreach($xp->query('//c:vcard') as $vcardNode) 53 | { 54 | $result = new ValidationResult($this->fileName); 55 | foreach($xp->query('(.//v:error|.//v:warn|.//v:info)',$vcardNode) as $node) 56 | { 57 | // build nice location string which won't be used anyway! :) 58 | $location = ''; 59 | foreach($xp->query('ancestor::c:*',$node) as $parent) 60 | { 61 | if ($parent->localName == 'vcard') break; 62 | $location .= ($location ? ' » ':'').$parent->localName; 63 | } 64 | 65 | // args for i18n strings 66 | $args = []; 67 | foreach($xp->query('v:arg',$node) as $arg) 68 | { 69 | $args[] = $arg->textContent; 70 | } 71 | $result->add($node->localName,$node->getAttribute('id'),Controller::escapeXML($node->textContent),$args,$node->getAttribute('href'),$location); 72 | $node->parentNode->removeChild($node); // clean up errors 73 | } 74 | 75 | $vcard = new vCard($vcardNode,$result); 76 | $this->vcards[] = $vcard; 77 | } 78 | } 79 | 80 | /** 81 | * add new error 82 | * 83 | * @param $type - error, warn or info 84 | * @param $error_class - @see localizedMessage 85 | * @param $default_message - if message has more than one line, first line is used as header, rest is body. 86 | * @param $args - @see localizedMessage 87 | * @param $href - link to more detailed explanation of the error 88 | * @param $location - (string) where the error has occured 89 | */ 90 | function add($type, $error_class, $default_message, array $args = [], $href = NULL, $location = NULL) 91 | { 92 | if ($type == 'error') $this->isValid = false; 93 | 94 | $this->errors[] = [ 95 | 'type'=>$type, 96 | 'class'=>$error_class, 97 | 'message'=>$default_message, 98 | 'args'=>$args, 99 | 'href'=>$href, 100 | 'location'=>$location, 101 | ]; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /class/vcard.php: -------------------------------------------------------------------------------- 1 | result holds vcard-specific errors. 7 | */ 8 | class vCard 9 | { 10 | public $data, $result; 11 | private $flags; 12 | 13 | function __construct(DOMNode $node, ValidationResult $result) 14 | { 15 | $this->result = $result; 16 | $this->node = $node; 17 | $this->flags = []; 18 | 19 | $this->data = $this->nodeToArray($node); 20 | if (!is_array($this->data)) 21 | { 22 | $this->data = []; // nodeToArray may return string if there are no elements! 23 | } 24 | } 25 | 26 | function flag($name) 27 | { 28 | if (!isset($this->flags[$name])) return false; 29 | 30 | return $this->flags[$name]; 31 | } 32 | 33 | function __get($name) 34 | { 35 | if (isset($this->data[$name])) return $this->data[$name]; 36 | return []; 37 | } 38 | 39 | function append($name,$value) 40 | { 41 | if (!isset($this->data[$name])) $this->data[$name] = []; 42 | $this->data[$name][] = $value; 43 | } 44 | 45 | function query($path) 46 | { 47 | $parts = explode('/',$path); 48 | $result = []; 49 | $this->queryPart($parts,$this->data,$result); 50 | return $result; 51 | } 52 | 53 | 54 | private function queryPart(array $parts, array $in, array &$result) 55 | { 56 | $prop = array_shift($parts); 57 | 58 | if (isset($in[$prop]) and is_array($in[$prop])) 59 | { 60 | if (count($parts)) 61 | { 62 | foreach($in[$prop] as $k => $v) 63 | { 64 | if (is_array($v)) 65 | { 66 | $this->queryPart($parts, $v, $result); 67 | } 68 | else 69 | { 70 | echo "WTF? $k in $prop"; 71 | } 72 | } 73 | } 74 | else 75 | { 76 | foreach($in[$prop] as $k => $v) 77 | { 78 | $result[] = $v; 79 | } 80 | } 81 | } 82 | } 83 | 84 | function allOrgNames() 85 | { 86 | $org_names = []; 87 | foreach($this->org as $org) 88 | { 89 | if (!empty($org['organization-name'])) foreach($org['organization-name'] as $name) 90 | { 91 | $org_names[] = $name; 92 | } 93 | } 94 | return $org_names; 95 | } 96 | 97 | private function nodeToArray(DOMNode $node) 98 | { 99 | $data = []; 100 | 101 | $hasElements = false; 102 | foreach($node->childNodes as $element) 103 | { 104 | if ($element->nodeType != XML_ELEMENT_NODE) continue; 105 | 106 | if ($element->namespaceURI == "http://www.w3.org/2006/03/hcard") 107 | { 108 | $hasElements = true; 109 | 110 | $name = $element->localName; 111 | if (!isset($data[$name])) $data[$name] = []; 112 | 113 | $data[$name][] = $this->nodeToArray($element); 114 | } 115 | else if ($element->namespaceURI == "http://pornel.net/hcard-validator") 116 | { 117 | if ($element->localName == 'flag') 118 | { 119 | $this->flags[ $element->getAttribute('id') ] = ($element->textContent == '') ? true : $element->textContent; 120 | } 121 | } 122 | } 123 | 124 | if (!$hasElements) 125 | { 126 | return trim($node->textContent,' '); 127 | } 128 | else 129 | { 130 | return $data; 131 | } 132 | } 133 | 134 | 135 | public function checkAndRemoveEmpty() 136 | { 137 | $this->flags['had_n'] = isset($this->data['n']); // even empty n property prevents implied nickname. this function will remove all empty props, so this needs to be saved now. 138 | 139 | $this->checkAndRemoveEmptyRecursive($this->data); 140 | } 141 | 142 | /** 143 | * hcard.xslt may produce properties with empty values 144 | * scan data (recursively) and remove properties (or subtrees) with empty values 145 | * 146 | * some properties can be empty - it's handled elsewhere 147 | */ 148 | private function checkAndRemoveEmptyRecursive(array &$data, $parent = NULL) 149 | { 150 | foreach($data as $prop => &$values) 151 | { 152 | foreach($values as $idx => &$v) 153 | { 154 | if (!is_array($v)) 155 | { 156 | if ('' === trim($v)) 157 | { 158 | $warn_or_err = "warn"; 159 | 160 | // adr and value (combined) of tel/email are not allowed to be empty 161 | if ($prop == 'adr' || ($prop == 'value' && $parent && ($parent == 'tel' || $parent == 'email'))) 162 | { 163 | $warn_or_err = "error"; 164 | } 165 | 166 | if ($parent) $this->result->add($warn_or_err,"empty_subprop","%s
property of %s
is empty",[$prop,$parent]);
167 | else $this->result->add($warn_or_err,"empty_prop","%s
property is empty",[$prop]);
168 |
169 | unset($values[$idx]);
170 | }
171 | }
172 | else
173 | {
174 | $this->checkAndRemoveEmptyRecursive($v, $prop);
175 | if (!count($v))
176 | {
177 | unset($values[$idx]);
178 | }
179 | }
180 | }
181 | if (!count($values))
182 | {
183 | unset($data[$prop]);
184 | }
185 | }
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/compilelangs.sh:
--------------------------------------------------------------------------------
1 | msgfmt /www/hcard/locale/en/LC_MESSAGES/errors.po -o /www/hcard/locale/en/LC_MESSAGES/errors.mo
2 | msgfmt /www/hcard/locale/en/LC_MESSAGES/props.po -o /www/hcard/locale/en/LC_MESSAGES/props.mo
3 | msgfmt /www/hcard/locale/en/LC_MESSAGES/main.po -o /www/hcard/locale/en/LC_MESSAGES/main.mo
4 | msgfmt /www/hcard/locale/pl/LC_MESSAGES/errors.po -o /www/hcard/locale/pl/LC_MESSAGES/errors.mo
5 | msgfmt /www/hcard/locale/pl/LC_MESSAGES/props.po -o /www/hcard/locale/pl/LC_MESSAGES/props.mo
6 | msgfmt /www/hcard/locale/pl/LC_MESSAGES/main.po -o /www/hcard/locale/pl/LC_MESSAGES/main.mo
7 |
8 | #sudo /usr/local/apache/sbin/apachectl restart
9 |
--------------------------------------------------------------------------------
/encode/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | It encodes e-mail addresses using random mix of urlencode
, HTML entities and then generates markup that's as tricky as possible, while remaining valid and parseable by browsers and XML-compliant parsers.
9 |
'.htmlspecialchars($out).'
';
69 | echo 'Test: '.$out.'
'; 70 | } 71 | ?> 72 |Return to the hCard Validator. 74 | -------------------------------------------------------------------------------- /examples/acid.html: -------------------------------------------------------------------------------- 1 | 3 | 4 |
5 | 6 | 7 |13 | ‘Well, Prince, so Genoa and Lucca are now just family estates of the Buonapartes. But I warn you, if you don’t tell me that this means war, if you still try to defend the infamies and horrors perpetrated by that Antichrist—I really believe he is Antichrist—I will have nothing more to do with you and you are no longer my friend, no longer my “faithful slave,” as you call yourself! But how do you do? I see I have frightened you—sit down and tell me all the news.’ 14 | 15 | 16 |
17 | 18 |19 | It was in July, 1805, and the speaker was the well–known Anna Pavlovna Scherer, maid of honor and favorite of the Empress Marya Fedorovna. With these words she greeted Prince Vasili Kuragin, a man of high rank and importance, who was the first to arrive at her reception. Anna Pavlovna had had a cough for some days. She was, as she said, suffering from la grippe; grippe being then a new word in St. Petersburg, used only by the elite. 20 | 21 | 22 | 23 | 24 | 25 |
26 |
27 | All her invitations without exception, written in French, and delivered by a scarlet-liveried footman that morning, ran as follows:
28 |
30 | ‘If you have nothing better to do, Count [or Prince], and if the prospect of spending an evening with a poor invalid is not too terrible, I shall be very charmed to see you tonight between 7 and 10—Annette Scherer.’ 31 |
32 | 33 |34 | 35 | ‘Heavens! what a virulent attack!’ replied the prince, not in the least disconcerted by this reception. He had just entered, wearing an embroidered court uniform, knee breeches, and shoes, and had stars on his breast and a serene expression on his flat face. He spoke in that refined French in which our grandfathers not only spoke but thought, and with the gentle, patronizing intonation natural to a man of importance who had grown old in society and at court. He went up to Anna Pavlovna, kissed her hand, presenting to her his bald, scented, and shining head, and complacently seated himself on the sofa. 36 | 37 | 38 |
39 |40 | ‘First of all, dear friend, tell me how you are. Set your friend’s mind at rest,’ said he without altering his tone, beneath the 41 | politeness and affected sympathy of which indifference and even irony could be discerned. 43 |
44 |
47 |
48 | Dr
49 |
50 | aka
51 |
52 | Mr Hyde
53 |
54 |
76 | 77 | | New York | 78 |Sydney is Good |
79 |
---|---|---|
8:00 am–9:00 am | 84 |Vodka |
85 | Food |
86 |
87 |
9:00 am–10:00 am | 90 |Food |
91 |
92 | Beer |
93 |
This hCard created with the hCard creator.
31 |31 | N 48° 81.6667 32 | E 2° 36.6667 33 |
37 | 38 | 39 | 40 | Eric Meyer 41 | 42 | wrote a post 43 | ( 44 | 45 | Tax Relief 46 | 47 | ) 48 | about an unintentionally humorous letter he received from the 49 | 50 | 51 | Internal Revenue Service 52 | . 53 |
54 | 55 |You can contact me via email to 11 | jane@example.com, 12 | 13 | or reach me at the following address:
14 |255 Some Street,
15 | Some Town,
16 | Some Place
You can contact me via email to 13 | jane@example.com, 14 | or reach me at the following address:
15 | 16 | 17 | 18 | 19 | Org 20 | 21 | 22 | 23 | unit 24 | 25 | 26 | 27 | ? 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 255 Some Street 36 | 37 | Some ignore Town 38 | Some Place 39 | 40 | 41 | 42 | 43 | 44 | 45 | openid! 46 |Joe B.
9 | john.smith@example.com 10 | 11 |Just a meeting place,
in case the venue changes.
66 | 67 | John 68 | Q. 69 | Public 70 | 71 |
72 | 73 | 74 | -------------------------------------------------------------------------------- /examples/example 8.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |Just29 |
testing.
This fax number is operational 0800 to 1715 EST, Mon-Fri.
25 | 26 | Updated: 10/31 10:27p 27 |Jane Doe uses PigeonMail 2.1 for email.
58 | -05:00 59 |86 | Mr.John Q. Public, Esq. 87 | Mail Drop: TNE QB 88 | 123 Main Street 89 | Any Town, CA 91921-1234 90 | U.S.A. 91 |92 |
Chatter
10 | 11 | IM with the AIM ShoppingBuddy 12 | 13 | IM with SomeYahooFriend 14 | 15 | IM with joebob@hotmail.com 16 | 17 | IM with username@jammerservice.com 18 | 19 | Nochat! 20 | Skype call to Skype echo service (Chinese) 21 | Skype call to Skype echo service (Chinese) 22 | 23 | 24 | 25 | 28 | Contact with ICQ 29 |Chatter
AKAChattyChatter
9 | 10 | IM with the AIM ShoppingBuddy 11 | IM with the AIM ShoppingBuddy 12 | 13 | IM with SomeYahooFriend 14 | 15 | IM with joebob@hotmail.com 16 | 17 | 18 | 19 | xmpp:username@jabberservice.com 20 | 21 | 22 | IM with the Skype echo service (Chinese) 23 | Skype call to Skype echo service (Chinese) 24 | Gadu-Gadu 25 | 26 | 29 | Contact with ICQ 30 |They call me Bond, James Bond.
12 |Because of an error in the validator it was impossible to check this document.
29 | '.Controller::escapeXML($e).''; ?> 30 | 31 | 32 | \n" 6 | "Language-Team: English\n" 7 | "MIME-Version: 1.0\n" 8 | "Content-Type: text/plain; charset=UTF-8\n" 9 | "Content-Transfer-Encoding: 8bit\n" 10 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 11 | 12 | # :file: /www/hcard/tpl/main.html 13 | msgid "title" 14 | msgstr "hCard Validátor" 15 | 16 | msgid "h1" 17 | msgstr "hCard microformat Validátor (beta, samozřejmě)" 18 | 19 | msgid "intro" 20 | msgstr "Toto je neoficiální validátor¹/kontrolor shody se specifikací hCard microformat." 21 | 22 | msgid "Input" 23 | msgstr "Vstup" 24 | 25 | msgid "urlintro" 26 | msgstr "Zkontroluje celou XHTML nebo HTML stránku zadáním HTTP URL." 27 | 28 | msgid "Address:" 29 | msgstr "Adresa:" 30 | 31 | msgid "Validate URL" 32 | msgstr "Validovat URL" 33 | 34 | msgid "Fragment" 35 | msgstr "Fragment" 36 | 37 | msgid "fragmentintro" 38 | msgstr "Vložte správně formátovaný XHTML fragment nebo celý dokument obsahující hCard." 39 | 40 | msgid "Validate fragment" 41 | msgstr "Validovat fragment" 42 | 43 | msgid "Upload" 44 | msgstr "Nahrát" 45 | 46 | msgid "uploadintro" 47 | msgstr "Pro validaci nahrajte HTML nebo XHTML soubor. Aby to fungovalo, Váš prohlížeč musí mít správně nataveny MIME typy." 48 | 49 | msgid "Upload file" 50 | msgstr "Nahrát soubor" 51 | 52 | msgid "Validate file" 53 | msgstr "Validovat soubor" 54 | 55 | msgid "Example" 56 | msgstr "Příklad" 57 | 58 | msgid "exampleintro" 59 | msgstr "Hledáte-li „hCards in the wild“, je to únavné. Zkuste testovací příklady:" 60 | 61 | msgid "Example file" 62 | msgstr "Soubor s příkladem" 63 | 64 | msgid "Browse examples" 65 | msgstr "Procházet příklady" 66 | 67 | msgid "View" 68 | msgstr "Zobraz" 69 | 70 | msgid "Validate example" 71 | msgstr "Validovat příklad" 72 | 73 | msgid "XHTML fragment" 74 | msgstr "XHTML fragment" 75 | 76 | msgid "api_and_other" 77 | msgstr "API & Další" 78 | 79 | msgid "byreferrer" 80 | msgstr "Na jakoukoliv stránku odkazem" 81 | 82 | msgid "Bookmarklet" 83 | msgstr "Bookmarklet" 84 | 85 | msgid "restful" 86 | msgstr "Pohodové JSON API" 87 | 88 | msgid "apidescription" 89 | msgstr "Odešlete GET
požadavek na ${url}.
Výsledek bude přibližně kompatibilní s ${validatornu}. V budoucnu pravděpodobně dojde ke změnám.
" 91 | 92 | msgid "pleaseuseforvalidation" 93 | msgstr "Prosím použijte toto API pro validaci, a nejen jako nástroj pro konverzi/extrakci." 94 | 95 | msgid "Send Feedback" 96 | msgstr "Poslat zpětnou vazbu" 97 | 98 | msgid "You can ${email} or the form below." 99 | msgstr "Můžete ${email} nebo pomocí formuláře níže." 100 | 101 | msgid "feedbacknote" 102 | msgstr "Pokud ${bug} nebo máte návrh, nezapomeňte zahrnout vzorek kódu hCard." 103 | 104 | msgid "feedbacknote_bug" 105 | msgstr "hlásíte chybu" 106 | 107 | msgid "Your name" 108 | msgstr "Vaše jméno" 109 | 110 | msgid "Your comment" 111 | msgstr "Váš komentář" 112 | 113 | msgid "Send feedback" 114 | msgstr "Odeslat zpětnou vazbu" 115 | 116 | msgid "Result" 117 | msgstr "Výsledek" 118 | 119 | msgid "valid" 120 | msgstr "Gratulujeme! Nebyly nalezeny žádné chyby." 121 | 122 | msgid "invalid" 123 | msgstr "Tento dokument obsahuje chyby." 124 | 125 | msgid "vcardnoerrors" 126 | msgstr "No issues found." 127 | 128 | msgid "More info" 129 | msgstr "Více informací" 130 | 131 | msgid "File source" 132 | msgstr "Zdrojový soubor" 133 | 134 | msgid "Parsed source" 135 | msgstr "Parsrovaný zdroj" 136 | 137 | msgid "Credits" 138 | msgstr "Zásluhy" 139 | 140 | msgid "fullcredits" 141 | msgstr "Napsal ${writtenby}. Ikony jsou z ${tango}. Testovací případy zahrnují ${acid} od Dmitry Baranovskiy, příklady z ${uforg} a ${testsuite}." 142 | 143 | msgid "footnote" 144 | msgstr "Nejedná se o validátor ve smyslu XML/SGML." 145 | 146 | msgid "sourceavailable" 147 | msgstr "Zdrojový kód je dostupný pod BSD licencí." 148 | -------------------------------------------------------------------------------- /locale/cs/LC_MESSAGES/props.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "POT-Creation-Date: \n" 5 | "PO-Revision-Date: \n" 6 | "Last-Translator: porneLReferer
"
81 |
82 | msgid "Bookmarklet"
83 | msgstr "Bookmarklet"
84 |
85 | msgid "restful"
86 | msgstr "RESTful JSON API"
87 |
88 | msgid "apidescription"
89 | msgstr "Send GET
request to ${url}.
Output will be roughly compatible with the ${validatornu}. Likely to change in the future.
" 91 | 92 | msgid "pleaseuseforvalidation" 93 | msgstr "Please use this API for validation, not just as an converter/extraction tool." 94 | 95 | msgid "Send Feedback" 96 | msgstr "Send Feedback" 97 | 98 | msgid "You can ${email} or the form below." 99 | msgstr "You can ${email} or the form below." 100 | 101 | msgid "feedbacknote" 102 | msgstr "If you're ${bug} or have a suggestion, don't forget to include example hCard code." 103 | 104 | msgid "feedbacknote_bug" 105 | msgstr "reporting a bug" 106 | 107 | msgid "Your name" 108 | msgstr "Your name" 109 | 110 | msgid "Your comment" 111 | msgstr "Your comment" 112 | 113 | msgid "Send feedback" 114 | msgstr "Send feedback" 115 | 116 | msgid "Result" 117 | msgstr "Result" 118 | 119 | msgid "valid" 120 | msgstr "Congratulations! No errors found." 121 | 122 | msgid "invalid" 123 | msgstr "This document contains errors." 124 | 125 | msgid "vcardnoerrors" 126 | msgstr "No issues found." 127 | 128 | msgid "More info" 129 | msgstr "More info" 130 | 131 | msgid "File source" 132 | msgstr "File source" 133 | 134 | msgid "Parsed source" 135 | msgstr "Parsed source" 136 | 137 | msgid "Credits" 138 | msgstr "Credits" 139 | 140 | msgid "fullcredits" 141 | msgstr "Written by ${writtenby}. Icons are from ${tango}. Test cases include ${acid} by Dmitry Baranovskiy, examples from ${uforg} and ${testsuite}." 142 | 143 | msgid "footnote" 144 | msgstr "It's not a validator in the XML/SGML sense." 145 | 146 | msgid "sourceavailable" 147 | msgstr "Source code is available under the BSD license." 148 | -------------------------------------------------------------------------------- /locale/en/LC_MESSAGES/props.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "POT-Creation-Date: \n" 5 | "PO-Revision-Date: \n" 6 | "Last-Translator: porneLEnvoyer la requête GET
à ${url}.
La sortie sera à peu près compatible avec la ${validatornu}. Susceptible de changer dans le futur.
" 91 | 92 | msgid "pleaseuseforvalidation" 93 | msgstr "S'il vous plaît utiliser l'API pour la validation, mais aussi comme un convertisseur/outil d'extraction." 94 | 95 | msgid "Send Feedback" 96 | msgstr "Envoyer un feedback" 97 | 98 | msgid "You can ${email} or the form below." 99 | msgstr "Vous pouvez ${email} ou utiliser le formulaire de contact." 100 | 101 | msgid "send feedback via e-mail" 102 | msgstr "envoyer un e-mail" 103 | 104 | msgid "feedbacknote" 105 | msgstr "Si vous rencontrez un ${bug} ou vous avez une suggestion, n'oubliez pas d'inclure le code de votre hCard." 106 | 107 | msgid "feedbacknote_bug" 108 | msgstr "rapporter un bug" 109 | 110 | msgid "Your name" 111 | msgstr "Votre nom" 112 | 113 | msgid "Your comment" 114 | msgstr "Votre commentaire" 115 | 116 | msgid "Send feedback" 117 | msgstr "Envoyer un feedback" 118 | 119 | msgid "Result" 120 | msgstr "Résultat" 121 | 122 | msgid "valid" 123 | msgstr "Félicitations! Aucune erreur trouvée." 124 | 125 | msgid "invalid" 126 | msgstr "Ce document contient des erreurs." 127 | 128 | msgid "vcardnoerrors" 129 | msgstr "Aucun problème détecté." 130 | 131 | msgid "More info" 132 | msgstr "En savoir plus" 133 | 134 | msgid "File source" 135 | msgstr "Fichier source" 136 | 137 | msgid "Parsed source" 138 | msgstr "Compiler la source" 139 | 140 | msgid "Credits" 141 | msgstr "Crédits" 142 | 143 | msgid "fullcredits" 144 | msgstr "Rédigé par ${writtenby}. Les icônes sont de ${tango}. Les tests inclus ${acid} par Dmitry Baranovskiy, exemples à partir de ${uforg} et ${testsuite}. Traduction par Axel Roche" 145 | 146 | msgid "footnote" 147 | msgstr "Ce n'est pas un validateur pour XML/SGML." 148 | 149 | msgid "sourceavailable" 150 | msgstr "Le code source est disponible, sous Licence BSD." 151 | 152 | -------------------------------------------------------------------------------- /locale/fr/LC_MESSAGES/props.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "POT-Creation-Date: \n" 5 | "PO-Revision-Date: \n" 6 | "Last-Translator: fdfReferer
"
81 |
82 | msgid "Bookmarklet"
83 | msgstr "Skryptozakładka"
84 |
85 | msgid "restful"
86 | msgstr "RESTowe API wysyłające JSON"
87 |
88 | msgid "URL to validate"
89 | msgstr "URL do sprawdzenia"
90 |
91 | msgid "apidescription"
92 | msgstr "Wyślij zapytanie GET
pod adres ${url}.
Wynik będzie w formacie z grubsza zgodnym z ${validatornu}. API może zmienić się w przyszłości.
" 94 | 95 | msgid "Validate hCards" 96 | msgstr "Sprawdź poprawność hCard" 97 | 98 | msgid "pleaseuseforvalidation" 99 | msgstr "Proszę używać API tylko do walidacji, a nie jako narzędzie do wyciągania wizytówek ze stron." 100 | 101 | msgid "Send Feedback" 102 | msgstr "Wyślij komentarz" 103 | 104 | msgid "send feedback via e-mail" 105 | msgstr "wysłać komentarz przez e-mail" 106 | 107 | msgid "feedbacknote" 108 | msgstr "Jeśli ${bug} lub masz sugestię, nie zapomnij dołączyć przykładowego kodu." 109 | 110 | msgid "feedbacknote_bug" 111 | msgstr "zgłaszasz błąd" 112 | 113 | msgid "You can ${email} or the form below." 114 | msgstr "Możesz ${email} lub użyć formularza poniżej." 115 | 116 | msgid "Your name" 117 | msgstr "Twoje imię" 118 | 119 | msgid "Your comment" 120 | msgstr "Komentarz" 121 | 122 | msgid "Send feedback" 123 | msgstr "Wyślij komentarz" 124 | 125 | msgid "Result" 126 | msgstr "Wynik" 127 | 128 | msgid "hCard #${n}" 129 | msgstr "hCard numer ${n}" 130 | 131 | msgid "valid" 132 | msgstr "Gratulacje! Nie znaleziono błędów." 133 | 134 | msgid "invalid" 135 | msgstr "Ten dokument zawiera błędy." 136 | 137 | msgid "vcardnoerrors" 138 | msgstr "Bez problemów." 139 | 140 | msgid "More info" 141 | msgstr "Więcej informacji" 142 | 143 | msgid "File source" 144 | msgstr "Źródło pliku" 145 | 146 | msgid "Parsed source" 147 | msgstr "Zinterpretowane źródło" 148 | 149 | msgid "Credits" 150 | msgstr "Twórcy" 151 | 152 | msgid "fullcredits" 153 | msgstr "Autorem walidatora jest ${writtenby}. Ikony pochodzą z ${tango}. Testowe pliki zawierają ${acid} Dmitriego Baranowskiego, a przykłady pochodzą z ${uforg} oraz ${testsuite}.
" 154 | 155 | msgid "footnote" 156 | msgstr "To nie jest walidacja w znaczeniu użytym w XML/SGML." 157 | 158 | msgid "sourceavailable" 159 | msgstr "Kod źródłowy jest dostępny na licencji BSD." 160 | 161 | msgid "(translations welcome!)" 162 | msgstr "(tłumaczenia mile widziane!)" 163 | 164 | msgid "Please write your feedback" 165 | msgstr "Proszę wpisać komentarz" 166 | 167 | msgid "Sending failed, sorry! Please e-mail your message instead." 168 | msgstr "Nie udało się wysłać wiadomości! Proszę wyślij ją przez e-mail." 169 | 170 | msgid "The message has been sent, thank you!" 171 | msgstr "Wiadomość została wysłana, dzięki!" 172 | -------------------------------------------------------------------------------- /locale/pl/LC_MESSAGES/props.po: -------------------------------------------------------------------------------- 1 | msgid "" 2 | msgstr "" 3 | "Project-Id-Version: \n" 4 | "POT-Creation-Date: \n" 5 | "PO-Revision-Date: \n" 6 | "Last-Translator: FalkaProceed. 15 | 20 |
Unable to validate — no referrer information received. 33 |
Proceed to the hCard Validator and enter the address manually.
34 | 2 | 3 |