1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4
5 #include <Util.h>
6 #include <Ice/UUID.h>
7 #include <Slice/PHPUtil.h>
8 #include <algorithm>
9 #include <ctype.h>
10
11 using namespace std;
12 using namespace IcePHP;
13 using namespace Slice::PHP;
14
15 namespace
16 {
17
18 bool
getMember(zval * zv,const string & name,zval * member,int type,bool required)19 getMember(zval* zv, const string& name, zval* member, int type, bool required)
20 {
21 zval* val = zend_hash_str_find(Z_OBJPROP_P(zv), STRCAST(name.c_str()), name.size());
22 if(!val)
23 {
24 if(required)
25 {
26 invalidArgument("object does not contain member `%s'", name.c_str());
27 return false;
28 }
29 }
30
31 if(val)
32 {
33 assert(Z_TYPE_P(val) == IS_INDIRECT);
34 val = Z_INDIRECT_P(val);
35 if(Z_TYPE_P(val) != type)
36 {
37 string expected = zendTypeToString(type);
38 string actual = zendTypeToString(Z_TYPE_P(val));
39 invalidArgument("expected value of type %s for member `%s' but received %s", expected.c_str(),
40 name.c_str(), actual.c_str());
41 return false;
42 }
43 ZVAL_COPY_VALUE(member, val);
44 }
45 return true;
46 }
47
48 void
setStringMember(zval * obj,const string & name,const string & val)49 setStringMember(zval* obj, const string& name, const string& val)
50 {
51 zend_class_entry* cls = Z_OBJCE_P(obj);
52 assert(cls);
53 zend_update_property_stringl(cls,
54 obj,
55 const_cast<char*>(name.c_str()),
56 static_cast<int>(name.size()),
57 const_cast<char*>(val.c_str()),
58 static_cast<int>(val.size())
59 );
60 }
61
62 template<typename T>
63 bool
getVersion(zval * zv,T & v,const char * type)64 getVersion(zval* zv, T& v, const char* type)
65 {
66 if(Z_TYPE_P(zv) != IS_OBJECT)
67 {
68 invalidArgument("value does not contain an object");
69 return false;
70 }
71
72 zend_class_entry* cls = idToClass(type);
73 assert(cls);
74
75 zend_class_entry* ce = Z_OBJCE_P(zv);
76 if(ce != cls)
77 {
78 invalidArgument("expected an instance of %s", ce->name->val);
79 return false;
80 }
81
82 zval majorVal;
83 if(!getMember(zv, "major", &majorVal, IS_LONG, true))
84 {
85 return false;
86 }
87
88 zval minorVal;
89 if(!getMember(zv, "minor", &minorVal, IS_LONG, true))
90 {
91 return false;
92 }
93
94 long m;
95 m = static_cast<long>(Z_LVAL_P(&majorVal));
96 if(m < 0 || m > 255)
97 {
98 invalidArgument("version major must be a value between 0 and 255");
99 return false;
100 }
101 v.major = static_cast<Ice::Byte>(m);
102
103 m = static_cast<long>(Z_LVAL_P(&minorVal));
104 if(m < 0 || m > 255)
105 {
106 invalidArgument("version minor must be a value between 0 and 255");
107 return false;
108 }
109 v.minor = static_cast<Ice::Byte>(m);
110
111 return true;
112 }
113
114 template<typename T>
115 bool
createVersion(zval * zv,const T & version,const char * type)116 createVersion(zval* zv, const T& version, const char* type)
117 {
118 zend_class_entry* cls = idToClass(type);
119 assert(cls);
120
121 if(object_init_ex(zv, cls) != SUCCESS)
122 {
123 runtimeError("unable to initialize %s", cls->name->val);
124 return false;
125 }
126
127 zend_update_property_long(cls, zv, const_cast<char*>("major"), sizeof("major") - 1, version.major);
128 zend_update_property_long(cls, zv, const_cast<char*>("minor"), sizeof("minor") - 1, version.minor);
129
130 return true;
131 }
132
133 template<typename T>
134 bool
versionToString(zval * zv,zval * s,const char * type)135 versionToString(zval* zv, zval* s, const char* type)
136 {
137 T v;
138 if(!getVersion<T>(zv, v, type))
139 {
140 return false;
141 }
142
143 try
144 {
145 string str = IceInternal::versionToString<T>(v);
146 ZVAL_STRINGL(s, STRCAST(str.c_str()), static_cast<int>(str.length()));
147 }
148 catch(const IceUtil::Exception& ex)
149 {
150 throwException(ex);
151 return false;
152 }
153
154 return true;
155 }
156
157 template<typename T>
158 bool
stringToVersion(const string & s,zval * zv,const char * type)159 stringToVersion(const string& s, zval* zv, const char* type)
160 {
161 try
162 {
163 T v = IceInternal::stringToVersion<T>(s);
164 return createVersion<T>(zv, v, type);
165 }
166 catch(const IceUtil::Exception& ex)
167 {
168 throwException(ex);
169 }
170
171 return false;
172 }
173
174 char Ice_ProtocolVersion[] = "::Ice::ProtocolVersion";
175 char Ice_EncodingVersion[] = "::Ice::EncodingVersion";
176
177 }
178
179 void*
extractWrapper(zval * zv)180 IcePHP::extractWrapper(zval* zv)
181 {
182 if(!zv)
183 {
184 runtimeError("method %s() must be invoked on an object", get_active_function_name());
185 return 0;
186 }
187
188 zend_object* obj = Z_OBJ_P(zv);
189 if(!obj)
190 {
191 runtimeError("no object found in %s()", get_active_function_name());
192 return 0;
193 }
194
195 return obj;
196 }
197
198 zend_class_entry*
idToClass(const string & id)199 IcePHP::idToClass(const string& id)
200 {
201 #ifdef ICEPHP_USE_NAMESPACES
202 string cls = scopedToName(id, true);
203 #else
204 string cls = scopedToName(id, false);
205 #endif
206
207 return nameToClass(cls);
208 }
209
210 zend_class_entry*
nameToClass(const string & name)211 IcePHP::nameToClass(const string& name)
212 {
213 zend_class_entry* result;
214 zend_string* s = zend_string_init(STRCAST(name.c_str()), static_cast<int>(name.length()), 0);
215 result = zend_lookup_class(s);
216 zend_string_release(s);
217 return result;
218 }
219
220 bool
createIdentity(zval * zv,const Ice::Identity & id)221 IcePHP::createIdentity(zval* zv, const Ice::Identity& id)
222 {
223 zend_class_entry* cls = idToClass("::Ice::Identity");
224 assert(cls);
225
226 if(object_init_ex(zv, cls) != SUCCESS)
227 {
228 runtimeError("unable to initialize Ice::Identity");
229 return false;
230 }
231
232 setStringMember(zv, "name", id.name);
233 setStringMember(zv, "category", id.category);
234
235 return true;
236 }
237
238 bool
extractIdentity(zval * zv,Ice::Identity & id)239 IcePHP::extractIdentity(zval* zv, Ice::Identity& id)
240 {
241 if(Z_TYPE_P(zv) != IS_OBJECT)
242 {
243 invalidArgument("value does not contain an object");
244 return false;
245 }
246
247 zend_class_entry* cls = idToClass("::Ice::Identity");
248 assert(cls);
249
250 zend_class_entry* ce = Z_OBJCE_P(zv);
251 if(ce != cls)
252 {
253 invalidArgument("expected an identity but received %s", ce->name->val);
254 return false;
255 }
256
257 //
258 // Category is optional, but name is required.
259 //
260 zval categoryVal;
261 ZVAL_UNDEF(&categoryVal);
262 zval nameVal;
263 ZVAL_UNDEF(&nameVal);
264
265 bool catOk = getMember(zv, "category", &categoryVal, IS_STRING, false);
266 bool nameOk = getMember(zv, "name", &nameVal, IS_STRING, true);
267
268 if(!catOk || !nameOk)
269 {
270 return false;
271 }
272
273 id.name = Z_STRVAL_P(&nameVal);
274
275 if(!Z_ISUNDEF(categoryVal))
276 {
277 id.category = Z_STRVAL_P(&categoryVal);
278 }
279 else
280 {
281 id.category = "";
282 }
283
284 return true;
285 }
286
287 bool
createStringMap(zval * zv,const map<string,string> & ctx)288 IcePHP::createStringMap(zval* zv, const map<string, string>& ctx)
289 {
290 array_init(zv);
291
292 for(map<string, string>::const_iterator p = ctx.begin(); p != ctx.end(); ++p)
293 {
294 if(add_assoc_stringl_ex(zv,
295 const_cast<char*>(p->first.c_str()),
296 static_cast<uint>(p->first.length()),
297 const_cast<char*>(p->second.c_str()),
298 static_cast<uint>(p->second.length())) == FAILURE)
299 {
300 return false;
301 }
302 }
303
304 return true;
305 }
306
307 bool
extractStringMap(zval * zv,map<string,string> & ctx)308 IcePHP::extractStringMap(zval* zv, map<string, string>& ctx)
309 {
310 if(Z_TYPE_P(zv) != IS_ARRAY)
311 {
312 string s = zendTypeToString(Z_TYPE_P(zv));
313 invalidArgument("expected an associative array but received %s", s.c_str());
314 return false;
315 }
316
317 HashTable* arr = Z_ARRVAL_P(zv);
318 zend_ulong num_key;
319 zend_string* key;
320 zval* val;
321 ZEND_HASH_FOREACH_KEY_VAL(arr, num_key, key, val)
322 {
323 if(!key)
324 {
325 invalidArgument("array key must be a string");
326 return false;
327 }
328
329 if(Z_TYPE_P(val) != IS_STRING)
330 {
331 invalidArgument("array value must be a string");
332 return false;
333 }
334
335 ctx[key->val] = Z_STRVAL_P(val);
336 (void)num_key; // Avoids error from older versions of GCC about unused variable num_key.
337 }
338 ZEND_HASH_FOREACH_END();
339
340 return true;
341 }
342
343 bool
createStringArray(zval * zv,const Ice::StringSeq & seq)344 IcePHP::createStringArray(zval* zv, const Ice::StringSeq& seq)
345 {
346 array_init(zv);
347 for(Ice::StringSeq::const_iterator p = seq.begin(); p != seq.end(); ++p)
348 {
349 if(add_next_index_stringl(zv, STRCAST(p->c_str()), static_cast<uint>(p->length())) == FAILURE)
350 {
351 return false;
352 }
353 }
354
355 return true;
356 }
357
358 bool
extractStringArray(zval * zv,Ice::StringSeq & seq)359 IcePHP::extractStringArray(zval* zv, Ice::StringSeq& seq)
360 {
361 if(Z_TYPE_P(zv) != IS_ARRAY)
362 {
363 string s = zendTypeToString(Z_TYPE_P(zv));
364 invalidArgument("expected an array of strings but received %s", s.c_str());
365 return false;
366 }
367
368 HashTable* arr = Z_ARRVAL_P(zv);
369 zval* val;
370 ZEND_HASH_FOREACH_VAL(arr, val)
371 {
372 if(Z_TYPE_P(val) != IS_STRING)
373 {
374 invalidArgument("array element must be a string");
375 return false;
376 }
377
378 string s(Z_STRVAL_P(val), Z_STRLEN_P(val));
379 seq.push_back(s);
380 }
381 ZEND_HASH_FOREACH_END();
382
383 return true;
384 }
385
386 bool
createProtocolVersion(zval * zv,const Ice::ProtocolVersion & v)387 IcePHP::createProtocolVersion(zval* zv, const Ice::ProtocolVersion& v)
388 {
389 return createVersion<Ice::ProtocolVersion>(zv, v, Ice_ProtocolVersion);
390 }
391
392 bool
createEncodingVersion(zval * zv,const Ice::EncodingVersion & v)393 IcePHP::createEncodingVersion(zval* zv, const Ice::EncodingVersion& v)
394 {
395 return createVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion);
396 }
397
398 bool
extractEncodingVersion(zval * zv,Ice::EncodingVersion & v)399 IcePHP::extractEncodingVersion(zval* zv, Ice::EncodingVersion& v)
400 {
401 return getVersion<Ice::EncodingVersion>(zv, v, Ice_EncodingVersion);
402 }
403
404 static bool
convertLocalException(const Ice::LocalException & ex,zval * zex)405 convertLocalException(const Ice::LocalException& ex, zval* zex)
406 {
407 zend_class_entry* cls = Z_OBJCE_P(zex);
408 assert(cls);
409
410 //
411 // Transfer data members from Ice exception to PHP object.
412 //
413 try
414 {
415 ex.ice_throw();
416 }
417 catch(const Ice::InitializationException& e)
418 {
419 setStringMember(zex, "reason", e.reason);
420 }
421 catch(const Ice::PluginInitializationException& e)
422 {
423 setStringMember(zex, "reason", e.reason);
424 }
425 catch(const Ice::AlreadyRegisteredException& e)
426 {
427 setStringMember(zex, "kindOfObject", e.kindOfObject);
428 setStringMember(zex, "id", e.id);
429 }
430 catch(const Ice::NotRegisteredException& e)
431 {
432 setStringMember(zex, "kindOfObject", e.kindOfObject);
433 setStringMember(zex, "id", e.id);
434 }
435 catch(const Ice::TwowayOnlyException& e)
436 {
437 setStringMember(zex, "operation", e.operation);
438 }
439 catch(const Ice::UnknownException& e)
440 {
441 setStringMember(zex, "unknown", e.unknown);
442 }
443 catch(const Ice::ObjectAdapterDeactivatedException& e)
444 {
445 setStringMember(zex, "name", e.name);
446 }
447 catch(const Ice::ObjectAdapterIdInUseException& e)
448 {
449 setStringMember(zex, "id", e.id);
450 }
451 catch(const Ice::NoEndpointException& e)
452 {
453 setStringMember(zex, "proxy", e.proxy);
454 }
455 catch(const Ice::EndpointParseException& e)
456 {
457 setStringMember(zex, "str", e.str);
458 }
459 catch(const Ice::IdentityParseException& e)
460 {
461 setStringMember(zex, "str", e.str);
462 }
463 catch(const Ice::ProxyParseException& e)
464 {
465 setStringMember(zex, "str", e.str);
466 }
467 catch(const Ice::IllegalIdentityException& e)
468 {
469 zval id;
470 if(!createIdentity(&id, e.id))
471 {
472 zval_ptr_dtor(&id);
473 return false;
474 }
475 zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, &id);
476 zval_ptr_dtor(&id);
477 }
478 catch(const Ice::RequestFailedException& e)
479 {
480 zval id;
481 if(!createIdentity(&id, e.id))
482 {
483 zval_ptr_dtor(&id);
484 return false;
485 }
486 zend_update_property(cls, zex, const_cast<char*>("id"), sizeof("id") - 1, &id);
487 zval_ptr_dtor(&id);
488 setStringMember(zex, "facet", e.facet);
489 setStringMember(zex, "operation", e.operation);
490 }
491 catch(const Ice::FileException& e)
492 {
493 zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error);
494 setStringMember(zex, "path", e.path);
495 }
496 catch(const Ice::SyscallException& e) // This must appear after all subclasses of SyscallException.
497 {
498 zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error);
499 }
500 catch(const Ice::DNSException& e)
501 {
502 zend_update_property_long(cls, zex, const_cast<char*>("error"), sizeof("error") - 1, e.error);
503 setStringMember(zex, "host", e.host);
504 }
505 catch(const Ice::UnsupportedProtocolException& e)
506 {
507 zval v;
508 if(!createProtocolVersion(&v, e.bad))
509 {
510 zval_ptr_dtor(&v);
511 return false;
512 }
513 zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, &v);
514 zval_ptr_dtor(&v);
515
516 if(!createProtocolVersion(&v, e.supported))
517 {
518 zval_ptr_dtor(&v);
519 return false;
520 }
521 zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, &v);
522 zval_ptr_dtor(&v);
523 }
524 catch(const Ice::UnsupportedEncodingException& e)
525 {
526 zval v;
527 if(!createEncodingVersion(&v, e.bad))
528 {
529 zval_ptr_dtor(&v);
530 return false;
531 }
532 zend_update_property(cls, zex, const_cast<char*>("bad"), sizeof("bad") - 1, &v);
533 zval_ptr_dtor(&v);
534
535 if(!createEncodingVersion(&v, e.supported))
536 {
537 zval_ptr_dtor(&v);
538 return false;
539 }
540 zend_update_property(cls, zex, const_cast<char*>("supported"), sizeof("supported") - 1, &v);
541 zval_ptr_dtor(&v);
542 }
543 catch(const Ice::NoValueFactoryException& e)
544 {
545 setStringMember(zex, "reason", e.reason);
546 setStringMember(zex, "type", e.type);
547 }
548 catch(const Ice::UnexpectedObjectException& e)
549 {
550 setStringMember(zex, "reason", e.reason);
551 setStringMember(zex, "type", e.type);
552 setStringMember(zex, "expectedType", e.expectedType);
553 }
554 catch(const Ice::ProtocolException& e) // This must appear after all subclasses of ProtocolException.
555 {
556 setStringMember(zex, "reason", e.reason);
557 }
558 catch(const Ice::FeatureNotSupportedException& e)
559 {
560 setStringMember(zex, "unsupportedFeature", e.unsupportedFeature);
561 }
562 catch(const Ice::SecurityException& e)
563 {
564 setStringMember(zex, "reason", e.reason);
565 }
566 catch(const Ice::ConnectionManuallyClosedException& e)
567 {
568 add_property_bool(zex, "graceful", e.graceful ? 1 : 0);
569 }
570 catch(const Ice::LocalException&)
571 {
572 //
573 // Nothing to do.
574 //
575 }
576
577 return true;
578 }
579
580 void
convertException(zval * zex,const Ice::Exception & ex)581 IcePHP::convertException(zval* zex, const Ice::Exception& ex)
582 {
583 ZVAL_UNDEF(zex);
584
585 ostringstream ostr;
586 ostr << ex;
587 string str = ostr.str();
588
589 try
590 {
591 ex.ice_throw();
592 }
593 catch(const Ice::LocalException& e)
594 {
595 zend_class_entry* cls = idToClass(e.ice_id());
596 if(cls)
597 {
598 if(object_init_ex(zex, cls) != SUCCESS)
599 {
600 runtimeError("unable to create exception %s", cls->name->val);
601 return;
602 }
603 if(!convertLocalException(e, zex))
604 {
605 return;
606 }
607 }
608 else
609 {
610 cls = idToClass("Ice::UnknownLocalException");
611 assert(cls);
612 if(object_init_ex(zex, cls) != SUCCESS)
613 {
614 runtimeError("unable to create exception %s", cls->name->val);
615 return;
616 }
617 setStringMember(zex, "unknown", str);
618 }
619 }
620 catch(const Ice::UserException&)
621 {
622 zend_class_entry* cls = idToClass("Ice::UnknownUserException");
623 assert(cls);
624 if(object_init_ex(zex, cls) != SUCCESS)
625 {
626 runtimeError("unable to create exception %s", cls->name->val);
627 return;
628 }
629 setStringMember(zex, "unknown", str);
630 }
631 catch(const Ice::Exception&)
632 {
633 zend_class_entry* cls = idToClass("Ice::UnknownException");
634 assert(cls);
635 if(object_init_ex(zex, cls) != SUCCESS)
636 {
637 runtimeError("unable to create exception %s", cls->name->val);
638 return;
639 }
640 setStringMember(zex, "unknown", str);
641 }
642
643 return;
644 }
645
646 void
throwException(const Ice::Exception & ex)647 IcePHP::throwException(const Ice::Exception& ex)
648 {
649 zval zex;
650 convertException(&zex, ex);
651 if(!Z_ISUNDEF(zex))
652 {
653 zend_throw_exception_object(&zex);
654 }
655 }
656
657 std::string
zendTypeToString(int type)658 IcePHP::zendTypeToString(int type)
659 {
660 string result;
661
662 switch(type)
663 {
664 case IS_NULL:
665 result = "null";
666 break;
667
668 case IS_LONG:
669 result = "long";
670 break;
671
672 case IS_DOUBLE:
673 result = "double";
674 break;
675
676 case IS_STRING:
677 result = "string";
678 break;
679
680 case IS_ARRAY:
681 result = "array";
682 break;
683
684 case IS_OBJECT:
685 result = "object";
686 break;
687
688 case IS_TRUE:
689 case IS_FALSE:
690 result = "bool";
691 break;
692
693 default:
694 result = "unknown";
695 break;
696 }
697
698 return result;
699 }
700
701 static void
throwError(const string & name,const string & msg)702 throwError(const string& name, const string& msg)
703 {
704 if(EG(exception))
705 {
706 return;
707 }
708 zval ex;
709 // AutoDestroy destroy(&ex);
710
711 zend_class_entry* cls;
712 {
713 zend_class_entry* p;
714 zend_string* s = zend_string_init(STRCAST(name.c_str()), static_cast<int>(name.size()), 0);
715 p = zend_lookup_class(s);
716 zend_string_release(s);
717 assert(p);
718 cls = p;
719 }
720 if(object_init_ex(&ex, cls) == FAILURE)
721 {
722 assert(false);
723 }
724
725 //
726 // Invoke constructor.
727 //
728 if(!invokeMethod(&ex, ZEND_CONSTRUCTOR_FUNC_NAME, msg))
729 {
730 assert(false);
731 }
732
733 zend_throw_exception_object(&ex);
734 // destroy.release();
735 }
736
737 void
runtimeError(const char * fmt,...)738 IcePHP::runtimeError(const char* fmt, ...)
739 {
740 va_list args;
741 char msg[1024];
742
743 va_start(args, fmt);
744
745 #if defined(_MSC_VER)
746 vsprintf_s(msg, fmt, args);
747 #else
748 vsprintf(msg, fmt, args);
749 #endif
750
751 va_end(args);
752
753 throwError("RuntimeException", msg);
754 }
755
756 void
invalidArgument(const char * fmt,...)757 IcePHP::invalidArgument(const char* fmt, ...)
758 {
759 va_list args;
760 char msg[1024];
761
762 va_start(args, fmt);
763
764 #if defined(_MSC_VER)
765 vsprintf_s(msg, fmt, args);
766 #else
767 vsprintf(msg, fmt, args);
768 #endif
769
770 va_end(args);
771
772 throwError("InvalidArgumentException", msg);
773 }
774
775 static bool
invokeMethodHelper(zval * obj,const string & name,zval * param)776 invokeMethodHelper(zval* obj, const string& name, zval* param)
777 {
778 assert(zend_hash_str_exists(&Z_OBJCE_P(obj)->function_table, STRCAST(name.c_str()), name.size()));
779 zval ret, method;
780 ZVAL_STRING(&method, STRCAST(name.c_str()));
781 uint32_t numParams = param ? 1 : 0;
782 // zval** params = param ? ¶m : 0;
783 int status = 0;
784 zend_try
785 {
786 status = call_user_function(0, obj, &method, &ret, numParams, param);
787 }
788 zend_catch
789 {
790 status = FAILURE;
791 }
792 zend_end_try();
793 zval_dtor(&method);
794 zval_dtor(&ret);
795 if(status == FAILURE || EG(exception))
796 {
797 return false;
798 }
799 return true;
800 }
801
802 bool
invokeMethod(zval * obj,const string & name)803 IcePHP::invokeMethod(zval* obj, const string& name)
804 {
805 return invokeMethodHelper(obj, name, 0);
806 }
807
808 bool
invokeMethod(zval * obj,const string & name,const string & arg)809 IcePHP::invokeMethod(zval* obj, const string& name, const string& arg)
810 {
811 zval param;
812 ZVAL_STRINGL(¶m, STRCAST(arg.c_str()), static_cast<int>(arg.size()));
813 return invokeMethodHelper(obj, name, ¶m);
814 }
815
816 bool
checkClass(zend_class_entry * ce,zend_class_entry * base)817 IcePHP::checkClass(zend_class_entry* ce, zend_class_entry* base)
818 {
819 while(ce)
820 {
821 if(ce == base)
822 {
823 return true;
824 }
825
826 for(zend_ulong i = 0; i < ce->num_interfaces; ++i)
827 {
828 if(checkClass(ce->interfaces[i], base))
829 {
830 return true;
831 }
832 }
833
834 ce = ce->parent;
835 }
836
837 return false;
838 }
839
ZEND_FUNCTION(Ice_stringVersion)840 ZEND_FUNCTION(Ice_stringVersion)
841 {
842 if(ZEND_NUM_ARGS() > 0)
843 {
844 WRONG_PARAM_COUNT;
845 }
846
847 RETURN_STRINGL(STRCAST(ICE_STRING_VERSION), static_cast<int>(strlen(ICE_STRING_VERSION)));
848 }
849
ZEND_FUNCTION(Ice_intVersion)850 ZEND_FUNCTION(Ice_intVersion)
851 {
852 if(ZEND_NUM_ARGS() > 0)
853 {
854 WRONG_PARAM_COUNT;
855 }
856
857 RETURN_LONG(ICE_INT_VERSION);
858 }
859
ZEND_FUNCTION(Ice_generateUUID)860 ZEND_FUNCTION(Ice_generateUUID)
861 {
862 if(ZEND_NUM_ARGS() > 0)
863 {
864 WRONG_PARAM_COUNT;
865 }
866
867 string uuid = Ice::generateUUID();
868 RETURN_STRINGL(STRCAST(uuid.c_str()), static_cast<int>(uuid.size()));
869 }
870
ZEND_FUNCTION(Ice_currentProtocol)871 ZEND_FUNCTION(Ice_currentProtocol)
872 {
873 if(ZEND_NUM_ARGS() > 0)
874 {
875 WRONG_PARAM_COUNT;
876 }
877
878 if(!createProtocolVersion(return_value, Ice::currentProtocol))
879 {
880 RETURN_NULL();
881 }
882 }
883
ZEND_FUNCTION(Ice_currentProtocolEncoding)884 ZEND_FUNCTION(Ice_currentProtocolEncoding)
885 {
886 if(ZEND_NUM_ARGS() > 0)
887 {
888 WRONG_PARAM_COUNT;
889 }
890
891 if(!createEncodingVersion(return_value, Ice::currentProtocolEncoding))
892 {
893 RETURN_NULL();
894 }
895 }
896
ZEND_FUNCTION(Ice_currentEncoding)897 ZEND_FUNCTION(Ice_currentEncoding)
898 {
899 if(ZEND_NUM_ARGS() > 0)
900 {
901 WRONG_PARAM_COUNT;
902 }
903
904 if(!createEncodingVersion(return_value, Ice::currentEncoding))
905 {
906 RETURN_NULL();
907 }
908 }
909
ZEND_FUNCTION(Ice_protocolVersionToString)910 ZEND_FUNCTION(Ice_protocolVersionToString)
911 {
912 zend_class_entry* versionClass = idToClass(Ice_ProtocolVersion);
913 assert(versionClass);
914
915 zval zv;
916 if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, versionClass) != SUCCESS)
917 {
918 RETURN_NULL();
919 }
920
921 if(!versionToString<Ice::ProtocolVersion>(&zv, return_value, Ice_ProtocolVersion))
922 {
923 RETURN_NULL();
924 }
925 }
926
ZEND_FUNCTION(Ice_stringToProtocolVersion)927 ZEND_FUNCTION(Ice_stringToProtocolVersion)
928 {
929 char* str;
930 size_t strLen;
931 if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS)
932 {
933 RETURN_NULL();
934 }
935 string s(str, strLen);
936
937 if(!stringToVersion<Ice::ProtocolVersion>(s, return_value, Ice_ProtocolVersion))
938 {
939 RETURN_NULL();
940 }
941 }
942
ZEND_FUNCTION(Ice_encodingVersionToString)943 ZEND_FUNCTION(Ice_encodingVersionToString)
944 {
945 zend_class_entry* versionClass = idToClass(Ice_EncodingVersion);
946 assert(versionClass);
947
948 zval* zv;
949 if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, versionClass) != SUCCESS)
950 {
951 RETURN_NULL();
952 }
953
954 if(!versionToString<Ice::EncodingVersion>(zv, return_value, Ice_EncodingVersion))
955 {
956 RETURN_NULL();
957 }
958 }
959
ZEND_FUNCTION(Ice_stringToEncodingVersion)960 ZEND_FUNCTION(Ice_stringToEncodingVersion)
961 {
962 char* str;
963 size_t strLen;
964 if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &str, &strLen) != SUCCESS)
965 {
966 RETURN_NULL();
967 }
968 string s(str, strLen);
969
970 if(!stringToVersion<Ice::EncodingVersion>(s, return_value, Ice_EncodingVersion))
971 {
972 RETURN_NULL();
973 }
974 }
975