* @revision 03 * @license http://creativecommons.org/licenses/by-sa/2.0/de/ Creative Commons Attribution-Share Alike 2.0 Germany * @homepage http://oss.tiggerswelt.net/oscar/ * @copyright Copyright © 2008 tiggersWelt.net */ require_once ("oscar/writer.php"); class Oscar_TLV extends Oscar_Writer { public $Type = 0; public $Length = 0; public $Data = ""; // {{{ __construct /** * Contructor of TLV-Object * * @param object $Parent (optional) * @param int $Type (optional) * @param mixed $Data (optional) * * @access public * @return void */ public function __construct ($Parent = null, $Type = null, $Data = null) { parent::__construct ($Parent); // Check if we are the parent-class of someone else if (($Class = get_class ($this)) != __CLASS__) // Inherit Type-Value from subclass if (defined ($Class . "::TYPE") && ($Type == null)) $Type = constant ($Class . "::TYPE"); // Set predefined values if ($Type != null) $this->setValues ($Type, $Data); } // }}} // {{{ parseTLVBlock /** * Parse a tlvBlock as specified by official documentation * * @param string $Data * @param object $Parent (optional) Parent OSCAR-Object * @param bool $Truncate (optional) Truncate data from input * @param array $Prefered (optional) Set of prefered TLV-Types * * @access public * @return array */ public static function parseTLVBlock (&$Data, $Parent = null, $Truncate = true, $Prefered = array ()) { // Copy the input $buf = $Data; // Get count of TLV-Items $Count = Oscar_Common::str2int16 ($buf, 0, true); // Parse the TLVs $TLVs = array (); for ($i = 0; $i < $Count; $i++) $TLVs [] = self::trimTLV ($buf, $Parent, $Prefered); // Truncate the input if ($Truncate) $Data = $buf; return $TLVs; } // }}} // {{{ parseTLV /** * Parse a TLV-Object * * @param string $Data * @param object $Parent (optional) * @param array $Prefered (optional) * * @access public * @return object * @todo Find better classes */ public static function parseTLV ($Data, $Parent = null, $Prefered = array ()) { // Read the whole data $Type = Oscar_Common::str2int16 ($Data, 0, true); $Length = Oscar_Common::str2int16 ($Data, 0, true); $Data = substr ($Data, 0, $Length); // Find best class for this packet $Candidates = array (); $Classes = get_declared_classes (); $Class = __CLASS__; foreach ($Classes as $cClass) if (is_subclass_of ($cClass, __CLASS__) && defined ($c = $cClass . "::TYPE") && (constant ($c) == $Type)) $Candidates [] = $cClass; $bCandidates = array (); foreach ($Candidates as $Candidate) { $Class = $Candidate; if (in_array ($Candidate, $Prefered)) { // Check for a max-length restriction if (defined ($c = $Class . "::MAX_LENGTH") && (constant ($c) < $Length)) continue; $bCandidates [] = $Candidate; // Check for matching length if (defined ($c = $Class . "::LENGTH") && (constant ($c) == $Length)) { $bCandidates = array (); break; } } } // Repick best candidate if (count ($bCandidates) > 0) $Class = array_shift ($bCandidates); // Create new packet $Packet = new $Class ($Parent); $Packet->setValues ($Type, $Data); // Return the new class return $Packet; } // }}} // {{{ trimTLV /** * Parse a TLV and truncate Data from input * * @param string $Data * @param object $Parent (optional) * @param array $Prefered (optional) * * @access public * @return object */ public static function trimTLV (&$Data, &$Parent = null, $Prefered = array ()) { $Packet = self::parseTLV ($Data, $Parent, $Prefered); $Data = substr ($Data, 4 + $Packet->Length); return $Packet; } // }}} // {{{ parseTLVs /** * Parse more than one TLV * * @param string $Data * @param object $Parent (optional) * @param array $Prefered (optional) * * @access public * @return array */ public static function parseTLVs ($Data, $Parent = null, $Prefered = array ()) { $out = array (); while (($Data != "") && is_object ($Packet = self::trimTLV ($Data, $Parent, $Prefered))) $out [] = $Packet; return $out; } // }}} // {{{ parseBlock /** * Parse a Data of type tlvBlock * * @param string $Data * @param object $Parent (optional) Our parent handle * @param array $Prefered (optional) List of prefered TLV-Types * * @access public * @return array */ public static function parseBlock (&$Data, $Parent = null, $Prefered = array ()) { // Get Number of TLV-Elements $Count = Oscar_Common::str2int16 ($Data, 0, true); // Get the number of TLV-Elements $out = array (); for ($i = 0; $i < $Count; $i++) $out [] = self::trimTLV ($Data, $Parent, $Prefered); // Return our array return $out; } // }}} // {{{ setValues /** * Fill this object with values * * @param int $Type * @param string $Data * * @access public * @return void */ public function setValues ($Type, $Data) { $this->Type = $Type; $this->Data = $Data; $this->Length = strlen ($Data); // Try to parse data if (is_callable (array ($this, "parse")) && ($Data !== null)) $this->parse (); } // }}} // {{{ generate /** * Pack everything into a nice string * * @access public * @return string */ public function generate () { return Oscar_Common::int16tostr ($this->Type) . Oscar_Common::int16tostr (strlen ($this->Data)) . $this->Data; } // }}} public function toString () { return "TLV 0x" . dechex ($this->Type) . " aka " . get_class ($this) . " with length " . $this->Length . (is_a ($this, __CLASS__) && ($this->Length < 33) ? " " . bin2hex ($this->Data) : ""); } // {{{ classAdd /** * Add a class to a TLV-Class * * @param string $className Name of the TLV-Class * @param string $Class Name of the class to add * * @access public * @return void **/ public static function classAdd ($className, $Class) { global $TLV_CLASSES; if (!isset ($TLV_CLASSES) || !is_array ($TLV_CLASSES)) $TLV_CLASSES = array (); $cn = strtoupper ($className); $c = strtolower ($Class); if (!isset ($TLV_CLASSES [$cn])) $TLV_CLASSES [$cn] = array (); $TLV_CLASSES [$cn][$c] = $Class; } // }}} // {{{ getClass /** * Retrive Classes inside a named class * * @param string $className Name of the TLV-Class * * @access public * @return array **/ public static function getClass ($className) { global $TLV_CLASSES; if (!isset ($TLV_CLASSES) || !is_array ($TLV_CLASSES)) return array (); $cn = strtoupper ($className); if (!isset ($TLV_CLASSES [$cn])) return array (); return $TLV_CLASSES [$cn]; } // }}} } // Global TLV-Class-Storage $TLV_CLASSES = array (); // Obsolte BartID require_once ("oscar/tlv/bartid.php"); // New customized TLVs require_once ("oscar/tlv/events_supported.php"); require_once ("oscar/tlv/logon/cookie.php"); require_once ("oscar/tlv/logon/point.php"); require_once ("oscar/tlv/logon/error.php"); require_once ("oscar/tlv/logon/multicon.php"); require_once ("oscar/tlv/logon/clientname.php"); require_once ("oscar/tlv/logon/build.php"); require_once ("oscar/tlv/logon/username.php"); require_once ("oscar/tlv/logon/password.php"); require_once ("oscar/tlv/logon/minor.php"); require_once ("oscar/tlv/logon/major.php"); require_once ("oscar/tlv/logon/server.php"); require_once ("oscar/tlv/locate/capability.php"); require_once ("oscar/tlv/nickinfo/membersince.php"); require_once ("oscar/tlv/nickinfo/idletime.php"); require_once ("oscar/tlv/nickinfo/sigtime.php"); require_once ("oscar/tlv/nickinfo/nickflags.php"); require_once ("oscar/tlv/nickinfo/onlinetime.php"); require_once ("oscar/tlv/nickinfo/country.php"); require_once ("oscar/tlv/nickinfo/shortcaps.php"); require_once ("oscar/tlv/nickinfo/realip.php"); require_once ("oscar/tlv/nickinfo/signontime.php"); require_once ("oscar/tlv/nickinfo/awaytime.php"); require_once ("oscar/tlv/nickinfo/capability.php"); require_once ("oscar/tlv/nickinfo/feedtime.php"); require_once ("oscar/tlv/nickinfo/instancenum.php"); require_once ("oscar/tlv/nickinfo/bart.php"); require_once ("oscar/tlv/nickinfo/awaymsgtime.php"); require_once ("oscar/tlv/message/id.php"); require_once ("oscar/tlv/message/store.php"); require_once ("oscar/tlv/message/params.php"); require_once ("oscar/tlv/message/requestack.php"); require_once ("oscar/tlv/message/auto.php"); require_once ("oscar/tlv/message/bart.php"); require_once ("oscar/tlv/message/sendtime.php"); require_once ("oscar/tlv/rendezvous/verified_url.php"); require_once ("oscar/tlv/rendezvous/seen_ip.php"); require_once ("oscar/tlv/rendezvous/url.php"); require_once ("oscar/tlv/rendezvous/proposed_ip.php"); require_once ("oscar/tlv/rendezvous/port.php"); require_once ("oscar/tlv/rendezvous/cancel.php"); require_once ("oscar/tlv/rendezvous/channel.php"); require_once ("oscar/tlv/rendezvous/ip.php"); require_once ("oscar/tlv/rendezvous/sequence.php"); require_once ("oscar/tlv/rendezvous/request_check.php"); require_once ("oscar/tlv/rendezvous/ip_xor.php"); require_once ("oscar/tlv/rendezvous/port_xor.php"); require_once ("oscar/tlv/rendezvous/maxversion.php"); require_once ("oscar/tlv/rendezvous/servicedata.php"); require_once ("oscar/tlv/feedbag/pending.php"); require_once ("oscar/tlv/feedbag/interaction.php"); # TODO: Implement feedbags before 305 / 0x131 require_once ("oscar/tlv/feedbag/alias.php"); require_once ("oscar/tlv/feedbag/collapsed.php"); require_once ("oscar/tlv/feedbag/email.php"); require_once ("oscar/tlv/feedbag/phone.php"); require_once ("oscar/tlv/feedbag/cellphone.php"); require_once ("oscar/tlv/feedbag/sms.php"); require_once ("oscar/tlv/feedbag/note.php"); require_once ("oscar/tlv/feedbag/alertpreferences.php"); require_once ("oscar/tlv/feedbag/msgcount.php"); require_once ("oscar/tlv/feedbag/onlinetime.php"); require_once ("oscar/tlv/feedbag/amsgcount.php"); require_once ("oscar/tlv/feedbag/rmsgcount.php"); require_once ("oscar/tlv/feedbag/buddyfeed.php"); require_once ("oscar/tlv/feedbag/workphone.php"); require_once ("oscar/tlv/feedbag/otherphone.php"); require_once ("oscar/tlv/feedbag/pdmode.php"); require_once ("oscar/tlv/buddy/maxbuddies.php"); require_once ("oscar/tlv/buddy/maxwatchers.php"); require_once ("oscar/tlv/buddy/maxtemp.php"); require_once ("oscar/tlv/buddy/query.php"); require_once ("oscar/tlv/icqsrv/data.php"); // Our old TLVs require_once ("oscar/tlv/username.php"); // Tag 1 require_once ("oscar/tlv/userclass.php"); // Tag 1 require_once ("oscar/tlv/message.php"); // Tag 2 require_once ("oscar/tlv/signon.php"); // Tag 3 require_once ("oscar/tlv/unavailable_type.php"); // Tag 3 require_once ("oscar/tlv/idle.php"); // Tag 4 require_once ("oscar/tlv/unavailable_data.php"); // Tag 4 require_once ("oscar/tlv/registration.php"); // Tag 5 require_once ("oscar/tlv/rendezvous.php"); // Tag 5 require_once ("oscar/tlv/status.php"); // Tag 6 require_once ("oscar/tlv/ipaddr.php"); // Tag 10 require_once ("oscar/tlv/motd.php"); // Tag 11 require_once ("oscar/tlv/dc_info.php"); // Tag 12 require_once ("oscar/tlv/onlinetime.php"); // Tag 15 require_once ("oscar/tlv/email.php"); // Tag 17 require_once ("oscar/tlv/instances.php"); // Tag 20 require_once ("oscar/tlv/invite.php"); // Tag 21 require_once ("oscar/tlv/avatar.php"); // Tag 29 require_once ("oscar/tlv/ids.php"); // Tag 200 require_once ("oscar/tlv/privacy_setting.php"); // Tag 202 ?>