View Javadoc
1   // ////////////////////////////////////////////////////////////////////////////
2   // dexterIM - Instant Messaging Framework
3   // Copyright (C) 2003 Christoph Walcher
4   //
5   // This program is free software; you can redistribute it and/or modify
6   // it under the terms of the GNU General Public License as published by
7   // the Free Software Foundation; either version 2 of the License, or
8   // (at your option) any later version.
9   //
10  // This program is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  // GNU General Public License for more details.
14  //
15  // You should have received a copy of the GNU General Public License
16  // along with this program; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  //////////////////////////////////////////////////////////////////////////////
19  package net.sf.dexterim.oscar.client;
20  
21  import net.sf.dexterim.core.Account;
22  import net.sf.dexterim.core.Contact;
23  import net.sf.dexterim.oscar.BufferArray;
24  import net.sf.dexterim.oscar.OscarByteBuffer;
25  import net.sf.dexterim.oscar.entity.DWord;
26  import net.sf.dexterim.oscar.entity.QWord;
27  import net.sf.dexterim.oscar.entity.Snac;
28  import net.sf.dexterim.oscar.entity.TLV;
29  import net.sf.dexterim.oscar.entity.VariableByte;
30  import net.sf.dexterim.oscar.entity.Word;
31  
32  
33  /***
34   * @author christoph
35   *
36   */
37  public class SendMessageRequest extends Snac {
38  	private static final DWord MESSAGE_CHARSET = new DWord(0x0000);
39  	private static final DWord MESSAGE_LANGUAGE = new DWord(0xffff);
40  	
41  	public SendMessageRequest(Contact recipient, String message, boolean storeIfOffline, boolean requestAcknowledge) {
42  		super(0x0004, 0x0006, 0x0000);
43  		
44  		OscarByteBuffer buffer = OscarByteBuffer.dynamic();
45  		
46  		/*
47  		00 04   word   SNAC family 
48  		00 06   word   SNAC subtype 
49  		00 00   word   SNAC flags 
50  		xx xx xx xx   dword   SNAC request-id 
51  		 
52  		xx xx xx xx
53  		xx xx xx xx   qword   msg-id cookie 
54  		xx xx   word   message channel (see table below) 
55  		xx   byte   screenname string length 
56  		xx ..   string   screenname string 
57  		 
58  		*/
59  		buffer.write(new QWord(System.currentTimeMillis()));
60  		buffer.write(new Word(0x0001));
61  		
62  		VariableByte screenName = new VariableByte(recipient.getIdentity().toString());
63  		
64  		buffer.write((byte)screenName.getLength());
65  		buffer.write(screenName);
66  		
67  		TLV messageData = new TLV(0x0002);
68  
69  		OscarByteBuffer capsBuffer = createCapabilityFragment();
70  		OscarByteBuffer messageBuffer = createTextMessageFragment(message);
71  		
72  		OscarByteBuffer fragmentBuffer = BufferArray.createBufferArray(capsBuffer, messageBuffer);
73  		
74  		messageData.setData(fragmentBuffer.slice());
75  
76  		buffer.write(OscarByteBuffer.wrap(messageData.toByteArray()));
77  		
78  		if (requestAcknowledge) {
79  			TLV requestAckTLV = new TLV(0x03);
80  			
81  			buffer.write(OscarByteBuffer.wrap(requestAckTLV.toByteArray()));
82  		}
83  		
84  		if (storeIfOffline) {
85  			TLV offlineTLV = new TLV(0x06);
86  			
87  			buffer.write(OscarByteBuffer.wrap(offlineTLV.toByteArray()));
88  		}
89  		
90  		setData(buffer.slice());
91  	}
92  	
93  	/*** Creates the Capabilities Message Fragment. Only text capability is
94  	 * created.
95  	 * 05   byte   fragment identifier (array of required capabilities) 
96  	 * 01   byte   fragment version 
97  	 * xx xx   word   Length of rest data 
98  	 *
99  	 * xx ...   array   byte array of required capabilities (1 - text) 
100 	 */
101 	private OscarByteBuffer createCapabilityFragment() {
102 		OscarByteBuffer buffer = OscarByteBuffer.dynamic();
103 
104 		buffer.write((byte)0x05);
105 		buffer.write((byte)0x01);
106 		
107 		buffer.write((byte)0x00);
108 		buffer.write((byte)0x01);
109 		
110 		buffer.write((byte)0x01);
111 		
112 		return buffer;
113 	}
114 	
115 	/***
116 	 01   byte   fragment identifier (text message) 
117 	 01   byte   fragment version 
118 	 xx xx   word   Length of rest data 
119 	 
120 	 00 00   word   Message charset number 
121 	 ff ff   word   Message language number 
122 	 xx ..   string (ascii)   Message text string 
123 	 */
124 	private OscarByteBuffer createTextMessageFragment(String message) {
125 		OscarByteBuffer buffer = OscarByteBuffer.dynamic();
126 
127 		buffer.write((byte)0x01);
128 		buffer.write((byte)0x01);
129 		
130 		VariableByte byteMessage = new VariableByte(message);
131 		
132 		DWord length = new DWord(MESSAGE_CHARSET.getLength() + MESSAGE_LANGUAGE.getLength() + byteMessage.getLength());
133 		buffer.write(length);
134 		
135 		buffer.write(MESSAGE_CHARSET);
136 		buffer.write(MESSAGE_LANGUAGE);
137 		buffer.write(byteMessage);
138 		
139 		return buffer;
140 	}
141 }