gloox  1.0
search.cpp
1 /*
2  Copyright (c) 2006-2009 by Jakob Schroeter <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 
15 #include "search.h"
16 
17 #include "clientbase.h"
18 #include "dataform.h"
19 #include "iq.h"
20 
21 namespace gloox
22 {
23 
24  // Search::Query ----
25  Search::Query::Query( DataForm* form )
26  : StanzaExtension( ExtSearch ), m_form( form ), m_fields( 0 )
27  {
28  }
29 
30  Search::Query::Query( int fields, const SearchFieldStruct& values )
31  : StanzaExtension( ExtSearch ), m_form( 0 ), m_fields( fields ), m_values( values )
32  {
33  }
34 
35  Search::Query::Query( const Tag* tag )
36  : StanzaExtension( ExtSearch ), m_form( 0 ), m_fields( 0 )
37  {
38  if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_SEARCH )
39  return;
40 
41  const TagList& l = tag->children();
42  TagList::const_iterator it = l.begin();
43  for( ; it != l.end(); ++it )
44  {
45  if( (*it)->name() == "instructions" )
46  {
47  m_instructions = (*it)->cdata();
48  }
49  else if( (*it)->name() == "item" )
50  {
51  m_srl.push_back( new SearchFieldStruct( (*it) ) );
52  }
53  else if( (*it)->name() == "first" )
54  m_fields |= SearchFieldFirst;
55  else if( (*it)->name() == "last" )
56  m_fields |= SearchFieldLast;
57  else if( (*it)->name() == "email" )
58  m_fields |= SearchFieldEmail;
59  else if( (*it)->name() == "nick" )
60  m_fields |= SearchFieldNick;
61  else if( !m_form && (*it)->name() == "x" && (*it)->xmlns() == XMLNS_X_DATA )
62  m_form = new DataForm( (*it) );
63  }
64  }
65 
66  Search::Query::~Query()
67  {
68  delete m_form;
69  SearchResultList::iterator it = m_srl.begin();
70  for( ; it != m_srl.end(); ++it )
71  delete (*it);
72  }
73 
74  const std::string& Search::Query::filterString() const
75  {
76  static const std::string filter = "/iq/query[@xmlns='" + XMLNS_SEARCH + "']";
77  return filter;
78  }
79 
80  Tag* Search::Query::tag() const
81  {
82  Tag* t = new Tag( "query" );
83  t->setXmlns( XMLNS_SEARCH );
84  if( m_form )
85  t->addChild( m_form->tag() );
86  else if( m_fields )
87  {
88  if( !m_instructions.empty() )
89  new Tag( t, "instructions", m_instructions );
90  if( m_fields & SearchFieldFirst )
91  new Tag( t, "first", m_values.first() );
92  if( m_fields & SearchFieldLast )
93  new Tag( t, "last", m_values.last() );
94  if( m_fields & SearchFieldNick )
95  new Tag( t, "nick", m_values.nick() );
96  if( m_fields & SearchFieldEmail )
97  new Tag( t, "email", m_values.email() );
98  }
99  else if( !m_srl.empty() )
100  {
101  SearchResultList::const_iterator it = m_srl.begin();
102  for( ; it != m_srl.end(); ++it )
103  {
104  t->addChild( (*it)->tag() );
105  }
106  }
107  return t;
108  }
109  // ---- ~Search::Query ----
110 
111  // ---- Search ----
113  : m_parent( parent )
114  {
115  if( m_parent )
116  m_parent->registerStanzaExtension( new Query() );
117  }
118 
120  {
121  if( m_parent )
122  {
123  m_parent->removeIDHandler( this );
124  m_parent->removeStanzaExtension( ExtRoster );
125  }
126  }
127 
128  void Search::fetchSearchFields( const JID& directory, SearchHandler* sh )
129  {
130  if( !m_parent || !directory || !sh )
131  return;
132 
133  const std::string& id = m_parent->getID();
134  IQ iq( IQ::Get, directory, id );
135  iq.addExtension( new Query() );
136  m_track[id] = sh;
137  m_parent->send( iq, this, FetchSearchFields );
138  }
139 
140  void Search::search( const JID& directory, DataForm* form, SearchHandler* sh )
141  {
142  if( !m_parent || !directory || !sh )
143  return;
144 
145  const std::string& id = m_parent->getID();
146  IQ iq( IQ::Set, directory, id );
147  iq.addExtension( new Query( form ) );
148 
149  m_track[id] = sh;
150  m_parent->send( iq, this, DoSearch );
151  }
152 
153  void Search::search( const JID& directory, int fields, const SearchFieldStruct& values, SearchHandler* sh )
154  {
155  if( !m_parent || !directory || !sh )
156  return;
157 
158  const std::string& id = m_parent->getID();
159 
160  IQ iq( IQ::Set, directory );
161  iq.addExtension( new Query( fields, values ) );
162 
163  m_track[id] = sh;
164  m_parent->send( iq, this, DoSearch );
165  }
166 
167  void Search::handleIqID( const IQ& iq, int context )
168  {
169  TrackMap::iterator it = m_track.find( iq.id() );
170  if( it != m_track.end() )
171  {
172  switch( iq.subtype() )
173  {
174  case IQ::Result:
175  {
176  const Query* q = iq.findExtension<Query>( ExtSearch );
177  if( !q )
178  return;
179 
180  switch( context )
181  {
182  case FetchSearchFields:
183  {
184  if( q->form() )
185  {
186  (*it).second->handleSearchFields( iq.from(), q->form() );
187  }
188  else
189  {
190  (*it).second->handleSearchFields( iq.from(), q->fields(), q->instructions() );
191  }
192  break;
193  }
194  case DoSearch:
195  {
196  if( q->form() )
197  {
198  (*it).second->handleSearchResult( iq.from(), q->form() );
199  }
200  else
201  {
202  (*it).second->handleSearchResult( iq.from(), q->result() );
203  }
204  break;
205  }
206  }
207  break;
208  }
209  case IQ::Error:
210  (*it).second->handleSearchError( iq.from(), iq.error() );
211  break;
212 
213  default:
214  break;
215  }
216 
217  m_track.erase( it );
218  }
219 
220  return;
221  }
222 
223 }