gloox  1.0.28
registration.cpp
1 /*
2  Copyright (c) 2005-2023 by Jakob Schröter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 #include "registration.h"
15 
16 #include "clientbase.h"
17 #include "stanza.h"
18 #include "error.h"
19 #include "prep.h"
20 #include "oob.h"
21 
22 namespace gloox
23 {
24 
25  // Registration::Query ----
27  : StanzaExtension( ExtRegistration ), m_form( form ), m_fields( 0 ), m_oob( 0 ),
28  m_del( false ), m_reg( false )
29  {
30  }
31 
33  : StanzaExtension( ExtRegistration ), m_form( 0 ), m_fields( 0 ), m_oob( 0 ), m_del( del ),
34  m_reg( false )
35  {
36  }
37 
38  Registration::Query::Query( int fields, const RegistrationFields& values )
39  : StanzaExtension( ExtRegistration ), m_form( 0 ), m_fields( fields ), m_values( values ),
40  m_oob( 0 ), m_del( false ), m_reg( false )
41  {
42  }
43 
45  : StanzaExtension( ExtRegistration ), m_form( 0 ), m_fields( 0 ), m_oob( 0 ), m_del( false ),
46  m_reg( false )
47  {
48  if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_REGISTER )
49  return;
50 
51  const TagList& l = tag->children();
52  TagList::const_iterator it = l.begin();
53  for( ; it != l.end(); ++it )
54  {
55  const std::string& name = (*it)->name();
56  if( name == "instructions" )
57  m_instructions = (*it)->cdata();
58  else if( name == "remove" )
59  m_del = true;
60  else if( name == "registered" )
61  m_reg = true;
62  else if( name == "username" )
63  {
64  m_fields |= FieldUsername;
65  m_values.username = (*it)->cdata();
66  }
67  else if( name == "nick" )
68  {
69  m_fields |= FieldNick;
70  m_values.nick = (*it)->cdata();
71  }
72  else if( name == "password" )
73  {
74  m_fields |= FieldPassword;
75  m_values.password = (*it)->cdata();
76  }
77  else if( name == "name" )
78  {
79  m_fields |= FieldName;
80  m_values.name = (*it)->cdata();
81  }
82  else if( name == "first" )
83  {
84  m_fields |= FieldFirst;
85  m_values.first = (*it)->cdata();
86  }
87  else if( name == "last" )
88  {
89  m_fields |= FieldLast;
90  m_values.last = (*it)->cdata();
91  }
92  else if( name == "email" )
93  {
94  m_fields |= FieldEmail;
95  m_values.email = (*it)->cdata();
96  }
97  else if( name == "address" )
98  {
99  m_fields |= FieldAddress;
100  m_values.address = (*it)->cdata();
101  }
102  else if( name == "city" )
103  {
104  m_fields |= FieldCity;
105  m_values.city = (*it)->cdata();
106  }
107  else if( name == "state" )
108  {
109  m_fields |= FieldState;
110  m_values.state = (*it)->cdata();
111  }
112  else if( name == "zip" )
113  {
114  m_fields |= FieldZip;
115  m_values.zip = (*it)->cdata();
116  }
117  else if( name == "phone" )
118  {
119  m_fields |= FieldPhone;
120  m_values.phone = (*it)->cdata();
121  }
122  else if( name == "url" )
123  {
124  m_fields |= FieldUrl;
125  m_values.url = (*it)->cdata();
126  }
127  else if( name == "date" )
128  {
129  m_fields |= FieldDate;
130  m_values.date = (*it)->cdata();
131  }
132  else if( name == "misc" )
133  {
134  m_fields |= FieldMisc;
135  m_values.misc = (*it)->cdata();
136  }
137  else if( name == "text" )
138  {
139  m_fields |= FieldText;
140  m_values.text = (*it)->cdata();
141  }
142  else if( !m_form && name == "x" && (*it)->xmlns() == XMLNS_X_DATA )
143  m_form = new DataForm( (*it) );
144  else if( !m_oob && name == "x" && (*it)->xmlns() == XMLNS_X_OOB )
145  m_oob = new OOB( (*it) );
146  }
147  }
148 
150  {
151  delete m_form;
152  delete m_oob;
153  }
154 
155  const std::string& Registration::Query::filterString() const
156  {
157  static const std::string filter = "/iq/query[@xmlns='" + XMLNS_REGISTER + "']";
158  return filter;
159  }
160 
162  {
163  Tag* t = new Tag( "query" );
164  t->setXmlns( XMLNS_REGISTER );
165 
166  if( !m_instructions.empty() )
167  new Tag( t, "instructions", m_instructions );
168 
169  if ( m_reg )
170  new Tag( t, "registered" );
171 
172  if( m_form )
173  t->addChild( m_form->tag() );
174  else if( m_oob )
175  t->addChild( m_oob->tag() );
176  else if( m_del )
177  new Tag( t, "remove" );
178  else if( m_fields )
179  {
180  if( m_fields & FieldUsername )
181  new Tag( t, "username", m_values.username );
182  if( m_fields & FieldNick )
183  new Tag( t, "nick", m_values.nick );
184  if( m_fields & FieldPassword )
185  new Tag( t, "password", m_values.password );
186  if( m_fields & FieldName )
187  new Tag( t, "name", m_values.name );
188  if( m_fields & FieldFirst )
189  new Tag( t, "first", m_values.first );
190  if( m_fields & FieldLast )
191  new Tag( t, "last", m_values.last );
192  if( m_fields & FieldEmail )
193  new Tag( t, "email", m_values.email );
194  if( m_fields & FieldAddress )
195  new Tag( t, "address", m_values.address );
196  if( m_fields & FieldCity )
197  new Tag( t, "city", m_values.city );
198  if( m_fields & FieldState )
199  new Tag( t, "state", m_values.state );
200  if( m_fields & FieldZip )
201  new Tag( t, "zip", m_values.zip );
202  if( m_fields & FieldPhone )
203  new Tag( t, "phone", m_values.phone );
204  if( m_fields & FieldUrl )
205  new Tag( t, "url", m_values.url );
206  if( m_fields & FieldDate )
207  new Tag( t, "date", m_values.date );
208  if( m_fields & FieldMisc )
209  new Tag( t, "misc", m_values.misc );
210  if( m_fields & FieldText )
211  new Tag( t, "text", m_values.text );
212  }
213 
214  return t;
215  }
216  // ---- ~Registration::Query ----
217 
218  // ---- Registration ----
220  : m_parent( parent ), m_to( to ), m_registrationHandler( 0 )
221  {
222  init();
223  }
224 
226  : m_parent( parent ), m_registrationHandler( 0 )
227  {
228  init();
229  }
230 
231  void Registration::init()
232  {
233  if( m_parent )
234  {
235  m_parent->registerIqHandler( this, ExtRegistration );
236  m_parent->registerStanzaExtension( new Query() );
237  }
238  }
239 
241  {
242  if( m_parent )
243  {
244  m_parent->removeIqHandler( this, ExtRegistration );
245  m_parent->removeIDHandler( this );
247  }
248  }
249 
251  {
252  if( !m_parent || m_parent->state() != StateConnected )
253  return;
254 
255  IQ iq( IQ::Get, m_to );
256  iq.addExtension( new Query() );
257  m_parent->send( iq, this, FetchRegistrationFields );
258  }
259 
260  bool Registration::createAccount( int fields, const RegistrationFields& values )
261  {
262  std::string username;
263  if( !m_parent || !prep::nodeprep( values.username, username ) )
264  return false;
265 
266  IQ iq( IQ::Set, m_to );
267  iq.addExtension( new Query( fields, values ) );
268  m_parent->send( iq, this, CreateAccount );
269 
270  return true;
271  }
272 
274  {
275  if( !m_parent || !form )
276  return;
277 
278  IQ iq( IQ::Set, m_to );
279  iq.addExtension( new Query( form ) );
280  m_parent->send( iq, this, CreateAccount );
281  }
282 
284  {
285  if( !m_parent || !m_parent->authed() )
286  return;
287 
288  IQ iq( IQ::Set, m_to );
289  iq.addExtension( new Query( true ) );
290  m_parent->send( iq, this, RemoveAccount );
291  }
292 
293  void Registration::changePassword( const std::string& username, const std::string& password )
294  {
295  if( !m_parent || !m_parent->authed() || username.empty() )
296  return;
297 
298  int fields = FieldUsername | FieldPassword;
300  rf.username = username;
301  rf.password = password;
302  createAccount( fields, rf );
303  }
304 
306  {
307  m_registrationHandler = rh;
308  }
309 
311  {
312  m_registrationHandler = 0;
313  }
314 
315  void Registration::handleIqID( const IQ& iq, int context )
316  {
317  if( !m_registrationHandler )
318  return;
319 
320  if( iq.subtype() == IQ::Result )
321  {
322  switch( context )
323  {
324  case FetchRegistrationFields:
325  {
326  const Query* q = iq.findExtension<Query>( ExtRegistration );
327  if( !q )
328  return;
329 
330  if( q->registered() )
331  m_registrationHandler->handleAlreadyRegistered( iq.from() );
332 
333  if( q->form() )
334  m_registrationHandler->handleDataForm( iq.from(), *(q->form()) );
335 
336  if( q->oob() )
337  m_registrationHandler->handleOOB( iq.from(), *(q->oob()) );
338 
339  m_registrationHandler->handleRegistrationFields( iq.from(), q->fields(), q->instructions() );
340  break;
341  }
342 
343  case CreateAccount:
344  case ChangePassword:
345  case RemoveAccount:
346  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationSuccess );
347  break;
348  }
349  }
350  else if( iq.subtype() == IQ::Error )
351  {
352  const Error* e = iq.error();
353  if( !e )
354  return;
355 
356  switch( e->error() )
357  {
358  case StanzaErrorConflict:
359  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationConflict );
360  break;
362  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationNotAcceptable );
363  break;
365  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationBadRequest );
366  break;
368  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationForbidden );
369  break;
371  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationRequired );
372  break;
374  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationUnexpectedRequest );
375  break;
377  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationNotAuthorized );
378  break;
380  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationNotAllowed );
381  break;
383  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationConstraint );
384  break;
385  default:
386  m_registrationHandler->handleRegistrationResult( iq.from(), RegistrationUnknownError );
387  break;
388 
389  }
390  }
391 
392  }
393 
394 }
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition: clientbase.h:79
ConnectionState state() const
void removeIqHandler(IqHandler *ih, int exttype)
void removeIDHandler(IqHandler *ih)
bool removeStanzaExtension(int ext)
void send(Tag *tag)
void registerIqHandler(IqHandler *ih, int exttype)
void registerStanzaExtension(StanzaExtension *ext)
bool authed() const
Definition: clientbase.h:290
An abstraction of a XEP-0004 Data Form.
Definition: dataform.h:57
A stanza error abstraction implemented as a StanzaExtension.
Definition: error.h:35
StanzaError error() const
Definition: error.h:75
An abstraction of an IQ stanza.
Definition: iq.h:34
IqType subtype() const
Definition: iq.h:74
@ Set
Definition: iq.h:46
@ Error
Definition: iq.h:49
@ Result
Definition: iq.h:48
@ Get
Definition: iq.h:45
An abstraction of a JID.
Definition: jid.h:31
This is an abstraction of a jabber:x:oob namespace element or a jabber:iq:oob namespace element as sp...
Definition: oob.h:36
A virtual interface that receives events from an Registration object.
virtual void handleDataForm(const JID &from, const DataForm &form)=0
virtual void handleAlreadyRegistered(const JID &from)=0
virtual void handleOOB(const JID &from, const OOB &oob)=0
virtual void handleRegistrationResult(const JID &from, RegistrationResult regResult)=0
virtual void handleRegistrationFields(const JID &from, int fields, std::string instructions)=0
A wrapping class for the XEP-0077 <query> element.
Definition: registration.h:126
const std::string & instructions() const
Definition: registration.h:169
const DataForm * form() const
Definition: registration.h:163
virtual const std::string & filterString() const
const OOB * oob() const
Definition: registration.h:198
virtual Tag * tag() const
void changePassword(const std::string &username, const std::string &password)
virtual void handleIqID(const IQ &iq, int context)
void removeRegistrationHandler()
void registerRegistrationHandler(RegistrationHandler *rh)
bool createAccount(int fields, const RegistrationFields &values)
Registration(ClientBase *parent, const JID &to)
This class abstracts a stanza extension, which is usually an XML child element in a specific namespac...
void addExtension(const StanzaExtension *se)
Definition: stanza.cpp:52
const Error * error() const
Definition: stanza.cpp:47
const JID & from() const
Definition: stanza.h:51
const StanzaExtension * findExtension(int type) const
Definition: stanza.cpp:57
This is an abstraction of an XML element.
Definition: tag.h:47
const std::string xmlns() const
Definition: tag.cpp:543
void addChild(Tag *child)
Definition: tag.cpp:424
const std::string & name() const
Definition: tag.h:394
const TagList & children() const
Definition: tag.cpp:510
bool setXmlns(const std::string &xmlns, const std::string &prefix=EmptyString)
Definition: tag.cpp:522
bool nodeprep(const std::string &node, std::string &out)
Definition: prep.cpp:59
The namespace for the gloox library.
Definition: adhoc.cpp:28
std::list< Tag * > TagList
Definition: tag.h:26
@ RegistrationUnknownError
@ RegistrationForbidden
@ RegistrationConflict
@ RegistrationNotAllowed
@ RegistrationUnexpectedRequest
@ RegistrationNotAuthorized
@ RegistrationNotAcceptable
@ RegistrationRequired
@ RegistrationConstraint
@ RegistrationBadRequest
const std::string XMLNS_X_OOB
Definition: gloox.cpp:51
const std::string XMLNS_REGISTER
Definition: gloox.cpp:41
const std::string XMLNS_X_DATA
Definition: gloox.cpp:49
@ StanzaErrorResourceConstraint
Definition: gloox.h:934
@ StanzaErrorNotAllowed
Definition: gloox.h:904
@ StanzaErrorForbidden
Definition: gloox.h:884
@ StanzaErrorConflict
Definition: gloox.h:878
@ StanzaErrorRegistrationRequired
Definition: gloox.h:924
@ StanzaErrorNotAuthorized
Definition: gloox.h:906
@ StanzaErrorUnexpectedRequest
Definition: gloox.h:945
@ StanzaErrorBadRequest
Definition: gloox.h:874
@ StanzaErrorNotAcceptable
Definition: gloox.h:900
@ ExtRegistration
@ StateConnected
Definition: gloox.h:644