/
uri_ext.cpp
387 lines (325 loc) · 9.56 KB
/
uri_ext.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
/*
FALCON - The Falcon Programming Language
FILE: uri_ext.cpp
Falcon class reflecting URI class
-------------------------------------------------------------------
Author: Giancarlo Niccolai
Begin: Wed, 27 Feb 2008 22:39:35 +0100
-------------------------------------------------------------------
(C) Copyright 2004: the FALCON developers (see list in AUTHORS file)
See LICENSE file for licensing details.
*/
/*#
@beginmodule core
*/
/** \file
Falcon class reflecting URI class.
*/
#include <falcon/module.h>
#include <falcon/vm.h>
#include <falcon/uri.h>
#include <falcon/lineardict.h>
#include "core_module.h"
#include <falcon/eng_messages.h>
#include <falcon/crobject.h>
namespace Falcon {
namespace core {
CoreObject* UriObject::factory( const CoreClass *me, void *uri, bool )
{
if ( uri != 0 )
return new UriObject( me, *static_cast<URI*>( uri ) );
else
return new UriObject( me );
}
/*# @class URI
@brief Interface to RFC3986 Universal Resource Indicator.
@optparam path The URI that will be used as initial data.
@optparam decode True if the path is URI encoded, and must be decoded (default).
@raise ParamError in case the inital URI is malformed.
This class offers an object oriented interface to access
URI elements.
Setting the properties in this class immediately reflects on the
related fields; for example setting the value of the @b uri
property causes a complete re-parse of the item; setting a field
as the query string will cause the uri to change.
Each update is subject to RFC3986 compliance checks, and will raise
a ParseError if conformance of the URI object is broken.
@prop scheme URI scheme.
@prop userInfo User, password or account specification preceding '\@' host.
@prop host Host specificator.
@prop port Optional port specificator (following the host after a ':').
@prop path Path specificator.
@prop query Query string in the URI.
@prop fragment Fragment string in the uri (following path and query after a '#').
@prop uri Complete URI.
*/
UriObject::UriObject( const UriObject &other ):
CoreObject( other ),
m_uri( other.uri() )
{
}
UriObject::~UriObject()
{
}
UriObject *UriObject::clone() const
{
return new UriObject( *this );
}
bool UriObject::getProperty( const String &prop, Item &value ) const
{
if ( prop == "scheme" )
{
value = new CoreString( uri().scheme() );
}
else if ( prop == "userInfo" )
{
value = new CoreString( uri().userInfo() );
}
else if ( prop == "path" )
{
value = new CoreString( uri().path() );
}
else if ( prop == "host" )
{
value = new CoreString( uri().host() );
}
else if ( prop == "port" )
{
value = new CoreString( uri().port() );
}
else if ( prop == "query" )
{
value = new CoreString( uri().query() );
}
else if ( prop == "fragment" )
{
value = new CoreString( uri().fragment() );
}
else if ( prop == "uri" )
{
value = new CoreString( uri().get(true) );
}
else
{
return defaultProperty( prop, value );
}
return true;
}
bool UriObject::setProperty( const String &prop, const Item &value )
{
if ( prop == "scheme" )
{
if ( ! value.isString() ) goto complain;
uri().scheme( *value.asString() );
}
else if ( prop == "userInfo" )
{
if ( ! value.isString() ) goto complain;
uri().userInfo( *value.asString() );
}
else if ( prop == "path" )
{
if ( ! value.isString() ) goto complain;
uri().path( *value.asString() );
}
else if ( prop == "host" )
{
if ( ! value.isString() ) goto complain;
uri().host( *value.asString() );
}
else if ( prop == "port" )
{
if ( ! value.isString() ) goto complain;
uri().port( *value.asString() );
}
else if ( prop == "query" )
{
if ( ! value.isString() ) goto complain;
uri().query( *value.asString() );
}
else if ( prop == "fragment" )
{
if ( ! value.isString() ) goto complain;
uri().fragment( *value.asString() );
}
else if ( prop == "uri" )
{
if ( ! value.isString() ) goto complain;
uri().parse( *value.asString() );
}
else
return false;
if ( ! uri().isValid() )
{
VMachine* vm = VMachine::getCurrent();
throw new AccessError( ErrorParam( e_param_range, __LINE__)
.origin( e_orig_runtime )
.extra( vm != 0 ? vm->moduleString( rtl_invalid_uri ) : "" ) );
}
return true;
complain:
throw new AccessError( ErrorParam( e_param_type, __LINE__)
.origin( e_orig_runtime )
.extra( "S" ) );
}
FALCON_FUNC URI_init ( ::Falcon::VMachine *vm )
{
Item *p0 = vm->param(0);
Item *i_parse = vm->param(1);
// nothing to do
if ( p0 == 0 )
return;
UriObject *self = dyncast<UriObject*>(vm->self().asObject());
// take the URI generated by the factory (can be empty).
if ( ! p0->isString() )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( "[S]" ) );
}
else {
self->uri().parse( *p0->asString(), false, (i_parse == 0 || i_parse->isTrue()) );
if ( !self->uri().isValid() )
{
throw new ParamError( ErrorParam( e_inv_params ).
origin( e_orig_runtime ).
extra( vm->moduleString( rtl_invalid_uri ) ) );
}
}
}
/*# @method encode URI
@brief Encode a string to URL encoding (static).
@param string The string to be encoded.
@return the URL/URI encoded string.
*/
FALCON_FUNC URI_encode ( ::Falcon::VMachine *vm )
{
Item *p0 = vm->param(0);
if ( ( p0 == 0 ) || ( ! p0->isString() ) )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( "S" ) );
return;
}
CoreString *str = new CoreString;
URI::URLEncode( *p0->asString(), *str );
vm->retval( str );
}
/*# @method decode URI
@brief Decode a string to from URL encoding (static).
@param enc_string The URI/URL encoded string.
@return The decoded string.
@raise ParamError if the string is not a valid URI/URL encoded string.
*/
FALCON_FUNC URI_decode ( ::Falcon::VMachine *vm )
{
Item *p0 = vm->param(0);
if ( ( p0 == 0 ) || ( ! p0->isString() ) )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( "S" ) );
return;
}
CoreString *str = new CoreString;
if ( ! URI::URLDecode( *p0->asString(), *str ) )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( vm->moduleString( rtl_invalid_uri ) ) );
return;
}
vm->retval( str );
}
/*# @method toString URI
@brief Returns a string representing this URI.
@return An URI encoded string containing a valid URI.
Renders the URI into a valid string representation.
@see URI.uri
*/
FALCON_FUNC URI_toString ( ::Falcon::VMachine *vm )
{
UriObject *self = dyncast<UriObject*>( vm->self().asObject() );
URI &uri = self->uri();
vm->retval( new CoreString( uri.get( true ) ) );
}
/*# @method getFields URI
@brief Returns fields contained in the query element into a dictionary.
@return The fields as a dictionary of nil if the query part contains no element.
@raise ParamError if the string is not a valid URI/URL encoded string.
*/
FALCON_FUNC URI_getFields ( ::Falcon::VMachine *vm )
{
UriObject *self = dyncast<UriObject*>( vm->self().asObject() );
URI &uri = self->uri();
if ( uri.query().size() == 0 )
{
vm->retnil();
return;
}
if( uri.fieldCount() == 0 )
{
// we have a query but no fields; this means we still have to parse it.
if ( ! uri.parseQuery( true ) )
{
// todo: better signalation
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( vm->moduleString( rtl_invalid_uri ) ) );
return;
}
// really nothing to parse?
if ( uri.fieldCount() == 0 )
{
vm->retnil();
return;
}
}
// ok, build our dictionary
uint32 count = uri.fieldCount();
CoreDict *dict = new CoreDict( new LinearDict( count ) );
CoreString *key = new CoreString;
CoreString *value = new CoreString;
uri.firstField( *key, *value );
count--;
dict->put( key, value );
while( count > 0 )
{
key = new CoreString;
value = new CoreString;
uri.nextField( *key, *value );
count --;
dict->put( key, value );
}
vm->retval( dict );
}
/*# @method setFields URI
@brief Sets query fields for this uri.
@param fields A dictionary of fields or nil to clear the query.
@raise ParamError if the input dictionary contains non-string values.
*/
FALCON_FUNC URI_setFields ( ::Falcon::VMachine *vm )
{
UriObject *self = dyncast<UriObject*>( vm->self().asObject() );
URI &uri = self->uri();
Item *p0 = vm->param(0);
if ( ( p0 == 0 ) || ( ! p0->isDict() ) )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( "S" ) );
return;
}
CoreDict *dict = p0->asDict();
Iterator iter( &dict->items() );
while( iter.hasCurrent() )
{
if ( ( !iter.getCurrentKey().isString()) || (! iter.getCurrent().isString() ) )
{
throw new ParamError( ErrorParam( e_inv_params, __LINE__ ).
origin( e_orig_runtime ).extra( "S" ) );
return;
}
uri.setField( *iter.getCurrentKey().asString(), *iter.getCurrent().asString() );
iter.next();
}
uri.makeQuery();
}
}
}
/* end of uri_ext.cpp */