Home | History | Annotate | Download | only in xmpp
      1 /*
      2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/libjingle/xmpp/presencereceivetask.h"
     12 
     13 #include "webrtc/libjingle/xmpp/constants.h"
     14 #include "webrtc/base/stringencode.h"
     15 
     16 namespace buzz {
     17 
     18 static bool IsUtf8FirstByte(int c) {
     19   return (((c)&0x80)==0) || // is single byte
     20     ((unsigned char)((c)-0xc0)<0x3e); // or is lead byte
     21 }
     22 
     23 PresenceReceiveTask::PresenceReceiveTask(XmppTaskParentInterface* parent)
     24  : XmppTask(parent, XmppEngine::HL_TYPE) {
     25 }
     26 
     27 PresenceReceiveTask::~PresenceReceiveTask() {
     28   Stop();
     29 }
     30 
     31 int PresenceReceiveTask::ProcessStart() {
     32   const XmlElement * stanza = NextStanza();
     33   if (stanza == NULL) {
     34     return STATE_BLOCKED;
     35   }
     36 
     37   Jid from(stanza->Attr(QN_FROM));
     38   HandlePresence(from, stanza);
     39 
     40   return STATE_START;
     41 }
     42 
     43 bool PresenceReceiveTask::HandleStanza(const XmlElement * stanza) {
     44   // Verify that this is a presence stanze
     45   if (stanza->Name() != QN_PRESENCE) {
     46     return false; // not sure if this ever happens.
     47   }
     48 
     49   // Queue it up
     50   QueueStanza(stanza);
     51 
     52   return true;
     53 }
     54 
     55 void PresenceReceiveTask::HandlePresence(const Jid& from,
     56                                          const XmlElement* stanza) {
     57   if (stanza->Attr(QN_TYPE) == STR_ERROR) {
     58     return;
     59   }
     60 
     61   PresenceStatus status;
     62   DecodeStatus(from, stanza, &status);
     63   PresenceUpdate(status);
     64 }
     65 
     66 void PresenceReceiveTask::DecodeStatus(const Jid& from,
     67                                        const XmlElement* stanza,
     68                                        PresenceStatus* presence_status) {
     69   presence_status->set_jid(from);
     70   if (stanza->Attr(QN_TYPE) == STR_UNAVAILABLE) {
     71     presence_status->set_available(false);
     72   } else {
     73     presence_status->set_available(true);
     74     const XmlElement * status_elem = stanza->FirstNamed(QN_STATUS);
     75     if (status_elem != NULL) {
     76       presence_status->set_status(status_elem->BodyText());
     77 
     78       // Truncate status messages longer than 300 bytes
     79       if (presence_status->status().length() > 300) {
     80         size_t len = 300;
     81 
     82         // Be careful not to split legal utf-8 chars in half
     83         while (!IsUtf8FirstByte(presence_status->status()[len]) && len > 0) {
     84           len -= 1;
     85         }
     86         std::string truncated(presence_status->status(), 0, len);
     87         presence_status->set_status(truncated);
     88       }
     89     }
     90 
     91     const XmlElement * priority = stanza->FirstNamed(QN_PRIORITY);
     92     if (priority != NULL) {
     93       int pri;
     94       if (rtc::FromString(priority->BodyText(), &pri)) {
     95         presence_status->set_priority(pri);
     96       }
     97     }
     98 
     99     const XmlElement * show = stanza->FirstNamed(QN_SHOW);
    100     if (show == NULL || show->FirstChild() == NULL) {
    101       presence_status->set_show(PresenceStatus::SHOW_ONLINE);
    102     } else if (show->BodyText() == "away") {
    103       presence_status->set_show(PresenceStatus::SHOW_AWAY);
    104     } else if (show->BodyText() == "xa") {
    105       presence_status->set_show(PresenceStatus::SHOW_XA);
    106     } else if (show->BodyText() == "dnd") {
    107       presence_status->set_show(PresenceStatus::SHOW_DND);
    108     } else if (show->BodyText() == "chat") {
    109       presence_status->set_show(PresenceStatus::SHOW_CHAT);
    110     } else {
    111       presence_status->set_show(PresenceStatus::SHOW_ONLINE);
    112     }
    113 
    114     const XmlElement * caps = stanza->FirstNamed(QN_CAPS_C);
    115     if (caps != NULL) {
    116       std::string node = caps->Attr(QN_NODE);
    117       std::string ver = caps->Attr(QN_VER);
    118       std::string exts = caps->Attr(QN_EXT);
    119 
    120       presence_status->set_know_capabilities(true);
    121       presence_status->set_caps_node(node);
    122       presence_status->set_version(ver);
    123     }
    124 
    125     const XmlElement* delay = stanza->FirstNamed(kQnDelayX);
    126     if (delay != NULL) {
    127       // Ideally we would parse this according to the Psuedo ISO-8601 rules
    128       // that are laid out in JEP-0082:
    129       // http://www.jabber.org/jeps/jep-0082.html
    130       std::string stamp = delay->Attr(kQnStamp);
    131       presence_status->set_sent_time(stamp);
    132     }
    133 
    134     const XmlElement* nick = stanza->FirstNamed(QN_NICKNAME);
    135     if (nick) {
    136       presence_status->set_nick(nick->BodyText());
    137     }
    138   }
    139 }
    140 
    141 } // namespace buzz
    142