1 /*
2  * This file is part of Licq, an instant messaging client for UNIX.
3  * Copyright (C) 2004-2013 Licq developers <licq-dev@googlegroups.com>
4  *
5  * Licq 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  * Licq 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 Licq; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19 
20 #include <cstdlib>
21 #include <cstring>
22 #include "msnbuffer.h"
23 
24 using namespace LicqMsn;
25 using std::list;
26 using std::string;
27 
CMSNBuffer(CMSNBuffer & b)28 CMSNBuffer::CMSNBuffer(CMSNBuffer &b)
29   : Licq::Buffer(b)
30 {
31   m_nDataSize = b.getDataMaxSize();
32   if (m_nDataSize)
33   {
34     m_pDataStart = new char[m_nDataSize];
35     memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
36   }
37   else
38   {
39     m_pDataStart = NULL;
40   }
41   m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
42   m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
43 }
44 
CMSNBuffer(Licq::Buffer & b)45 CMSNBuffer::CMSNBuffer(Licq::Buffer& b)
46 {
47   m_nDataSize = b.getDataMaxSize();
48   if (m_nDataSize)
49   {
50     m_pDataStart = new char[m_nDataSize];
51     memcpy(m_pDataStart, b.getDataStart(), m_nDataSize);
52   }
53   else
54   {
55     m_pDataStart = NULL;
56   }
57   m_pDataPosRead = m_pDataStart + (b.getDataPosRead() - b.getDataStart());
58   m_pDataPosWrite = m_pDataStart + (b.getDataPosWrite() - b.getDataStart());
59 }
60 
ParseHeaders()61 bool CMSNBuffer::ParseHeaders()
62 {
63   char ctmp = 0;
64   int counter = 0;
65   string stmp = "", strHeader, strData;
66   struct SHeader *pHeader = 0;
67 
68   if (m_lHeader.size() > 0)
69     ClearHeaders();
70 
71   while (!End())
72   {
73     *this >> ctmp;
74 
75     // Get header
76     while (ctmp != ':' && ctmp != '\r' && ctmp != 0)
77     {
78       stmp += ctmp;
79       *this >> ctmp;
80     }
81 
82     // Check for the end of the headers list
83     if (ctmp == '\r')
84     {
85       while (ctmp == '\r' || ctmp == '\n')
86       {
87         counter++;
88         *this >> ctmp;
89 
90         if (counter == 2)
91         {
92           setDataPosRead(getDataPosRead() - 1);
93           return true;
94         }
95       }
96 
97       counter = 0;
98     }
99 
100     *this >> ctmp; // skip ':'
101 
102     strHeader = stmp;
103     // Skip whitespace
104     while (ctmp == ' ' && ctmp != 0) *this >> ctmp;
105 
106     stmp = "";
107 
108     // Get data
109     while (ctmp != '\r' && ctmp != 0)
110     {
111       stmp += ctmp;
112       *this >> ctmp;
113     }
114 
115     // Finish the \n
116     *this >> ctmp;
117 
118     strData = stmp;
119     pHeader = new SHeader;
120 
121     if (!pHeader) return false;
122     pHeader->strHeader = strHeader;
123     pHeader->strValue = strData;
124     m_lHeader.push_back(pHeader);
125 
126     stmp = "";
127   }
128 
129   return true;
130 }
131 
GetValue(const string & strKey)132 string CMSNBuffer::GetValue(const string& strKey)
133 {
134   string strReturn = "";
135   list<SHeader *>::iterator it;
136   for (it = m_lHeader.begin(); it != m_lHeader.end(); it++)
137   {
138     if ((*it)->strHeader == strKey)
139     {
140       strReturn = (*it)->strValue;
141     }
142   }
143 
144   return strReturn;
145 }
146 
HasHeader(const string & strKey)147 bool CMSNBuffer::HasHeader(const string& strKey)
148 {
149   list<SHeader *>::iterator it;
150   for (it = m_lHeader.begin(); it != m_lHeader.end(); it++)
151   {
152     if ((*it)->strHeader == strKey)
153     {
154       return true;
155     }
156   }
157 
158   return false;
159 }
160 
ClearHeaders()161 void CMSNBuffer::ClearHeaders()
162 {
163   list<SHeader *>::iterator it;
164   for (it = m_lHeader.begin(); it != m_lHeader.end(); ++it)
165   {
166     if (*it)
167     {
168       delete *it;
169      *it = 0;
170     }
171   }
172   m_lHeader.clear();
173 }
174 
SkipParameter()175 void CMSNBuffer::SkipParameter()
176 {
177   char cCheck;
178   *this >> cCheck;
179 
180   if (isspace(cCheck))
181   {
182     // Leading space to next paramater
183     while (isspace(cCheck) && !End())
184       *this >> cCheck;
185   }
186 
187   // Now skip the paramater
188   while (!isspace(cCheck) && !End())
189     *this>> cCheck;
190 }
191 
SkipRN()192 void CMSNBuffer::SkipRN()
193 {
194   char cCheck;
195   *this >> cCheck;
196 
197   while ((cCheck == '\r' || cCheck == '\n') && !End())
198     *this >> cCheck;
199 
200   setDataPosRead(getDataPosRead() - 1);
201 }
202 
GetParameter()203 string CMSNBuffer::GetParameter()
204 {
205   char cCheck;
206   string strParam;
207   *this >> cCheck;
208 
209   if (cCheck == ' ')
210   {
211     while (cCheck == ' ' && !End())
212       *this >> cCheck;
213   }
214 
215   setDataPosRead(getDataPosRead() - 1);
216 
217   while (cCheck != ' ' && cCheck != '\r' && !End())
218   {
219     *this >> cCheck;
220     if (cCheck != ' ' && cCheck != '\r' && cCheck != '\n')
221       strParam += cCheck;
222   }
223 
224   return strParam;
225 }
226 
GetParameterUnsignedShort()227 unsigned short CMSNBuffer::GetParameterUnsignedShort()
228 {
229   string strValue = GetParameter();
230   unsigned short nValue = (unsigned short)atoi(strValue.c_str());
231   return nValue;
232 }
233 
GetParameterUnsignedLong()234 unsigned long CMSNBuffer::GetParameterUnsignedLong()
235 {
236   string strValue = GetParameter();
237   unsigned long nValue = strtoul(strValue.c_str(), (char **)NULL, 10);
238   return nValue;
239 }
SkipPacket()240 void CMSNBuffer::SkipPacket()
241 {
242   char cCheck = 0;
243 
244   while (cCheck != '\n' && !End())
245     *this >> cCheck;
246 }
247 
Skip(unsigned long _nSize)248 void CMSNBuffer::Skip(unsigned long _nSize)
249 {
250   incDataPosRead(_nSize);
251 }
252 
253