[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Dotgnu-libs-commits] CVS: dotgnu-base/DotGNU/Net/Jabber JabberMessage.c
From: |
Peter Minten <address@hidden> |
Subject: |
[Dotgnu-libs-commits] CVS: dotgnu-base/DotGNU/Net/Jabber JabberMessage.cs,NONE,1.1 JabberPresence.cs,NONE,1.1 JabberError.cs,NONE,1.1 JabberIQ.cs,NONE,1.1 JabberException.cs,NONE,1.1 |
Date: |
Sat, 28 Sep 2002 06:40:38 -0400 |
Update of /cvsroot/dotgnu-libs/dotgnu-base/DotGNU/Net/Jabber
In directory subversions:/tmp/cvs-serv11664/DotGNU/Net/Jabber
Added Files:
JabberMessage.cs JabberPresence.cs JabberError.cs JabberIQ.cs
JabberException.cs
Log Message:
Added Jabber classes
--- NEW FILE ---
/*
* JabberMessage.cs - A jabber message
*
* Copyright (C) 2002 Peter Minten
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace DotGNU.Net.Jabber
{
using DotGNU;
using System;
using System.IO;
using System.Text;
using System.Xml;
/// <remarks>A jabber message.</remarks>
public class JabberMessage
{
//This is a transformer class. It only exposes fields.
/// <summary>Constructs a message using the supplied XML
chunk.</summary>
/// <param name="chunk">The chunk of XML containing a jabber
message.</param>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
/// valid jabber message.</exception>
public JabberMessage (String chunk)
{
ParseXml(chunk); //The joy of dedicated methods :-)
}
/// <summary>Constructs a message using the supplied values.</summary>
/// <param name="new_to">The JID of the recipient. Optional, if omitted
the message
/// is interpreted by Jabber as being send to the sender.</param>
/// <param name="new_from">The JID of the sender. Optional, if omitted
the
/// JID of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</param>
/// <param name="new_id">An optional unique identifier. This may be
used for
/// tracking messages.</param>
/// <param name="new_type">The type of message. Optional, if omitted it
is set to normal.
/// This may be one of:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>normal</term>
/// <description>A simple single message.</description>
/// </item>
/// <item>
/// <term>chat</term>
/// <description>A message send in a one-to-one chat.</description>
/// </item>
/// <item>
/// <term>groupchat</term>
/// <description>A message send in a multi-user chat.</description>
/// </item>
/// <item>
/// <term>headline</term>
/// <description>A message that is of a list of items.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </param>
/// <param name="new_subject">A subject string. Optional. No mixed
content
/// allowed.</param>
/// <param name="new_thread">A random string used for indentifying
messages
/// in a thread. Optional. No mixed content allowed.</param>
/// <param name="new_body">The body of the message, no attributes
allowed.
/// Optional.</param>
/// <param name="new_error">If type is error this must be set.</param>
/// <param name="new_otherchild">A properly namespaced child element.
/// Optional. Use this for sending messages with custom content.
</param>
/// <exception cref="JabberException">A value was invalid.</exception>
public JabberMessage (String new_to, String new_from, String new_id,
String new_type, String
new_subject,
String new_thread,
String new_body,
JabberError new_error,
String new_otherchild)
{
//Checking code
CheckJID(new_to);
CheckJID(new_from);
CheckType(new_type);
//Assignment code
to = new_to;
from = new_from;
id = new_id;
type = new_type;
subject = new_subject;
thread = new_thread;
body = new_body;
error = new_error;
otherchild = new_otherchild;
}
//Attributes
///<value>The JID of the recipient. Optional, if omitted the message
/// is interpreted by Jabber as being send to the sender.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String To
{
get
{
return to;
}
set
{
CheckJID(value);
//No errors, carry on
to = value;
}
}
///<value>The JID of the sender. Optional, if omitted the JID
/// of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String From
{
get
{
return from;
}
set
{
CheckJID(value);
//No errors, carry on
from = value;
}
}
///<value>An optional unique identifier. This may be used for
/// tracking messages.</value>
public String Id
{
get
{
return id;
}
set
{
id = value;
}
}
///<value>The type of message. Optional, if omitted it is set to
normal.
/// This may be one of:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>normal</term>
/// <description>A simple single message.</description>
/// </item>
/// <item>
/// <term>chat</term>
/// <description>A message send in a one-to-one chat.</description>
/// </item>
/// <item>
/// <term>groupchat</term>
/// <description>A message send in a multi-user chat.</description>
/// </item>
/// <item>
/// <term>headline</term>
/// <description>A message that is of a list of items.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </value>
/// <exception cref="JabberException">Invalid type.</exception>
//Note: I could create a JabberMessageType enum for this, but that
//would require a translation to String everytime it is used. For
//the applications it doesn't matter very much if an enum or a string
//is used.
public String Type
{
get
{
return type;
}
set
{
CheckType(value);
//No errors, continue
type = value;
}
}
///<value>A subject string. Optional. No mixed content allowed.</value>
public String Subject
{
get
{
return subject;
}
set
{
//No checking
subject = value;
}
}
///<value>A random string used for indentifying messages in a thread.
/// Optional. No mixed content allowed.</value>
public String Thread
{
get
{
return thread;
}
set
{
thread = value;
}
}
///<value>If type is error this must be set.</value>
public JabberError Error
{
get
{
return error;
}
set
{
//Since JabberError has it's own checks don't check here
error = value;
}
}
///<value>The body of the message, no attributes allowed.
Optional.</value>
public String Body
{
get
{
return body;
}
set
{
body = value;
}
}
///<value>A properly namespaced child element. Optional. Use this for
/// sending messages with custom content. </value>
public String OtherChild
{
get
{
return otherchild;
}
set
{
otherchild = value;
}
}
//The XML chunk
///<value>The XML chunk this message represents.</value>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
/// valid jabber message.</exception>
public String Xml
{
get
{
return ComposeXml();
}
set
{
ParseXml(value);
}
}
//Private stuff follows
//Variables
//Since this class uses many many strings let's declare them
//all at once.
private String to, from, id, type, subject, thread, body, otherchild;
private JabberError error;
//Parse the given XML chunk, XmlException on incorrect Xml,
//JabberException on incorrect Jabber (no valid message).
private void ParseXml(String input)
{
//Construct an XmlTextReader with the standard settings
XmlTextReader tr = new XmlTextReader(input);
//Read the first node, EOF is not an option
if (tr.Read() == false)
{
throw new JabberException("Empty chunk");
}
//Node must be element
if (tr.NodeType != XmlNodeType.Element)
{
throw new JabberException("Chunk didn't start with an
element");
}
//Node must be message element
if (tr.Name != "message")
{
throw new JabberException("No presence element at top
level");
}
//Check if there are attributes and loop the attributes if so
if (tr.AttributeCount > 0)
{
for (int x = 0; x < tr.AttributeCount; x++)
{
//Move to the attribute
MoveToAttribute(x);
//Get name of attribute
String currname = tr.Name();
//Enter value into the right variable
switch(currname)
{
case "to":
//Check JID
CheckJID(tr.Value);
//No errors, continue
to = tr.Value;
break;
case "from":
//Check JID
CheckJID(tr.Value);
//No errors, continue
from = tr.Value;
break;
case "id":
//No restrictions here
id = tr.Value;
break;
case "type":
//Check if the type is valid
CheckType(tr.Value);
//No exception, it's valid
type = tr.Value();
break;
default:
//Invalid attribute
throw new
JabberException("Unknown attribute in message");
break;
}
}
//Last attribute parsed, move back to the element
tr.MoveToElement();
}
//Variable to avoid advancing the reader because the reader ha
//already been advanced
bool advance = true;
//Attributes are parsed, move on to the children
//If Depth becomes 1 the chunk is balanced and complete
while (tr.Depth > 1)
{
if (advance)
{
//Move to the next node, EOF is not an option
if (tr.Read() == false)
throw new JabberException("Unbalanced
message chunk");
}
else
{
advance = true;
}
//Everything under depth 2 is part of a child,
//so skip that stuff
if (tr.Depth == 2)
{
//Determine kind of child
switch (tr.Name)
{
case "body":
//No attributes allowed
if (tr.AttributeCount > 0)
throw new
JabberException
("Body of
message has attributes");
//Store the body content
body = tr.ReadElementString();
break;
case "subject":
//No attributes allowed
if (tr.AttributeCount > 0)
throw new
JabberException
("Subject of
message has attributes");
//Store the subject content
subject =
tr.ReadElementString();
break;
case "thread":
//No attributes allowed
if (tr.AttributeCount > 0)
throw new
JabberException
("Thread part
of message has attributes");
//Store the thread content
thread = tr.ReadElementString();
break;
case "error":
error = new
JabberError(tr.ReadOuterXml());
advance = false;
break;
default:
//This is an unknown child, I
hope it's valid,
//but I won't parse it
otherchild = tr.ReadOuterXml();
advance = false;
break;
}
}
}
}
//Compose an XML chunk
private String ComposeXml()
{
//Setup of the XML writer
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlTextWriter tw = new XmlTextWriter(sw);
//Write start element, I don't use namespaces here
tw.WriteStartElement(null, "message", null);
//Write attributes
if (to != null)
{
tw.WriteStartAttribute(null, "to", null);
tw.WriteString(to);
}
if (from != null)
{
tw.WriteStartAttribute(null, "from", null);
tw.WriteString(from);
}
if (id != null)
{
tw.WriteStartAttribute(null, "id", null);
tw.WriteString(id);
}
if (type != null)
{
tw.WriteStartAttribute(null, "type", null);
tw.WriteString(type);
}
//Write children
if (subject != null)
{
tw.WriteStartElement(null, "subject", null);
tw.WriteString(subject);
tw.WriteEndElement();
}
if (thread != null)
{
tw.WriteStartElement(null, "thread", null);
tw.WriteString(thread);
tw.WriteEndElement();
}
if (body != null)
{
tw.WriteStartElement(null, "body", null);
tw.WriteString(body);
tw.WriteEndElement();
}
tw.WriteRaw(otherchild);
if (type == "error")
{
tw.WriteRaw(error.Xml);
}
else
{
throw new JabberException
("Type is error but no error
child is supplied.");
}
//End chunk
tw.WriteEndElement();
//Close stream
tw.Close();
//Return value
return sb.ToString();
}
//Check if the given JID is correct
private void CheckJID(String input)
{
bool atused = false;
foreach (char c in input)
{
switch (c)
{
case 0x22: //"
case 0x27: //'
case 0x3C: //<
case 0x3E: //>
case 0x7F: //del
case 0xFFFE: //BOM
case 0xFFFF: //BOM
throw new JabberException("Invalid
character in JID");
break;
case 0x40: //@
//Has the @ sign been used before
if (atused)
throw new JabberException
("@ sign used more than
once in a JID");
else
atused = true;
break;
}
}
}
//Check if the given type is correct
private void CheckType(String input)
{
switch(input)
{
case "normal":
case "chat":
case "groupchat":
case "headline":
case "error":
//These are all correct
break;
default:
//Incorrect value
throw new JabberException("Invalid type value
in message");
break;
}
}
//Simple check for attribute validity
private void AttributeValid (String attr)
{
switch(attr)
{
case "to":
case "from":
case "id":
case "type":
break; //Do nothing
default:
throw new JabberException("Invalid attribute in
message XML");
break;
}
}
}; // class JabberMessage
}; // namespace DotGNU.Net.Jabber
--- NEW FILE ---
/*
* JabberPresence.cs - A jabber presence message
*
* Copyright (C) 2002 Peter Minten
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace DotGNU.Net.Jabber
{
using System;
using System.Xml;
/// <remarks>A jabber presence message.</remarks>
public class JabberPresence
{
//TODO: CONSTRUCTORS
/// <summary>Constructs a presence message using the supplied XML
chunk.</summary>
/// <param name="chunk">The chunk of XML containing a jabber presence
message.</param>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
//// valid jabber presence message.</exception>
public JabberPresence (String chunk)
{
ParseXml(chunk); //The joy of dedicated methods :-)
}
/// <summary>Constructs a message using the supplied values.</summary>
/// <param name="new_to">The JID of the recipient. Optional, if omitted
the message
/// is interpreted by Jabber as being send to the sender.</param>
/// <param name="new_from">The JID of the sender. Optional, if omitted
the
/// JID of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</param>
/// <param name="new_id">An optional unique identifier. This may be
used for
/// tracking messages.</param>
/// <param name="new_type">The type of presence message. Optional, if
omitted it is
/// set to normal. This may be one of:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>available</term>
/// <description>The entity is available for
communication.</description>
/// </item>
/// <item>
/// <term>unavailable</term>
/// <description>The entity is unavailable for
communication.</description>
/// </item>
/// <item>
/// <term>subscribe</term>
/// <description>The sender wants to subscribe to the receivers
/// presence.</description>
/// </item>
/// <item>
/// <term>subscribed</term>
/// <description>The sender allows the receiver to receive it's
/// presence.</description>
/// </item>
/// <item>
/// <term>unsubscribe</term>
/// <description>The sender has unsubscribed from the receivers
/// presence.</description>
/// </item>
/// <item>
/// <term>unsubscribed</term>
/// <description>Subscription request denied or previous
subscription
/// cancelled.</description>
/// </item>
/// <item>
/// <term>probe</term>
/// <description>A request for the receivers current
presence.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </param>
/// <param name="new_show">Describes an availability status.
/// Must be one of the following:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>away</term>
/// <description>The entity is temporarily away.</description>
/// </item>
/// <item>
/// <term>chat</term>
/// <description>The entity is free to chat.</description>
/// </item>
/// <item>
/// <term>xa</term>
/// <description>The entity is away for an extended period
/// (eXtended Away).</description>
/// </item>
/// <item>
/// <term>dnd</term>
/// <description>The entity is busy (Do Not Disturb).</description>
/// </item>
/// </list>
/// </param>
/// <param name="new_error">If type is error this must be set.</param>
/// <param name="new_otherchild">A properly namespaced child element.
/// Optional. Use this for sending messages with custom
content.</param>
/// <exception cref="JabberException">A value was invalid.</exception>
public JabberPresence (String new_to, String new_from, String new_id,
String new_type, String
new_show,
String new_status, uint
new_priority,
JabberError new_error,
String new_otherchild)
{
//Checking code
CheckJID(new_to);
CheckJID(new_from);
CheckType(new_type);
//Assignment code
to = new_to;
from = new_from;
id = new_id;
type = new_type;
//Invalid values are ignored
if (value == "away" || value == "chat"
|| value == "xa" || value == "dnd")
show = new_show;
status = new_status;
priority = new_priority;
error = new_error;
otherchild = new_otherchild;
}
//Attributes
///<value>The JID of the recipient. Optional, if omitted the message
/// is interpreted by Jabber as being send to the sender.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String To
{
get
{
return to;
}
set
{
CheckJID(value);
//No errors, carry on
to = value;
}
}
///<value>The JID of the sender. Optional, if omitted the JID
/// of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String From
{
get
{
return from;
}
set
{
CheckJID(value);
//No errors, carry on
from = value;
}
}
///<value>An optional unique identifier. This may be used for
/// tracking messages.</value>
public String Id
{
get
{
return id;
}
set
{
id = value;
}
}
///<value>The type of status/request/message. Optional, if omitted it
/// is set to available.
/// This may be one of:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>available</term>
/// <description>The entity is available for
communication.</description>
/// </item>
/// <item>
/// <term>unavailable</term>
/// <description>The entity is unavailable for
communication.</description>
/// </item>
/// <item>
/// <term>subscribe</term>
/// <description>The sender wants to subscribe to the receivers
/// presence.</description>
/// </item>
/// <item>
/// <term>subscribed</term>
/// <description>The sender allows the receiver to receive it's
/// presence.</description>
/// </item>
/// <item>
/// <term>unsubscribe</term>
/// <description>The sender has unsubscribed from the receivers
/// presence.</description>
/// </item>
/// <item>
/// <term>unsubscribed</term>
/// <description>Subscription request denied or previous subscription
/// cancelled.</description>
/// </item>
/// <item>
/// <term>probe</term>
/// <description>A request for the receivers current
presence.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </value>
//Note: I could create a JabberPresenceType enum for this, but that
//would require a translation to String everytime it is used. For
//the applications it doesn't matter very much if an enum or a string
//is used.
/// <exception cref="JabberException">Invalid type.</exception>
public String Type
{
get
{
return type;
}
set
{
CheckType(value);
//No errors, continue
type = value;
}
}
///<value>If type is error this must be set.</value>
public JabberError Error
{
get
{
return error;
}
set
{
//Since JabberError has it's own checks don't check here
error = value;
}
}
///<value>Describes an availability status. Must be one of the
following:
/// <list type="table">
/// <listheader>
/// <term>Value</term>
/// <description>Description</description>
/// </listheader>
/// <item>
/// <term>away</term>
/// <description>The entity is temporarily away.</description>
/// </item>
/// <item>
/// <term>chat</term>
/// <description>The entity is free to chat.</description>
/// </item>
/// <item>
/// <term>xa</term>
/// <description>The entity is away for an extended period
/// (eXtended Away).</description>
/// </item>
/// <item>
/// <term>dnd</term>
/// <description>The entity is busy (Do Not Disturb).</description>
/// </item>
/// </list>
///</value>
public String Show
{
get
{
return show;
}
set
{
//Invalid values are ignored
if (value == "away" || value == "chat" || value == "xa"
|| value == "dnd")
show = value;
}
}
///<value>A description of the availability status.</value>
public String Status
{
get
{
return status;
}
set
{
status = value;
}
}
///<value>An unsigned integer representing the priority level of
/// the connected resource, 0 is lowest priority.</value>
public uint Priority
{
get
{
return priority.ToString();
}
set
{
priority value;
}
}
///<value>A properly namespaced child element. Optional. Use this for
/// sending presence messages with custom content. </value>
public String OtherChild
{
get
{
return otherchild;
}
set
{
otherchild = value;
}
}
//TODO: CHILDREN
//Private stuff follows
//Variables
//Since this class uses many many strings let's declare them
//all at once.
private String to, from, id, type, show, status, otherchild;
private uint priority;
private JabberError error;
//Parse the given XML chunk, XmlException on incorrect Xml,
//JabberException on incorrect Jabber (no valid message).
private void ParseXml(String input)
{
//Construct an XmlTextReader with the standard settings
XmlTextReader tr = new XmlTextReader(input);
//Read the first node, EOF is not an option
if (tr.Read() == false)
{
throw new JabberException("Empty chunk");
}
//Node must be element
if (tr.NodeType != XmlNodeType.Element)
{
throw new JabberException("Chunk didn't start with an
element");
}
//Node must be presence element
if (tr.Name != "presence")
{
throw new JabberException("No presence element at top
level");
}
//Check if there are attributes and loop the attributes if so
if (tr.AttributeCount > 0)
{
for (int x = 0; x < tr.AttributeCount; x++)
{
//Move to the attribute
MoveToAttribute(x);
//Get name of attribute
String currname = tr.Name();
//Enter value into the right variable
switch(currname)
{
case "to":
//Check JID
CheckJID(tr.Value);
//No errors, continue
to = tr.Value;
break;
case "from":
//Check JID
CheckJID(tr.Value);
//No errors, continue
from = tr.Value;
break;
case "id":
//No restrictions here
id = tr.Value;
break;
case "type":
//Check if the type is valid
CheckType(tr.Value);
//No exception, it's valid
type = tr.Value();
break;
default:
//Invalid attribute
throw new
JabberException("Unknown attribute in presence message");
break;
}
}
//Last attribute parsed, move back to the element
tr.MoveToElement();
}
//Variable to avoid advancing the reader because the reader ha
//already been advanced
bool advance = true;
//Attributes are parsed, move on to the children
//If Depth becomes 1 the chunk is balanced and complete
while (tr.Depth > 1)
{
if (advance)
{
//Move to the next node, EOF is not an option
if (tr.Read() == false)
throw new JabberException("Unbalanced
message chunk");
}
else
{
advance = true;
}
//Everything under depth 2 is part of a child,
//so skip that stuff
if (tr.Depth == 2)
{
//Determine kind of child
switch (tr.Name)
{
case "show":
//Ignore invalid values
if (value == "away" || value ==
"chat" || value == "xa"
|| value == "dnd")
show =
tr.ReadElementString();
break;
case "status":
//Store the status content
status = tr.ReadElementString();
break;
case "priority":
//Store the priority content
priority =
uint.Parse(tr.ReadElementString());
break;
case "error":
error = new
JabberError(tr.ReadOuterXml());
advance = false;
break;
default:
//This is an unknown child, I
hope it's valid,
//but I won't parse it
otherchild = tr.ReadOuterXml();
advance = false;
break;
}
}
}
}
//Compose an XML chunk
private String ComposeXml()
{
//Setup of the XML writer
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlTextWriter tw = new XmlTextWriter(sw);
//Write start element, I don't use namespaces here
tw.WriteStartElement(null, "presence", null);
//Write attributes
if (to != null)
{
tw.WriteStartAttribute(null, "to", null);
tw.WriteString(to);
}
if (from != null)
{
tw.WriteStartAttribute(null, "from", null);
tw.WriteString(from);
}
if (id != null)
{
tw.WriteStartAttribute(null, "id", null);
tw.WriteString(id);
}
if (type != null)
{
tw.WriteStartAttribute(null, "type", null);
tw.WriteString(type);
}
//Write children
if (show != null)
{
tw.WriteStartElement(null, "show", null);
tw.WriteString(show);
tw.WriteEndElement();
}
if (status != null)
{
tw.WriteStartElement(null, "status", null);
tw.WriteString(status);
tw.WriteEndElement();
}
if (priority != null)
{
tw.WriteStartElement(null, "priority", null);
tw.WriteString(priority.ToString());
tw.WriteEndElement();
}
tw.WriteRaw(otherchild);
if (type == "error")
{
tw.WriteRaw(error.Xml);
}
else
{
throw new JabberException
("Type is error but no error
child is supplied.");
}
//End chunk
tw.WriteEndElement();
//Close stream
tw.Close();
//Return value
return sb.ToString();
}
//Check if the given JID is correct
private void CheckJID(String input)
{
bool atused = false;
foreach (char c in input)
{
switch (c)
{
case 0x22: //"
case 0x27: //'
case 0x3C: //<
case 0x3E: //>
case 0x7F: //del
case 0xFFFE: //BOM
case 0xFFFF: //BOM
throw new JabberException("Invalid
character in JID");
break;
case 0x40: //@
//Has the @ sign been used before
if (atused)
throw new JabberException
("@ sign used more than
once in a JID");
else
atused = true;
break;
}
}
}
//Check if the given type is correct
private void CheckType(String input)
{
switch(input)
{
case "available":
case "unavailable":
case "subscribe":
case "subscribed":
case "unsubscribe":
case "unsubscribed":
case "probe":
case "error":
//These are all correct
break;
default:
//Incorrect value
throw new JabberException("Invalid type value
in presence message");
break;
}
}
//Simple check for attribute validity
private void AttributeValid (String attr)
{
switch(attr)
{
case "to":
case "from":
case "id":
case "type":
break; //Do nothing
default:
throw new JabberException("Invalid attribute in
message XML");
break;
}
}
}; // class JabberPresence
}; // namespace DotGNU.Net.Jabber
--- NEW FILE ---
/*
* JabberError.cs - A jabber error message
*
* Copyright (C) 2002 Peter Minten
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace DotGNU.Net.Jabber
{
using DotGNU;
using System;
using System.Xml;
/// <remarks>A jabber error message.</remarks>
public class JabberError
{
//This is a transformer class. It only exposes fields.
/// <summary>Constructs a message using the supplied XML
chunk.</summary>
/// <param name="chunk">The chunk of XML containing a jabber
message.</param>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
//// valid jabber message.</exception>
public JabberError (String chunk)
{
ParseXml(chunk); //The joy of dedicated methods :-)
}
//Attributes
///<value>The number of the error.</value>
public String Number
{
get
{
return number;
}
set
{
//TODO: Check if the supplied value is valid
number = value;
}
}
///<value>A description of the error. Optional.</value>
public String Description
{
get
{
return description;
}
set
{
description = value;
}
}
//The XML chunk
///<value>The XML chunk this message represents.</value>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
//// valid jabber message.</exception>
public String Xml
{
get
{
return ComposeXml();
}
set
{
ParseXml();
}
}
//Private stuff follows
//Variables
//Since this class uses only strings let's declare them
//all at once.
private String number, description;
//Parse the given XML chunk, XmlException on incorrect Xml,
//JabberException on incorrect Jabber (no valid message).
private void ParseXml(String input)
{
//Construct an XmlTextReader with the standard settings
XmlTextReader tr = new XmlTextReader(input);
//Read the first node, EOF is not an option
if (tr.Read() == false)
{
throw new JabberException("Empty error part");
}
//Node must be element
//Can't be reached in normal circumstances
if (tr.NodeType != XmlNodeType.Element)
{
throw new JabberException
("Warning: unreachable part reached.");
}
//Check if a code attribute is supplied
if (tr["code"] == null)
throw new JabberException
("Error part of message has no code attribute");
//Assign value
//TODO: Check value for validity
number = tr["code"];
//If element has contents assign contents to description
if (!tr.IsEmptyElement)
description = tr.ReadInnerXml();
else
description = null;
//Operation done, I don't care if the error chunk is balanced
return;
}
//Compose an XML chunk
private String ComposeXml()
{
//Setup of the XML writer
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlTextWriter tw = new XmlTextWriter(sw);
//Write start element, I don't use namespaces here
tw.WriteStartElement(null, "error", null);
//Write code attribute
tw.WriteStartAttribute(null, "code", null);
tw.WriteString(code);
//Write description
if (description != null)
{
tw.WriteString(description);
}
//End chunk
tw.WriteEndElement();
//Close stream
tw.Close();
//Return value
return sb.ToString();
}
}; // class JabberError
}; // namespace DotGNU.Net.Jabber
--- NEW FILE ---
/*
* JabberIQ.cs - A jabber IQ message
*
* Copyright (C) 2002 Peter Minten
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace DotGNU.Net.Jabber
{
using DotGNU;
using System;
using System.IO;
using System.Text;
using System.Xml;
/// <remarks>A jabber message.</remarks>
public class JabberIQ
{
//This is a transformer class. It only exposes fields.
/// <summary>Constructs an IQ message using the supplied XML
chunk.</summary>
/// <param name="chunk">The chunk of XML containing a jabber
message.</param>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
/// valid jabber message.</exception>
public JabberIQ (String chunk)
{
ParseXml(chunk); //The joy of dedicated methods :-)
}
/// <summary>Constructs an IQ message using the supplied
values.</summary>
/// <param name="new_to">The JID of the recipient. Optional, if omitted
the message
/// is interpreted by Jabber as being send to the sender.</param>
/// <param name="new_from">The JID of the sender. Optional, if omitted
the
/// JID of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</param>
/// <param name="new_id">An optional unique identifier. This may be
used for
/// tracking messages.</param>
/// <param name="new_type">The type of IQ message.
/// This must be one of:
/// <list type="table">
/// <listheader>
/// <term>get</term>
/// <description>This request is a question.</description>
/// </listheader>
/// <item>
/// <term>set</term>
/// <description>This request sets values..</description>
/// </item>
/// <item>
/// <term>result</term>
/// <description>This IQ message contains the results of a
query.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </param>
/// <param name="new_subject">A subject string. Optional. No mixed
content
/// allowed.</param>
/// <param name="new_thread">A random string used for indentifying
messages
/// in a thread. Optional. No mixed content allowed.</param>
/// <param name="new_body">The body of the message, no attributes
allowed.
/// Optional.</param>
/// <param name="new_error">If type is error this must be set.</param>
/// <param name="new_child">A properly namespaced child element.
/// Optional.</param>
/// <exception cref="JabberException">A value was invalid.</exception>
public JabberIQ (String new_to, String new_from, String new_id,
String new_type,
JabberError new_error,
String new_child)
{
//Checking code
CheckJID(new_to);
CheckJID(new_from);
CheckType(new_type);
//Assignment code
to = new_to;
from = new_from;
id = new_id;
type = new_type;
error = new_error;
child = new_child;
}
//Attributes
///<value>The JID of the recipient. Optional, if omitted the message
/// is interpreted by Jabber as being send to the sender.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String To
{
get
{
return to;
}
set
{
CheckJID(value);
//No errors, carry on
to = value;
}
}
///<value>The JID of the sender. Optional, if omitted the JID
/// of the sender is filled in automatically. If set a check will
/// take place (by the jabber node relaying the message) that
/// the said JID matches that of the sender. So in general it's
/// best not to set this as this will prevent errors.</value>
/// <exception cref="JabberException">Invalid JID.</exception>
public String From
{
get
{
return from;
}
set
{
CheckJID(value);
//No errors, carry on
from = value;
}
}
///<value>An optional unique identifier. This may be used for
/// tracking messages.</value>
public String Id
{
get
{
return id;
}
set
{
id = value;
}
}
///<value>The type of IQ message.
/// This must be one of:
/// <list type="table">
/// <listheader>
/// <term>get</term>
/// <description>This request is a question.</description>
/// </listheader>
/// <item>
/// <term>set</term>
/// <description>This request sets values..</description>
/// </item>
/// <item>
/// <term>result</term>
/// <description>This IQ message contains the results of a
query.</description>
/// </item>
/// <item>
/// <term>error</term>
/// <description>An error message</description>
/// </item>
/// </list>
/// </value>
/// <exception cref="JabberException">Invalid type.</exception>
//Note: I could create a JabberIQType enum for this, but that
//would require a translation to String everytime it is used. For
//the applications it doesn't matter very much if an enum or a string
//is used.
public String Type
{
get
{
return type;
}
set
{
CheckType(value);
//No errors, continue
type = value;
}
}
///<value>If type is error this must be set.</value>
public JabberError Error
{
get
{
return error;
}
set
{
//Since JabberError has it's own checks don't check here
error = value;
}
}
///<value>A properly namespaced child element. Optional, though
/// you won't get very far if you don't specify this.</value>
public String Child
{
get
{
return child;
}
set
{
child = value;
}
}
//The XML chunk
///<value>The XML chunk this IQ message represents.</value>
/// <exception cref="XmlException">The XML was invalid.</exception>
/// <exception cref="JabberException">The XML didn't contain a
/// valid jabber message.</exception>
public String Xml
{
get
{
return ComposeXml();
}
set
{
ParseXml(value);
}
}
//Private stuff follows
//Variables
//Since this class uses many many strings let's declare them
//all at once.
private String to, from, id, type, subject, thread, body, child;
private JabberError error;
//Parse the given XML chunk, XmlException on incorrect Xml,
//JabberException on incorrect Jabber (no valid message).
private void ParseXml(String input)
{
//Construct an XmlTextReader with the standard settings
XmlTextReader tr = new XmlTextReader(input);
//Read the first node, EOF is not an option
if (tr.Read() == false)
{
throw new JabberException("Empty chunk");
}
//Node must be element
if (tr.NodeType != XmlNodeType.Element)
{
throw new JabberException("Chunk didn't start with an
element");
}
//Node must be message element
if (tr.Name != "message")
{
throw new JabberException("No presence element at top
level");
}
//Check if there are attributes and loop the attributes if so
if (tr.AttributeCount > 0)
{
for (int x = 0; x < tr.AttributeCount; x++)
{
//Move to the attribute
MoveToAttribute(x);
//Get name of attribute
String currname = tr.Name();
//Enter value into the right variable
switch(currname)
{
case "to":
//Check JID
CheckJID(tr.Value);
//No errors, continue
to = tr.Value;
break;
case "from":
//Check JID
CheckJID(tr.Value);
//No errors, continue
from = tr.Value;
break;
case "id":
//No restrictions here
id = tr.Value;
break;
case "type":
//Check if the type is valid
CheckType(tr.Value);
//No exception, it's valid
type = tr.Value();
break;
default:
//Invalid attribute
throw new
JabberException("Unknown attribute in message");
break;
}
}
//Last attribute parsed, move back to the element
tr.MoveToElement();
}
//Variable to avoid advancing the reader because the reader ha
//already been advanced
bool advance = true;
//Attributes are parsed, move on to the children
//If Depth becomes 1 the chunk is balanced and complete
while (tr.Depth > 1)
{
if (advance)
{
//Move to the next node, EOF is not an option
if (tr.Read() == false)
throw new JabberException("Unbalanced
message chunk");
}
else
{
advance = true;
}
//Everything under depth 2 is part of a child,
//so skip that stuff
if (tr.Depth == 2)
{
//Determine kind of child
switch (tr.Name)
{
case "error":
error = new
JabberError(tr.ReadOuterXml());
advance = false;
break;
default:
//This is an unknown child, I
hope it's valid,
//but I won't parse it
child = tr.ReadOuterXml();
advance = false;
break;
}
}
}
}
//Compose an XML chunk
private String ComposeXml()
{
//Setup of the XML writer
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
XmlTextWriter tw = new XmlTextWriter(sw);
//Write start element, I don't use namespaces here
tw.WriteStartElement(null, "message", null);
//Write attributes
if (to != null)
{
tw.WriteStartAttribute(null, "to", null);
tw.WriteString(to);
}
if (from != null)
{
tw.WriteStartAttribute(null, "from", null);
tw.WriteString(from);
}
if (id != null)
{
tw.WriteStartAttribute(null, "id", null);
tw.WriteString(id);
}
if (type != null)
{
tw.WriteStartAttribute(null, "type", null);
tw.WriteString(type);
}
//Write children
tw.WriteRaw(child);
if (type == "error")
{
tw.WriteRaw(error.Xml);
}
else
{
throw new JabberException
("Type is error but no error
child is supplied.");
}
//End chunk
tw.WriteEndElement();
//Close stream
tw.Close();
//Return value
return sb.ToString();
}
//Check if the given JID is correct
private void CheckJID(String input)
{
bool atused = false;
foreach (char c in input)
{
switch (c)
{
case 0x22: //"
case 0x27: //'
case 0x3C: //<
case 0x3E: //>
case 0x7F: //del
case 0xFFFE: //BOM
case 0xFFFF: //BOM
throw new JabberException("Invalid
character in JID");
break;
case 0x40: //@
//Has the @ sign been used before
if (atused)
throw new JabberException
("@ sign used more than
once in a JID");
else
atused = true;
break;
}
}
}
//Check if the given type is correct
private void CheckType(String input)
{
switch(input)
{
case "get":
case "set":
case "result":
case "error":
//These are all correct
break;
default:
//Incorrect value
throw new JabberException("Invalid type value
in IQ message");
break;
}
}
//Simple check for attribute validity
private void AttributeValid (String attr)
{
switch(attr)
{
case "to":
case "from":
case "id":
case "type":
break; //Do nothing
default:
throw new JabberException("Invalid attribute in
IQ XML");
break;
}
}
}; // class JabberIQ
}; // namespace DotGNU.Net.Jabber
--- NEW FILE ---
/*
* JabberException.cs - A jabber exception
*
* Copyright (C) 2002 Peter Minten
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
namespace DotGNU.Net.Jabber
{
using System;
using System.Xml;
/// <remarks>A jabber exception.</remarks>
public class JabberException : Exception
{
private const String stdmessage = "Somethings rotten in your code.";
//This is a transformer class. It only exposes fields.
/// <summary>Constructs a JabberException with the standard error
string.</summary>
/// <param name="chunk">The chunk of XML containing a jabber
JabberException.</param>
public JabberException() : base(stdmessage) {}
/// <summary>Constructs a JabberException with the supplied error
string.</summary>
/// <param name="errorString">The error string.</param>
public JabberException(String errorString) : base(errorString){}
/// <summary>Constructs a JabberException with the supplied error
string
/// and inner exception.</summary>
/// <param name="errorString">The error string.</param>
/// <param name="inner">The inner exception.</param>
public JabberException(String errorString, Exception inner)
: base(errorString, inner){}
///<value>The error string.</value>
public override String Message
{
get
{
String msgpar = base.Message;
if (msgpar == null)
return stdmessage;
else
return msgpar;
}
}
}; // class JabberException
}; // namespace DotGNU.Net.Jabber
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Dotgnu-libs-commits] CVS: dotgnu-base/DotGNU/Net/Jabber JabberMessage.cs,NONE,1.1 JabberPresence.cs,NONE,1.1 JabberError.cs,NONE,1.1 JabberIQ.cs,NONE,1.1 JabberException.cs,NONE,1.1,
Peter Minten <address@hidden> <=