getParser(); unset($msg); $this->parser = new DOMDocument('1.0', 'utf-8'); $this->parser->loadHTML(''); $this->rewrite( $parser->getElementsByTagName('body')->item(0), $this->parser->getElementsByTagName('body')->item(0) ); unset($parser); $this->parse( $this->parser->getElementsByTagName('body')->item(0) ); $this->html = strtr( (string)substr($this->parser->saveXML( $this->parser->getElementsByTagName('body')->item(0) ), 6, -7), array('/>' => '>') // Tak! GG nie lubi XML! ); } /** * Zwraca wiadomość zgodną z BotAPI Gadu-Gadu, którą można przekazać bezpośrednio do BotMastera * @param NULL|bool $img Czy dołączać obrazki? * @return string */ function getGG($image = NULL) { if($image === FALSE) { $image = ''; } elseif($image === TRUE) { $last = array_pop($this->images); if(count($this->images) > 0) { $push = new BotAPIGG(); foreach($this->images as $data) { $push->putImage($image[3]); } } $image = $last[2].file_get_contents($last[3]); } else { if(count($this->images) > 0) { $push = new BotAPIGG(); foreach($this->images as $image) { if(!$push->existsImage($image[2])) { $push->putImage($image[3]); } } } $image = ''; } $format = $this->getFormat(); return pack('VVVV', strlen($this->html)+1, strlen($this->old)+1, strlen($image), strlen($format)).$this->html."\0".$this->old."\0".$image.$format; } /** * Zwraca wiadomość zgodną z BotAPI Gadu-Gadu, którą można przekazać bezpośrednio do BotMastera * @return string */ function __toString() { return $this->getGG(); } /** * Zwraca wiadomość w formacie HTML przekonwertowaną tak, by zawierała jedynie dozwolone tagi. * @return string */ function getHTML() { return $this->html; } /** * Zwraca wiadomość jako tekst * @return string */ function getText() { return $this->old; } /** * Zwraca formatowanie wiadomości tekstowej zgodne z BotAPI Gadu-Gadu * @see BotMsgGG::getText() * @return string */ function getFormat() { if($this->format == '') { return ''; } else { return pack('Cv', 0x02, strlen($this->format)).$this->format; } } /** * Wyślij wiadomość na standardowe wyjście w sposób właściwy dla BotAPI */ function sendPullResponse() { header('Content-Type: application/x-gadu-gadu; charset=utf-8'); echo $this->getGG(); } private function rewrite($dom, $saveto, $top = TRUE) { if(!($dom instanceof DOMElement)) { throw new BotMsgException('Nieznany element DOM: '.get_class($dom)); } foreach($dom->childNodes as $node) { if($node instanceof DOMElement) { switch(strtolower($node->tagName)) { case 'b': case 'i': case 'u': case 'sup': case 'sub': case 'span': $tag = DOMHelper::cloneNode($node, $saveto); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); break; case 'strong': $tag = DOMHelper::cloneNode($node, $saveto, 'b'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); break; case 'script': case 'style': break; case 'p': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); DOMHelper::insertElement('br', $saveto); $tag = DOMHelper::cloneNode($node, $saveto, 'span'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); DOMHelper::insertElement('br', $saveto); DOMHelper::insertElement('br', $saveto); break; case 'a': $tag = DOMHelper::cloneNode($node, $saveto, 'span'); $this->rewrite($node, $tag, FALSE); if($node->getAttribute('href') != $node->textContent) { $tag->appendChild($tag->ownerDocument->createTextNode(' ('.$node->getAttribute('href').')')); } $saveto->appendChild($tag); break; case 'h1': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); DOMHelper::insertElement('br', $saveto); $tag = DOMHelper::cloneNode($node, $saveto, 'b'); $tag2 = $tag->ownerDocument->createElement('u'); $tag->appendChild($tag2); $this->rewrite($node, $tag2, FALSE); $saveto->appendChild($tag); DOMHelper::insertElement('br', $saveto); break; case 'h2': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); DOMHelper::insertElement('br', $saveto); $tag = DOMHelper::cloneNode($node, $saveto, 'b'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); DOMHelper::insertElement('br', $saveto); break; case 'h3': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); DOMHelper::insertElement('br', $saveto); $tag = DOMHelper::cloneNode($node, $saveto, 'b'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); DOMHelper::insertElement('br', $saveto); break; case 'ul': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); $tag = DOMHelper::cloneNode($node, $saveto, 'span'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); break; case 'ol': DOMHelper::rtrim($saveto); DOMHelper::insertElement('br', $saveto); if(!$node->hasAttribute('start') || !ctype_digit($node->getAttribute('start'))) { $node->setAttribute('start', 1); } $tag = DOMHelper::cloneNode($node, $saveto, 'span'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); break; case 'li': $tag = DOMHelper::cloneNode($node, $saveto, 'span'); if(strtolower($dom->tagName) == 'ul') { $tag->appendChild($tag->ownerDocument->createTextNode('- ')); } elseif(strtolower($dom->tagName) == 'ol') { $tag->appendChild($tag->ownerDocument->createTextNode($dom->getAttribute('start').'. ')); $dom->setAttribute('start', $dom->getAttribute('start')+1); } $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); $saveto->appendChild($saveto->ownerDocument->createElement('br')); break; case 'br': case 'img': $tag = DOMHelper::cloneNode($node, $saveto); $saveto->appendChild($tag); break; default: $tag = DOMHelper::cloneNode($node, $saveto, 'span'); $this->rewrite($node, $tag, FALSE); $saveto->appendChild($tag); break; } } elseif($node instanceof DOMText) { $val = strtr($node->nodeValue, array("\n" => '', "\r" => '')); if($val) { $saveto->appendChild($saveto->ownerDocument->createTextNode($val)); } } else { $saveto->appendChild($saveto->ownerDocument->importNode($node, TRUE)); } } if($top) { DOMHelper::trim($saveto); } foreach($saveto->childNodes as $node) { if(($node instanceof DOMElement) && $node->tagName == 'span' && $node->attributes->length == 0) { while($node->hasChildNodes()) { $node->parentNode->insertBefore($node->firstChild, $node); } $node->parentNode->removeChild($node); } } foreach($saveto->childNodes as $node) { if(($node instanceof DOMElement) && $node->hasAttribute('auto')) { $node->removeAttribute('auto'); } } } private function image($node) { if($node->hasAttribute('src')) { $src = $node->getAttribute('src'); $node->removeAttribute('src'); if(!is_file($src)) { return; } if(isset($this->images[$src])) { list($crc, $size, $name) = $this->images[$src]; } else { $size = filesize($src); if($size<0 || $size>262144) { return; } $crc = hash_file('crc32b', $src); $name = sprintf('%08s%08x', $crc, $size); $this->images[$src] = array($crc, $size, $name, $src); } $node->setAttribute('name', $name); $this->format .= pack('vC', mb_strlen($this->old), self::FORMAT_IMAGE) .pack('CCVV', 0x09, 0x01, $size, hexdec($crc)); $this->f_old = ''; } } private function format(&$node) { $node->setAttribute('beforeFormatType', dechex($this->f_type)); $node->setAttribute('beforeFormatColor', base64_encode($this->f_color)); if($node->hasAttribute('color')) { $color = trim($node->getAttribute('color')); if(substr($color, 0, 1)=='#' AND (strlen($color)==4 OR strlen($color)==7) AND ctype_xdigit(substr($color, 1))) { $node->setAttribute('style', 'color:'.$color.';'.$node->getAttribute('style')); $R = $G = $B = 0; if(strlen($color)==4) { $R = hexdec(str_repeat(substr($color, 1, 1), 2)); $G = hexdec(str_repeat(substr($color, 2, 1), 2)); $B = hexdec(str_repeat(substr($color, 3, 1), 2)); } else { $R = hexdec(substr($color, 1, 2)); $G = hexdec(substr($color, 3, 2)); $B = hexdec(substr($color, 5, 2)); } $this->f_color = chr($R).chr($G).chr($B); $this->f_type |= self::FORMAT_COLOR; } $node->removeAttribute('color'); } switch(strtolower($node->tagName)) { case 'b': $this->f_type |= self::FORMAT_BOLD; break; case 'i': $this->f_type |= self::FORMAT_ITALIC; break; case 'u': $this->f_type |= self::FORMAT_UNDERLINE; break; } } private function unformat($node) { $this->f_type = hexdec($node->getAttribute('beforeFormatType')); $node->removeAttribute('beforeFormatType'); $this->f_color = base64_decode($node->getAttribute('beforeFormatColor')); $node->removeAttribute('beforeFormatColor'); return TRUE; } private function cf() { $format = pack('C', $this->f_type).$this->f_color; if($this->f_old != $format) { $this->format .= pack('v', mb_strlen($this->old)).$format; $this->f_old = $format; } } private function parse($dom) { if(!($dom instanceof DOMElement)) { throw new BotMsgException('Nieznany element DOM: '.$dom); } foreach($dom->childNodes as $node) { if($node instanceof DOMText || $node instanceof DOMEntity) { $this->cf(); $this->old .= $node->nodeValue; } elseif($node instanceof DOMElement) { if($node->tagName == 'br') { $this->old .= "\r\n"; continue; } elseif($node->tagName == 'img') { $this->image($node); continue; } $this->format($node); $this->parse($node); $this->unformat($node); } else { throw new BotMsgException('Nieznany element DOM: '.$node); } } } } ?>