Projet

Général

Profil

0001-Add-PHP-7-binding-28608.patch

Benjamin Dauvergne, 06 septembre 2019 15:31

Télécharger (85,6 ko)

Voir les différences:

Subject: [PATCH 1/2] Add PHP 7 binding (#28608)

License: MIT
 bindings/Makefile.am                          |   8 +-
 bindings/bindings.py                          |   5 +
 bindings/overrides.xml                        |   8 +-
 bindings/php7/Makefile.am                     |  41 ++
 bindings/php7/__init__.py                     |   0
 bindings/php7/examples/Makefile.am            |   2 +
 .../get_attributes_from_assertion.php         |  11 +
 bindings/php7/lang.py                         |  43 ++
 bindings/php7/lasso.ini                       |   2 +
 bindings/php7/php_code.py                     | 511 ++++++++++++++++
 bindings/php7/tests/Makefile.am               |   8 +
 bindings/php7/tests/binding_tests.php         | 211 +++++++
 bindings/php7/tests/binding_tests.sh          |   3 +
 bindings/php7/tests/profile_tests.php         | 224 +++++++
 bindings/php7/tests/profile_tests.sh          |   3 +
 bindings/php7/wrapper_header.py               |  64 ++
 bindings/php7/wrapper_source.py               | 550 ++++++++++++++++++
 bindings/php7/wrapper_source_top.c            | 380 ++++++++++++
 configure.ac                                  |  81 +++
 19 files changed, 2150 insertions(+), 5 deletions(-)
 create mode 100644 bindings/php7/Makefile.am
 create mode 100644 bindings/php7/__init__.py
 create mode 100644 bindings/php7/examples/Makefile.am
 create mode 100644 bindings/php7/examples/get_attributes_from_assertion.php
 create mode 100644 bindings/php7/lang.py
 create mode 100644 bindings/php7/lasso.ini
 create mode 100644 bindings/php7/php_code.py
 create mode 100644 bindings/php7/tests/Makefile.am
 create mode 100644 bindings/php7/tests/binding_tests.php
 create mode 100755 bindings/php7/tests/binding_tests.sh
 create mode 100644 bindings/php7/tests/profile_tests.php
 create mode 100755 bindings/php7/tests/profile_tests.sh
 create mode 100644 bindings/php7/wrapper_header.py
 create mode 100644 bindings/php7/wrapper_source.py
 create mode 100644 bindings/php7/wrapper_source_top.c
bindings/Makefile.am
6 6
if PHP5_ENABLED
7 7
SUBDIRS += php5
8 8
endif
9
if PHP7_ENABLED
10
SUBDIRS += php7
11
endif
9 12
if JAVA_ENABLED
10 13
SUBDIRS += java
11 14
endif
......
15 18

  
16 19
CLEANFILES = bindings.pyc lang_java.pyc lang_python.pyc lang_php5.pyc \
17 20
             utils.pyc lang_php5_helpers/__init__.pyc lang_php5_helpers/php_code.pyc \
18
              lang_php5_helpers/wrapper_header.pyc lang_php5_helpers/wrapper_source.pyc
21
             lang_php5_helpers/wrapper_header.pyc lang_php5_helpers/wrapper_source.pyc \
22
             lang_php7.pyc \
23
             lang_php7_helpers/__init__.pyc lang_php7_helpers/php_code.pyc \
24
             lang_php7_helpers/wrapper_header.pyc lang_php7_helpers/wrapper_source.pyc
19 25

  
20 26
EXTRA_DIST = bindings.py \
21 27
	overrides.xml \
bindings/bindings.py
629 629

  
630 630
        php5_binding = lang.Binding(binding)
631 631
        php5_binding.generate()
632
    elif options.language == 'php7':
633
        from php7 import lang
634

  
635
        php7_binding = lang.Binding(binding)
636
        php7_binding.generate()
632 637
    elif options.language == 'java':
633 638
        from java import lang
634 639

  
bindings/overrides.xml
198 198
  <func name="lasso_log_set_handler" skip="true"/>
199 199
  <func name="lasso_log_remove_handler" skip="true"/>
200 200
  <func name="lasso_key_new_for_signature_from_memory" skip="true"/>
201
  <func name="lasso_samlp2_extensions_get_any" skip="php5,perl,java"/>
202
  <func name="lasso_samlp2_extensions_set_any" skip="php5,perl,java"/>
203
  <func name="lasso_samlp2_extensions_get_attributes" skip="php5,perl,java"/>
204
  <func name="lasso_samlp2_extensions_set_attributes" skip="php5,perl,java"/>
201
  <func name="lasso_samlp2_extensions_get_any" skip="php5,php7,perl,java"/>
202
  <func name="lasso_samlp2_extensions_set_any" skip="php5,php7,perl,java"/>
203
  <func name="lasso_samlp2_extensions_get_attributes" skip="php5,php7,perl,java"/>
204
  <func name="lasso_samlp2_extensions_set_attributes" skip="php5,php7,perl,java"/>
205 205
  <!-- Xml -->
206 206
  <func name="lasso_node_export_to_soap_with_headers">
207 207
    <param name="node"/>
bindings/php7/Makefile.am
1
CLEANFILES = lasso.php php_lasso.h _lasso.c
2
DISTCLEANFILES = __init__.pyc lang.pyc php_code.pyc wrapper_header.pyc wrapper_top.pyc wrapper_source.pyc
3
SUBDIRS = examples tests
4

  
5
AM_CPPFLAGS = \
6
	-I$(top_builddir) \
7
	-I$(top_srcdir) \
8
	$(SASL_CFLAGS)
9

  
10
php_extensiondir = ${prefix}@PHP7_UNPREFIXED_EXTENSION_DIR@
11
php_extension_LTLIBRARIES = lasso.la
12

  
13
php_includedir = @PHP7_INCLUDE_DIR@
14
nodist_php_include_DATA = lasso.php
15

  
16
php_configdir=@PHP7_CONFIG_DIR@
17
php_config_DATA = lasso.ini
18

  
19
lasso_la_CFLAGS = -fno-strict-aliasing $(LASSO_CORE_CFLAGS) -I$(top_srcdir) -I$(top_builddir) $(PHP7_INCLUDES) $(AM_CFLAGS)
20
lasso_la_CFLAGS += -Wno-unused-parameter -Wno-sign-compare # problem in zend.h
21
lasso_la_LDFLAGS = -export-dynamic -prefer-pic -module -avoid-version
22
lasso_la_LIBADD = $(top_builddir)/lasso/liblasso.la $(LASSO_LIBS) $(PHP7_LDFLAGS)
23
nodist_lasso_la_SOURCES = _lasso.c
24

  
25
BUILT_SOURCES = _lasso.c
26

  
27
if WSF_ENABLED
28
EXTRA_ARGS = --enable-id-wsf
29
endif
30

  
31

  
32
lasso.php _lasso.c: lang.py wrapper_source.py wrapper_header.py wrapper_source_top.c php_code.py ../overrides.xml
33
	$(AM_V_GEN) $(PYTHON) $(top_srcdir)/bindings/bindings.py -l php7 --src-dir=$(top_srcdir)/lasso/ $(EXTRA_ARGS)
34

  
35
doc:
36
	phpdoc -o HTML:frames:earthli -f lasso.php -t docs
37

  
38

  
39
.PHONY: doc
40

  
41
EXTRA_DIST = lasso.ini lang.py php_code.py wrapper_header.py wrapper_source.py __init__.py wrapper_source_top.c
bindings/php7/examples/Makefile.am
1
MAINTAINERCLEANFILES = Makefile.in
2
EXTRA_DIST = get_attributes_from_assertion.php
bindings/php7/examples/get_attributes_from_assertion.php
1
/* Example SP PHP5 code to get attributes from an assertion */
2

  
3
foreach ($assertion->attributeStatement[0]->attribute as $attribute) {
4
    if ($attribute->name == LASSO_SAML2_ATTRIBUTE_NAME_EPR) {
5
        continue;
6
    }
7
    echo 'attribute : ' . $attribute->name . "\n";
8
    foreach ($attribute->attributeValue as $value) {
9
        echo '  value : ' . $value->any[0]->content . "\n";
10
    }
11
}
bindings/php7/lang.py
1
# Lasso - A free implementation of the Liberty Alliance specifications.
2
#
3
# Copyright (C) 2004-2007 Entr'ouvert
4
# http://lasso.entrouvert.org
5
#
6
# Authors: See AUTHORS file in top-level directory.
7
#
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, see <http://www.gnu.org/licenses/>.
20

  
21
import os
22
from php7.wrapper_source import WrapperSource
23
from php7.wrapper_header import WrapperHeader
24
from php7.php_code import PhpCode
25

  
26
class Binding:
27
    def __init__(self, binding_data):
28
        self.binding_data = binding_data
29

  
30
    def generate(self):
31
        fd = open('_lasso.c', 'w')
32
        wrapper_source = WrapperSource(self.binding_data, fd)
33
        wrapper_source.generate()
34
        fd.close()
35

  
36
        fd = open('php_lasso.h', 'w')
37
        WrapperHeader(self.binding_data, fd, wrapper_source.functions_list).generate()
38
        fd.close()
39

  
40
        fd = open('lasso.php', 'w')
41
        PhpCode(self.binding_data, fd).generate()
42
        fd.close()
43

  
bindings/php7/lasso.ini
1
; configuration for php PDO module
2
extension=lasso.so
bindings/php7/php_code.py
1
# Lasso - A free implementation of the Liberty Alliance specifications.
2
#
3
# Copyright (C) 2004-2007 Entr'ouvert
4
# http://lasso.entrouvert.org
5
#
6
# Authors: See AUTHORS file in top-level directory.
7
#
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, see <http://www.gnu.org/licenses/>.
20

  
21
import re
22
import sys
23
import six
24

  
25
from utils import *
26

  
27
class PhpCode:
28
    def __init__(self, binding_data, fd):
29
        self.binding_data = binding_data
30
        self.fd = fd
31

  
32
    def is_object(self, t):
33
        return is_object(t) and not is_int(t, self.binding_data)
34

  
35
    def generate(self):
36
        self.generate_header()
37
        for klass in self.binding_data.structs:
38
            self.generate_class(klass)
39
        self.generate_exceptions()
40
        self.generate_footer()
41

  
42
    def generate_header(self):
43
        six.print_('''\
44
<?php
45

  
46
/* this file has been generated automatically; do not edit */
47

  
48
/**
49
 * @package Lasso
50
 */
51

  
52
// Try to load Lasso extension if it's not already loaded.
53
if (!extension_loaded('lasso')) {
54
    die("Lasso extension is not loaded");
55
}
56

  
57
/**
58
 * @package Lasso
59
 *
60
 * Root class of all Lasso objects to define generic getter and setter
61
 */
62
class LassoObject {
63
    /**
64
     * @return mixed
65
     */
66
    public function __get($attr) {
67
        $func = "get_" . $attr;
68
        if (method_exists($this, $func)) {
69
            return call_user_func(array($this, $func));
70
        }
71
        return null;
72
    }
73

  
74
    public function __set($attr, $value) {
75
        $func = "set_" . $attr;
76
        if (method_exists($this, $func)) {
77
            call_user_func(array($this, $func), $value);
78
        }
79
    }
80
}
81

  
82
/*
83
 * Convert a C object to a PHP object
84
 */
85
function cptrToPhp ($cptr) {
86
    if (is_null($cptr) || !$cptr) return null;
87
    $typename = lasso_get_object_typename($cptr);
88
    $class_name = $typename . "NoInit";
89
    $obj = new $class_name();
90
    if (! is_null($obj)) {
91
        $obj->_cptr = $cptr;
92
        return $obj;
93
    }
94
    return null;
95
}
96

  
97
function lassoGetRequestTypeFromSoapMsg($mesg) {
98
    return lasso_get_request_type_from_soap_msg($mesg);
99
}
100

  
101
function lassoRegisterIdWsf2DstService($prefix, $href) {
102
    lasso_register_idwsf2_dst_service($prefix, $href);
103
}
104
''', file=self.fd)
105

  
106
    def generate_class(self, klass):
107
        class_name = klass.name
108

  
109
        if klass.parent != 'GObject':
110
            inheritence = ' extends %s' % klass.parent
111
        else:
112
            inheritence = ' extends LassoObject'
113

  
114
        six.print_('/**', file=self.fd)
115
        six.print_(' * @package Lasso', file=self.fd)
116
        six.print_(' */', file=self.fd)
117
        six.print_('class %(class_name)s%(inheritence)s {' % locals(), file=self.fd)
118

  
119
        if klass.members or klass.methods:
120
            self.generate_constructors(klass)
121
            self.generate_getters_and_setters(klass)
122
            self.generate_methods(klass)
123

  
124
        six.print_('}', file=self.fd)
125
        six.print_('', file=self.fd)
126

  
127
        # Add a special class to get an object instance without initialising
128
        six.print_('/**', file=self.fd)
129
        six.print_(' * @package Lasso', file=self.fd)
130
        six.print_(' */', file=self.fd)
131
        six.print_('class %(class_name)sNoInit extends %(class_name)s {' % locals(), file=self.fd)
132
        six.print_('    public function __construct() {}', file=self.fd)
133
        six.print_('}', file=self.fd)
134
        six.print_('', file=self.fd)
135

  
136
    def generate_constructors(self, klass):
137
        method_prefix = format_as_underscored(klass.name) + '_'
138
        for m in self.binding_data.functions:
139
            name = m.rename or m.name
140
            if m.name == method_prefix + 'new':
141
                php_args = []
142
                c_args = []
143
                for arg in m.args:
144
                    arg_type, arg_name, arg_options = arg
145
                    if arg_options.get('optional'):
146
                        php_args.append('$%s = null' % arg_name)
147
                    else:
148
                        php_args.append('$%s' % arg_name)
149

  
150
                    if self.is_object(arg_type):
151
                        c_args.append('$%s->_cptr' % arg_name)
152
                    else:
153
                        c_args.append('$%s' % arg_name)
154

  
155
                php_args = ', '.join(php_args)
156
                c_args = ', '.join(c_args)
157
                # XXX: could check $this->_cptr->typename to see if it got the
158
                # right class type
159
                six.print_('    public $_cptr = null;', file=self.fd)
160
                six.print_('', file=self.fd)
161
                six.print_('    public function __construct(%s) {' % php_args, file=self.fd)
162
                six.print_('        $this->_cptr = %s(%s);' % (m.name, c_args), file=self.fd)
163
                six.print_('        if (is_null($this->_cptr)) { throw new Exception("Constructor for ', klass.name, ' failed "); }', file=self.fd)
164
                six.print_('    }', file=self.fd)
165
                six.print_('', file=self.fd)
166

  
167
            elif name.startswith(method_prefix) and m.args \
168
                    and clean_type(unconstify(m.args[0][0])) != klass.name:
169
                if m.rename:
170
                    php_name = m.rename
171
                else:
172
                    mname = m.name
173
                    mname = mname[len(method_prefix):]
174
                    if 'new' in mname and not mname.startswith('new'):
175
                        continue
176
                    php_name = format_underscore_as_camelcase(mname)
177
                php_args = []
178
                c_args = []
179
                for arg in m.args:
180
                    arg_type, arg_name, arg_options = arg
181
                    if arg_options.get('optional'):
182
                        php_args.append('$%s = null' % arg_name)
183
                    else:
184
                        php_args.append('$%s' % arg_name)
185

  
186
                    if self.is_object(arg_type):
187
                        c_args.append('$%s->_cptr' % arg_name)
188
                    else:
189
                        c_args.append('$%s' % arg_name)
190
                php_args = ', '.join(php_args)
191
                c_args = ', '.join(c_args)
192
                six.print_('    public static function %s(%s) {' % (php_name, php_args), file=self.fd)
193
                six.print_('        return cptrToPhp(%s(%s));' % (m.name, c_args), file=self.fd)
194
                six.print_('    }', file=self.fd)
195
                six.print_('', file=self.fd)
196

  
197

  
198

  
199
    def generate_getter(self, c, m):
200
        d = {
201
            'type': arg_type(m),
202
            'name': format_as_camelcase(arg_name(m)),
203
            'docstring': self.get_docstring_return_type(arg_type(m)),
204
            'class': c.name
205
        }
206

  
207
        six.print_('''\
208
    /**
209
    * @return  %(docstring)s
210
    */
211
    protected function get_%(name)s() {''' % d, file=self.fd)
212
        six.print_('        $t = %(class)s_%(name)s_get($this->_cptr);' % d, file=self.fd)
213
        if self.is_object(m):
214
            six.print_('        $t = cptrToPhp($t);', file=self.fd)
215
        elif (is_glist(m) or is_hashtable(m)) and self.is_object(element_type(m)):
216
                six.print_('        foreach ($t as $key => $item) {', file=self.fd)
217
                six.print_('            $t[$key] = cptrToPhp($item);', file=self.fd)
218
                six.print_('        }', file=self.fd)
219
        elif is_hashtable(m) or (is_glist(m) and (is_cstring(element_type(m)) \
220
                or is_xml_node(element_type(m)))) or is_int(m, self.binding_data) \
221
                or is_boolean(m) or is_cstring(m) or is_xml_node(m):
222
            pass
223
        else:
224
            raise Exception('Cannot generate a Php getter %s.%s' % (c,m))
225
        six.print_('        return $t;', file=self.fd)
226
        six.print_('    }', file=self.fd)
227

  
228
    def generate_setter(self, c, m):
229
        d = { 'type': arg_type(m), 'name': format_as_camelcase(arg_name(m)),
230
                'docstring': self.get_docstring_return_type(arg_type(m)), 'class': c.name }
231
        six.print_('    protected function set_%(name)s($value) {' % d, file=self.fd)
232
        if self.is_object(m):
233
            six.print_('        $value = $value->_cptr;', file=self.fd)
234
        elif (is_glist(m) or is_hashtable(m)) and self.is_object(element_type(m)):
235
            six.print_('        $array = array();', file=self.fd)
236
            six.print_('        if (!is_null($value)) {', file=self.fd)
237
            six.print_('            foreach ($value as $key => $item) {', file=self.fd)
238
            six.print_('                $array[$key] = $item->_cptr;', file=self.fd)
239
            six.print_('            }', file=self.fd)
240
            six.print_('        }', file=self.fd)
241
            six.print_('        $value = $array;', file=self.fd)
242
        elif is_hashtable(m) or (is_glist(m) and (is_cstring(element_type(m)) \
243
                or is_xml_node(element_type(m)))) or is_int(m, self.binding_data) \
244
                or is_boolean(m) or is_cstring(m) or is_xml_node(m):
245
            pass
246
        else:
247
            raise Exception('Cannot generate a Php setter %s.%s' % (c,m))
248
        six.print_('        %(class)s_%(name)s_set($this->_cptr, $value);' % d, file=self.fd)
249
        six.print_('    }', file=self.fd)
250
        six.print_('', file=self.fd)
251

  
252
    def generate_getters_and_setters(self, klass):
253
        for m in klass.members:
254
            self.generate_getter(klass, m)
255
            self.generate_setter(klass, m)
256

  
257
    def generate_methods(self, klass):
258
        methods = klass.methods[:]
259

  
260
        # first pass on methods, removing accessors
261
        for m in klass.methods:
262
            if m.rename:
263
                meth_name = m.rename
264
            else:
265
                meth_name = m.name
266
            if not ('_get_' in meth_name and len(m.args) == 1):
267
                continue
268
            methods.remove(m)
269
            try:
270
                setter_name = meth_name.replace('_get_', '_set_')
271
                setter = [x for x in methods if x.name == setter_name][0]
272
                methods.remove(setter)
273
            except IndexError:
274
                setter = None
275
            mname = re.match(r'lasso_.*_get_(\w+)', meth_name).group(1)
276
            mname = format_as_camelcase(mname)
277

  
278
            six.print_('    /**', file=self.fd)
279
            six.print_('     * @return %s' % self.get_docstring_return_type(m.return_type), file=self.fd)
280
            six.print_('     */', file=self.fd)
281
            six.print_('    protected function get_%s() {' % mname, file=self.fd)
282
            if self.is_object(m.return_type):
283
                six.print_('        $cptr = %s($this->_cptr);' % meth_name, file=self.fd)
284
                six.print_('        if (! is_null($cptr)) {', file=self.fd)
285
                six.print_('            return cptrToPhp($cptr);', file=self.fd)
286
                six.print_('        }', file=self.fd)
287
                six.print_('        return null;', file=self.fd)
288
            else:
289
                six.print_('        return %s($this->_cptr);' % meth_name, file=self.fd)
290
            six.print_('    }', file=self.fd)
291
            if setter:
292
                six.print_('    protected function set_%s($value) {' % mname, file=self.fd)
293
                if self.is_object(m.return_type):
294
                    six.print_('        %s($this->_cptr, $value->_cptr);' % setter.name, file=self.fd)
295
                else:
296
                    six.print_('        %s($this->_cptr, $value);' % setter.name, file=self.fd)
297
                six.print_('    }', file=self.fd)
298
            six.print_('', file=self.fd)
299

  
300
        # second pass on methods, real methods
301
        method_prefix = format_as_underscored(klass.name) + '_'
302
        for m in methods:
303
            if m.name.endswith('_new') or m.name.endswith('_new_from_dump') or \
304
                    m.name.endswith('_new_full'):
305
                continue
306
            if not m.name.startswith(method_prefix):
307
                print >> sys.stderr, 'W:', m.name, 'vs', method_prefix
308
                continue
309

  
310
            if m.rename:
311
                mname = m.rename
312
            else:
313
                mname = m.name
314
            cname = mname
315
            mname = mname[len(method_prefix):]
316
            php_args = []
317
            c_args = []
318
            outarg = None
319
            for arg in m.args[1:]:
320
                arg_type, arg_name, arg_options = arg
321
                arg_name = '$' + arg_name
322
                if is_out(arg):
323
                    assert not outarg
324
                    outarg = arg
325
                if arg_options.get('optional'):
326
                    if arg_options.get('default'):
327
                        defval = arg_options.get('default')
328
                        if defval.startswith('c:'): # constant
329
                            php_args.append('%s = %s' % (arg_name, defval[2:]))
330
                        elif defval.startswith('b:'): # boolean
331
                            php_args.append('%s = %s' % (arg_name, defval[2:]))
332
                        else:
333
                            print >> sys.stderr, "E: don't know what to do with %s" % defval
334
                            sys.exit(1)
335
                    else:
336
                        php_args.append('%s = null' % arg_name)
337
                else:
338
                    php_args.append(arg_name)
339
                if is_xml_node(arg) or is_boolean(arg) or is_cstring(arg) or \
340
                    is_int(arg, self.binding_data) or is_glist(arg) or \
341
                    is_hashtable(arg) or is_time_t_pointer(arg):
342
                    c_args.append(arg_name)
343
                elif self.is_object(arg):
344
                    c_args.append('%s->_cptr' % arg_name)
345
                else:
346
                    raise Exception('Does not handle argument of type: %s' % ((m, arg),))
347
                if is_out(arg):
348
                    php_args.pop()
349
                    php_args.append(arg_name)
350
                    c_args.pop()
351
                    c_args.append(arg_name)
352

  
353
            if php_args:
354
                php_args = ', '.join(php_args)
355
            else:
356
                php_args = ''
357
            if c_args:
358
                c_args = ', ' + ', '.join(c_args)
359
            else:
360
                c_args = ''
361

  
362
            if m.docstring:
363
                six.print_(self.generate_docstring(m, mname, 4), file=self.fd)
364
            six.print_('    public function %s(%s) {' % (
365
                    format_underscore_as_camelcase(mname), php_args), file=self.fd)
366
            if m.return_type == 'void':
367
                six.print_('        %s($this->_cptr%s);' % (cname, c_args), file=self.fd)
368
            elif is_rc(m.return_type):
369
                six.print_('        $rc = %s($this->_cptr%s);' % (cname, c_args), file=self.fd)
370
                six.print_('        if ($rc == 0) {', file=self.fd)
371
                six.print_('            return 0;', file=self.fd)
372
                six.print_('        } else if ($rc > 0) {', file=self.fd) # recoverable error
373
                six.print_('            return $rc;', file=self.fd)
374
                six.print_('        } else if ($rc < 0) {', file=self.fd) # unrecoverable error
375
                six.print_('            LassoError::throw_on_rc($rc);', file=self.fd)
376
                six.print_('        }', file=self.fd)
377
            else:
378
                six.print_('        return %s($this->_cptr%s);' % (cname, c_args), file=self.fd)
379
            six.print_('    }', file=self.fd)
380
            six.print_('', file=self.fd)
381

  
382
        six.print_('', file=self.fd)
383

  
384
    def generate_docstring(self, func, method_name, indent):
385
        docstring = func.docstring.orig_docstring
386
        if func.args:
387
            first_arg_name = func.args[0][1]
388
        else:
389
            first_arg_name = None
390

  
391
        def rep(s):
392
            type = s.group(1)[0]
393
            var = s.group(1)[1:]
394
            if type == '#': # struct
395
                return var
396
            elif type == '%': # %TRUE, %FALSE
397
                if var in ('TRUE', 'FALSE'):
398
                    return var
399
                print >> sys.stderr, 'W: unknown docstring thingie \'%s\' in \'%s\'' % (s.group(1), func.docstring.orig_docstring)
400
            elif type == '@':
401
                if var == first_arg_name:
402
                    return '$this'
403
                else:
404
                    return '$' + var
405
            return s.group(1)
406

  
407
        lines = []
408
        for l in docstring.splitlines():
409
            if l.strip() and not lines:
410
                continue
411
            lines.append(l)
412
        s = indent * ' ' + '/**\n'
413
        s += '\n'.join([indent * ' ' + ' * ' + x for x in lines[1:]])
414
        s += '\n' + indent * ' ' + ' */'
415
        regex = re.compile(r'([\#%@]\w+)', re.DOTALL)
416
        s = regex.sub(rep, s)
417
        s = s.replace('Return value: ', '@return %s ' % self.get_docstring_return_type(func.return_type))
418
        return s
419

  
420
    def get_docstring_return_type(self, return_type):
421
        if return_type == None:
422
            return ''
423
        elif return_type == 'gboolean':
424
            return 'boolean'
425
        elif return_type in ['int', 'gint'] + self.binding_data.enums:
426
            return 'int'
427
        elif return_type in ('char*', 'gchar*', 'const char*', 'const gchar*', 'xmlNode*'):
428
            return 'string'
429
        elif return_type in ('GList*', 'GHashTable*'):
430
            return 'array'
431
        else:
432
            # Objects
433
            return return_type.replace('*', '')
434

  
435
    def generate_exceptions(self):
436
        done_cats = []
437

  
438
        for exc_cat in self.binding_data.overrides.findall('exception/category'):
439
            cat = exc_cat.attrib.get('name')
440
            done_cats.append(cat)
441
            parent_cat = exc_cat.attrib.get('parent', '')
442
            six.print_('''\
443
/**
444
 * @package Lasso
445
 */
446
class Lasso%sError extends Lasso%sError {}
447
''' % (cat, parent_cat), file=self.fd) 
448

  
449
        exceptions_dict = {}
450

  
451
        for c in self.binding_data.constants:
452
            m = re.match(r'LASSO_(\w+)_ERROR_(.*)', c[1])
453
            if not m:
454
                continue
455
            cat, detail = m.groups()
456
            cat = cat.title().replace('_', '')
457
            detail = (cat + '_' + detail).title().replace('_', '')
458
            if not cat in done_cats:
459
                done_cats.append(cat)
460
                for exc_cat in self.binding_data.overrides.findall('exception/category'):
461
                    if exc_cat.attrib.get('name') == cat:
462
                        parent_cat = exc_cat.attrib.get('parent')
463
                        break
464
                else:
465
                    parent_cat = ''
466

  
467
                six.print_('''\
468
/**
469
 * @package Lasso
470
 */
471
class Lasso%sError extends Lasso%sError {}
472
''' % (cat, parent_cat), file=self.fd)
473

  
474
            if detail not in exceptions_dict:
475
                six.print_('''\
476
/**
477
 * @package Lasso
478
 */
479
class Lasso%sError extends Lasso%sError {
480
    protected $code = %s;
481
}
482
''' % (detail, cat, c[1]), file=self.fd)
483
                exceptions_dict[detail] = c[1]
484

  
485
        six.print_('''\
486
/**
487
 * @package Lasso
488
 */
489
class LassoError extends Exception {
490
    private static $exceptions_dict = array(''', file=self.fd)
491

  
492
        for k, v in exceptions_dict.items():
493
            six.print_('        %s => "Lasso%sError",' % (v, k), file=self.fd)
494

  
495
        six.print_('''\
496
    );
497

  
498
    public static function throw_on_rc($rc) {
499
        $exception = self::$exceptions_dict[$rc];
500
        if (! class_exists($exception)) {
501
            $exception = "LassoError";
502
        }
503
        throw new $exception(strError($rc), $rc);
504
    }
505
}
506
''', file=self.fd)
507

  
508
    def generate_footer(self):
509
        six.print_('''\
510
?>''', file=self.fd)
511

  
bindings/php7/tests/Makefile.am
1
MAINTAINERCLEANFILES = Makefile.in
2
if PHP7_ENABLED
3
TESTS_ENVIRONMENT=env "SRCDIR=$(srcdir)/" "PHP7=$(PHP7)"
4
TESTS = profile_tests.sh binding_tests.sh
5
endif
6

  
7
EXTRA_DIST = profile_tests.php binding_tests.php profile_tests.sh binding_tests.sh
8

  
bindings/php7/tests/binding_tests.php
1
#!/usr/bin/php
2
<?php
3
# Lasso - A free implementation of the Liberty Alliance specifications.
4
# 
5
# Copyright (C) 2004-2007 Entr'ouvert
6
# http://lasso.entrouvert.org
7
#
8
# Authors: See AUTHORS file in top-level directory.
9
#
10
# This program is free software; you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation; either version 2 of the License, or
13
# (at your option) any later version.
14
# 
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# GNU General Public License for more details.
19
# 
20
# You should have received a copy of the GNU General Public License
21
# along with this program; if not, see <http://www.gnu.org/licenses/>.
22

  
23
require("../lasso.php");
24

  
25
define("DATA_DIR", getenv("SRCDIR") . "../../../tests/data/");
26

  
27
function test01() {
28
    echo "Get an xmlNode* from a Lasso function... ";
29

  
30
    $organisation_string = '<Organization xmlns="urn:liberty:metadata:2003-08">
31
  <OrganizationName>Name of the organization</OrganizationName>
32
 </Organization>';
33

  
34
    $server = new LassoServer(
35
        DATA_DIR . "sp1-la/metadata.xml",
36
        DATA_DIR . "sp1-la/private-key-raw.pem",
37
        NULL,
38
        DATA_DIR . "sp1-la/certificate.pem");
39
    assert(!is_null($server->organization));
40
    assert($server->organization == $organisation_string);
41

  
42
    echo "OK.\n";
43
}
44

  
45
function test02() {
46
    echo "Get and set a list of strings... ";
47

  
48
    $requestAuthnContext = new LassoLibRequestAuthnContext();
49
    $requestAuthnContext->authnContextClassRef = array(LASSO_LIB_AUTHN_CONTEXT_CLASS_REF_PASSWORD);
50
    assert(! is_null($requestAuthnContext->authnContextClassRef));
51
    assert(sizeof($requestAuthnContext->authnContextClassRef) == 1);
52
    assert($requestAuthnContext->authnContextClassRef[0] == LASSO_LIB_AUTHN_CONTEXT_CLASS_REF_PASSWORD);
53

  
54
    echo "OK.\n";
55
}
56

  
57
function test03() {
58
    echo "Get and set a list of xmlNode*... ";
59

  
60
    $server = new LassoServer(
61
        DATA_DIR . "sp1-la/metadata.xml",
62
        DATA_DIR . "sp1-la/private-key-raw.pem",
63
        NULL,
64
        DATA_DIR . "sp1-la/certificate.pem");
65
    $server->addProvider(
66
        LASSO_PROVIDER_ROLE_IDP,
67
        DATA_DIR . "idp1-la/metadata.xml",
68
        DATA_DIR . "idp1-la/public-key.pem",
69
        DATA_DIR . "idp1-la/certificate.pem");
70
    $login = new LassoLogin($server);
71
    $login->initAuthnRequest();
72
    $requestAuthnContext = new LassoLibRequestAuthnContext();
73
    $extension1 = '<lib:Extension xmlns:lib="urn:liberty:iff:2003-08">
74
    <action>do</action>
75
</lib:Extension>';
76
	$extension2 = '<lib:Extension xmlns:lib="urn:liberty:iff:2003-08">
77
    <action2>do action 2</action2><action3>do action 3</action3>
78
</lib:Extension>';
79
    $extensionList = array($extension1, $extension2);
80
    $login->request->extension = $extensionList;
81
    assert($login->request->extension == $extensionList);
82
    assert($login->request->extension[0] == $extension1);
83
    assert($login->request->extension[1] == $extension2);
84

  
85
    echo "OK.\n";
86
}
87

  
88
function test04() {
89
    echo "Get and set a list of Lasso objects... ";
90

  
91
    $response = new LassoSamlpResponse();
92
    assert(!$response->assertion);
93

  
94
    $assertions = array();
95
    $assertion1 = new LassoSamlAssertion();
96
    $assertion1->assertionId = "assertion 1";
97
    $assertions[] = $assertion1;
98
    assert($assertions[0]->assertionId == "assertion 1");
99
    $assertion2 = new LassoSamlAssertion();
100
    $assertion2->assertionId = "assertion 2";
101
    $assertions[] = $assertion2;
102
    $response->assertion = $assertions;
103
    assert($response->assertion[0]->assertionId == "assertion 1");
104
    assert($response->assertion[1]->assertionId == "assertion 2");
105
    unset($assertions);
106
    assert($response->assertion[0]->assertionId == "assertion 1");
107
    assert($response->assertion[1]->assertionId == "assertion 2");
108
    $assertions = $response->assertion;
109
    assert($assertions[0]->assertionId == "assertion 1");
110
    assert($assertions[1]->assertionId == "assertion 2");
111

  
112
    echo "OK.\n";
113
}
114

  
115
function test05() {
116
    echo "Get and set a hashtable of objects... ";
117

  
118
    $server = new LassoServer(
119
        DATA_DIR . "sp1-la/metadata.xml",
120
        DATA_DIR . "sp1-la/private-key-raw.pem",
121
        NULL,
122
        DATA_DIR . "sp1-la/certificate.pem");
123
    $server->addProvider(
124
        LASSO_PROVIDER_ROLE_IDP,
125
        DATA_DIR . "idp1-la/metadata.xml",
126
        DATA_DIR . "idp1-la/public-key.pem",
127
        DATA_DIR . "idp1-la/certificate.pem");
128
    assert(!is_null($server->providers));
129
    assert($server->providers["https://idp1/metadata"]->providerId == "https://idp1/metadata");
130
    assert($server->providers["https://idp1/metadata"]->providerId == "https://idp1/metadata");
131
    $tmp_providers = $server->providers;
132
    $server->providers = NULL;
133
    assert(!$server->providers);
134
    $server->providers = $tmp_providers;
135
    $provider = $server->providers["https://idp1/metadata"];
136
    assert($server->providers["https://idp1/metadata"]->providerId == "https://idp1/metadata");
137

  
138
    echo "OK.\n";
139
}
140

  
141
function test06() {
142
    echo "Get and set SAML 2.0 assertion attribute values... ";
143

  
144
    $attribute1_name = "first attribute";
145
    $attribute1_string = "first string";
146
    $attribute2_name = "second attribute";
147
    $attribute2_string = "second string";
148
    $attribute3_string = "third string";
149

  
150
    $expected_assertion_dump = '<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" SignType="0" SignMethod="0" EncryptionActivated="false" EncryptionSymKeyType="0"><saml:AttributeStatement><saml:Attribute Name="first attribute"><saml:AttributeValue><XXX>first string</XXX></saml:AttributeValue></saml:Attribute><saml:Attribute Name="second attribute"><saml:AttributeValue><XXX>second string</XXX></saml:AttributeValue><saml:AttributeValue><XXX>third string</XXX></saml:AttributeValue></saml:Attribute></saml:AttributeStatement></saml:Assertion>';
151

  
152
    $text_node1 = new LassoMiscTextNode();
153
    $text_node1->content = $attribute1_string;
154
    $any1 = array();
155
    $any1[] = $text_node1;
156
    $attribute_value1 = new LassoSaml2AttributeValue();
157
    $attribute_value1->any = $any1;
158
    $attribute_values1 = array();
159
    $attribute_values1[] = $attribute_value1;
160
    $attribute1 = new LassoSaml2Attribute();
161
    $attribute1->name = $attribute1_name;
162
    $attribute1->attributeValue = $attribute_values1;
163

  
164
    $text_node2 = new LassoMiscTextNode();
165
    $text_node2->content = $attribute2_string;
166
    $any2 = array();
167
    $any2[] = $text_node2;
168
    $attribute_value2 = new LassoSaml2AttributeValue();
169
    $attribute_value2->any = $any2;
170

  
171
    $text_node3 = new LassoMiscTextNode();
172
    $text_node3->content = $attribute3_string;
173
    $any3 = array();
174
    $any3[] = $text_node3;
175
    $attribute_value3 = new LassoSaml2AttributeValue();
176
    $attribute_value3->any = $any3;
177

  
178
    $attribute_values2 = array();
179
    $attribute_values2[] = $attribute_value2;
180
    $attribute_values2[] = $attribute_value3;
181

  
182
    $attribute2 = new LassoSaml2Attribute();
183
    $attribute2->name = $attribute2_name;
184
    $attribute2->attributeValue = $attribute_values2;
185

  
186
    $attributes = array();
187
    $attributes[] = $attribute1;
188
    $attributes[] = $attribute2;
189

  
190
    $attributeStatement = new LassoSaml2AttributeStatement();
191
    $attributeStatement->attribute = $attributes;
192
    $attributeStatements = array();
193
    $attributeStatements[] = $attributeStatement;
194

  
195
    $assertion = new LassoSaml2Assertion();
196
    $assertion->attributeStatement = $attributeStatements;
197

  
198
    assert($assertion->dump() == $expected_assertion_dump);
199

  
200
    echo "OK.\n";
201
}
202

  
203
lasso_init();
204
test01();
205
test02();
206
test03();
207
test04();
208
//test05();
209
test06();
210
lasso_shutdown();
211

  
bindings/php7/tests/binding_tests.sh
1
#!/bin/sh
2

  
3
${PHP7:?PHP7 variable is not defined} -n -d extension_dir=../.libs -d extension=lasso.so ${SRCDIR}binding_tests.php
bindings/php7/tests/profile_tests.php
1
#!/usr/bin/php
2
<?php
3
# Lasso - A free implementation of the Liberty Alliance specifications.
4
# 
5
# Copyright (C) 2004-2007 Entr'ouvert
6
# http://lasso.entrouvert.org
7
#
8
# Authors: See AUTHORS file in top-level directory.
9
#
10
# This program is free software; you can redistribute it and/or modify
11
# it under the terms of the GNU General Public License as published by
12
# the Free Software Foundation; either version 2 of the License, or
13
# (at your option) any later version.
14
# 
15
# This program is distributed in the hope that it will be useful,
16
# but WITHOUT ANY WARRANTY; without even the implied warranty of
17
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
# GNU General Public License for more details.
19
# 
20
# You should have received a copy of the GNU General Public License
21
# along with this program; if not, see <http://www.gnu.org/licenses/>.
22

  
23
require("../lasso.php");
24

  
25
define(DATA_DIR, getenv('SRCDIR') . '../../../tests/data/');
26

  
27
function test01() {
28
    echo "Server construction, dump & newFromDump... ";
29

  
30
    $server = new LassoServer(
31
        DATA_DIR . "sp1-la/metadata.xml",
32
        DATA_DIR . "sp1-la/private-key-raw.pem",
33
        NULL,
34
        DATA_DIR . "sp1-la/certificate.pem");
35
    $server->addProvider(
36
        LASSO_PROVIDER_ROLE_IDP,
37
        DATA_DIR . "idp1-la/metadata.xml",
38
        DATA_DIR . "idp1-la/public-key.pem",
39
        DATA_DIR . "idp1-la/certificate.pem");
40

  
41
    $dump = $server->dump();
42
    assert(! is_null($dump));
43
    assert($dump != "");
44
    $server2 = LassoServer::newFromDump($dump);
45
    $dump2 = $server2->dump();
46
    assert($dump == $dump2);
47

  
48
    echo "OK.\n";
49
}
50

  
51
function test02() {
52
    echo "Server construction with no optional argument, dump & newFromDump... ";
53

  
54
    $server = new LassoServer(DATA_DIR . "sp1-la/metadata.xml");
55
    $server->addProvider(
56
        LASSO_PROVIDER_ROLE_IDP,
57
        DATA_DIR . "idp1-la/metadata.xml",
58
        DATA_DIR . "idp1-la/public-key.pem",
59
        DATA_DIR . "idp1-la/certificate.pem");
60

  
61
    $dump = $server->dump();
62
    $server2 = LassoServer::newFromDump($dump);
63
    $dump2 = $server2->dump();
64
    assert($dump == $dump2);
65

  
66
    echo "OK.\n";
67
}
68

  
69
function test03() {
70
    echo "SP login; testing access to authentication request... ";
71

  
72
    $server = new LassoServer(
73
        DATA_DIR . "sp1-la/metadata.xml",
74
        DATA_DIR . "sp1-la/private-key-raw.pem",
75
        NULL,
76
        DATA_DIR . "sp1-la/certificate.pem");
77
    $server->addProvider(
78
        LASSO_PROVIDER_ROLE_IDP,
79
        DATA_DIR . "idp1-la/metadata.xml",
80
        DATA_DIR . "idp1-la/public-key.pem",
81
        DATA_DIR . "idp1-la/certificate.pem");
82

  
83
    $login = new LassoLogin($server);
84
    $result = $login->initAuthnRequest();
85
    assert(! is_null($login->request));
86
    assert(get_class($login->request) == "LassoLibAuthnRequestNoInit");
87
    $dump = $login->request->dump();
88
    $login->request->protocolProfile = LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART;
89
    assert($login->request->protocolProfile == LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART);
90
    $dump2 = $login->request->dump();
91
    assert($dump != $dump2);
92

  
93
    echo "OK.\n";
94
}
95

  
96
function test04() {
97
    echo "SP login; testing processing of an empty Response... ";
98

  
99
    $server = new LassoServer(
100
        DATA_DIR . "sp1-la/metadata.xml",
101
        DATA_DIR . "sp1-la/private-key-raw.pem",
102
        NULL,
103
        DATA_DIR . "sp1-la/certificate.pem");
104
    $server->addProvider(
105
        LASSO_PROVIDER_ROLE_IDP,
106
        DATA_DIR . "idp1-la/metadata.xml",
107
        DATA_DIR . "idp1-la/public-key.pem",
108
        DATA_DIR . "idp1-la/certificate.pem");
109

  
110
    $login = new LassoLogin($server);
111
    try {
112
        $login->processResponseMsg("");
113
    }
114
    catch (LassoProfileInvalidMsgError $error) {
115
    }
116

  
117
    echo "OK.\n";
118
}
119

  
120
function test05() {
121
    echo "Conversion of a lib:AuthnRequest with an AuthnContext into a query and back... ";
122

  
123
    $spServer = new LassoServer(
124
        DATA_DIR . "sp1-la/metadata.xml",
125
        DATA_DIR . "sp1-la/private-key-raw.pem",
126
        NULL,
127
        DATA_DIR . "sp1-la/certificate.pem");
128
    $spServer->addProvider(
129
        LASSO_PROVIDER_ROLE_IDP,
130
        DATA_DIR . "idp1-la/metadata.xml",
131
        DATA_DIR . "idp1-la/public-key.pem",
132
        DATA_DIR . "idp1-la/certificate.pem");
133

  
134
    $spLogin = new LassoLogin($spServer);
135
    $spLogin->initAuthnRequest();
136
    $requestAuthnContext = new LassoLibRequestAuthnContext();
137
    $requestAuthnContext->authnContextClassRef = array(LASSO_LIB_AUTHN_CONTEXT_CLASS_REF_PASSWORD);
138
    assert($requestAuthnContext->authnContextClassRef[0] == LASSO_LIB_AUTHN_CONTEXT_CLASS_REF_PASSWORD);
139
    $spLogin->request->requestAuthnContext = $requestAuthnContext;
140
    assert(! is_null($spLogin->request->requestAuthnContext));
141
    $spLogin->request->protocolProfile = LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART;
142
    assert($spLogin->request->protocolProfile == LASSO_LIB_PROTOCOL_PROFILE_BRWS_ART);
143
    $spLogin->buildAuthnRequestMsg();
144
    assert(! is_null($spLogin->msgUrl));
145
    assert($spLogin->msgUrl != "");
146

  
147
    $idpServer = new LassoServer(
148
        DATA_DIR . "idp1-la/metadata.xml",
149
        DATA_DIR . "idp1-la/private-key-raw.pem",
150
        NULL,
151
        DATA_DIR . "idp1-la/certificate.pem");
152
    $idpServer->addProvider(
153
        LASSO_PROVIDER_ROLE_IDP,
154
        DATA_DIR . "sp1-la/metadata.xml",
155
        DATA_DIR . "sp1-la/public-key.pem",
156
        DATA_DIR . "sp1-la/certificate.pem");
157

  
158
    $idpLogin = new LassoLogin($idpServer);
159
    list($urlBase, $authnRequestQuery) = explode("?", $spLogin->msgUrl, 2);
160
    assert($authnRequestQuery != "");
161
    $idpLogin->processAuthnRequestMsg($authnRequestQuery);
162
    assert(! is_null($idpLogin->request));
163
    assert(! is_null($idpLogin->request->requestAuthnContext));
164
    assert($idpLogin->request->requestAuthnContext != "");
165
    assert(sizeof($idpLogin->request->requestAuthnContext->authnContextClassRef) == 1);
166
    assert($idpLogin->request->requestAuthnContext->authnContextClassRef[0] ==
167
        LASSO_LIB_AUTHN_CONTEXT_CLASS_REF_PASSWORD);
168

  
169
    echo "OK.\n";
170
}
171

  
172
function test06() {
173
    echo "SP logout without session and identity; testing initRequest... ";
174

  
175
    $server = new LassoServer(
176
        DATA_DIR . "sp1-la/metadata.xml",
177
        DATA_DIR . "sp1-la/private-key-raw.pem",
178
        NULL,
179
        DATA_DIR . "sp1-la/certificate.pem");
180
    $server->addProvider(
181
        LASSO_PROVIDER_ROLE_IDP,
182
        DATA_DIR . "idp1-la/metadata.xml",
183
        DATA_DIR . "idp1-la/public-key.pem",
184
        DATA_DIR . "idp1-la/certificate.pem");
185

  
186
    $logout = new LassoLogout($server);
187
    try {
188
        $logout->initRequest();
189
        echo "logout.initRequest without having set identity before should fail\n";
190
        assert(False);
191
    }
192
    catch (LassoProfileSessionNotFoundError $error) {
193
    }
194

  
195
    echo "OK.\n";
196
}
197

  
198
function test07() {
199
    echo "IDP logout without session and identity; testing logout.getNextProviderId... ";
200

  
201
    $server = new LassoServer(
202
        DATA_DIR . "idp1-la/metadata.xml",
203
        DATA_DIR . "idp1-la/private-key-raw.pem",
204
        NULL,
205
        DATA_DIR . "idp1-la/certificate.pem");
206
    $server->addProvider(
207
        LASSO_PROVIDER_ROLE_IDP,
208
        DATA_DIR . "sp1-la/metadata.xml",
209
        DATA_DIR . "sp1-la/public-key.pem",
210
        DATA_DIR . "sp1-la/certificate.pem");
211

  
212
    $logout = new LassoLogout($server);
213
    assert(is_null($logout->next_providerID));
214

  
215
    echo "OK.\n";
216
}
217

  
218
test01();
219
test02();
220
test03();
221
test04();
222
test05();
223
test06();
224
test07();
bindings/php7/tests/profile_tests.sh
1
#!/bin/sh
2

  
3
${PHP7:?PHP7 variable is not defined} -n -d extension_dir=../.libs -d extension=lasso.so ${SRCDIR}profile_tests.php
bindings/php7/wrapper_header.py
1
# Lasso - A free implementation of the Liberty Alliance specifications.
2
#
3
# Copyright (C) 2004-2007 Entr'ouvert
4
# http://lasso.entrouvert.org
5
#
6
# Authors: See AUTHORS file in top-level directory.
7
#
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, see <http://www.gnu.org/licenses/>.
20
import six
21

  
22
class WrapperHeader:
23
    def __init__(self, binding_data, fd, functions_list):
24
        self.binding_data = binding_data
25
        self.fd = fd
26
        self.functions_list = functions_list
27

  
28
    def generate(self):
29
        self.generate_header()
30
        self.generate_functions_list()
31
        self.generate_footer()
32

  
33
    def generate_header(self):
34
        # FIXME: Get the current version and name
35
        six.print_('''\
36
/* this file has been generated automatically; do not edit */
37

  
38
#include "../../config.h"
39

  
40
#ifndef PHP_LASSO_H
41
#define PHP_LASSO_H 1
42

  
43
#define PHP_LASSO_EXTNAME "lasso"
44
#define PHP_LASSO_VERSION VERSION
45

  
46
#define PHP_LASSO_SERVER_RES_NAME "Lasso Server"
47

  
48
PHP_MINIT_FUNCTION(lasso);
49
PHP_MSHUTDOWN_FUNCTION(lasso);
50
''', file=self.fd)
51

  
52
    def generate_functions_list(self):
53
        for m in self.functions_list:
54
            six.print_('PHP_FUNCTION(%s);' % m, file=self.fd)
55
        six.print_('', file=self.fd)
56

  
57
    def generate_footer(self):
58
        six.print_('''\
59
extern zend_module_entry lasso_module_entry;
60
#define phpext_lasso_ptr &lasso_module_entry
61

  
62
#endif
63
''', file=self.fd)
64

  
bindings/php7/wrapper_source.py
1
# Lasso - A free implementation of the Liberty Alliance specifications.
2
#
3
# Copyright (C) 2004-2007 Entr'ouvert
4
# http://lasso.entrouvert.org
5
#
6
# Authors: See AUTHORS file in top-level directory.
7
#
8
# This program is free software; you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 2 of the License, or
11
# (at your option) any later version.
12
#
13
# This program is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with this program; if not, see <http://www.gnu.org/licenses/>.
20

  
21
import sys
22
import os
23
import six
24

  
25
from utils import *
26

  
27
class WrapperSource:
28
    def __init__(self, binding_data, fd):
29
        self.binding_data = binding_data
30
        self.fd = fd
31
        self.functions_list = []
32
        self.src_dir = os.path.dirname(__file__)
33

  
34
    def is_object(self, t):
35
        return t not in ['char*', 'const char*', 'gchar*', 'const gchar*', 'GList*', 'GHashTable*', 'GType',
36
                'xmlNode*', 'int', 'gint', 'gboolean', 'const gboolean'] + self.binding_data.enums
37

  
38
    def generate(self):
39
        self.generate_header()
40
        self.generate_constants()
41
        self.generate_middle()
42
        for m in self.binding_data.functions:
43
            self.generate_function(m)
44
        for c in self.binding_data.structs:
45
            self.generate_members(c)
46
            for m in c.methods:
47
                self.generate_function(m)
48
        self.generate_functions_list()
49
        self.generate_footer()
50

  
51
    def generate_header(self):
52
        self.functions_list.append('lasso_get_object_typename')
53
        self.functions_list.append('lasso_init')
54
        self.functions_list.append('lasso_shutdown')
55

  
56
        six.print_('''\
57
/* this file has been generated automatically; do not edit */
58
''', file=self.fd)
59

  
60
        six.print_(open(os.path.join(self.src_dir,'wrapper_source_top.c')).read(), file=self.fd)
61

  
62
        for h in self.binding_data.headers:
63
            six.print_('#include <%s>' % h, file=self.fd)
64
        six.print_('', file=self.fd)
65

  
66
        six.print_('''\
67
PHP_MINIT_FUNCTION(lasso)
68
{
69
    le_lasso_server = zend_register_list_destructors_ex(php_gobject_generic_destructor, NULL, PHP_LASSO_SERVER_RES_NAME, module_number);
70
    lasso_init();
71
''', file=self.fd)
72

  
73
    def generate_constants(self):
74
        six.print_('    /* Constants (both enums and defines) */', file=self.fd)
75
        for c in self.binding_data.constants:
76
            if c[0] == 'i':
77
                six.print_('    REGISTER_LONG_CONSTANT("%s", %s, CONST_CS|CONST_PERSISTENT);' % (c[1], c[1]), file=self.fd)
78
            elif c[0] == 's':
79
                six.print_('    REGISTER_STRING_CONSTANT("%s", (char*) %s, CONST_CS|CONST_PERSISTENT);' % (c[1], c[1]), file=self.fd)
80
            elif c[0] == 'b':
81
                six.print_('''\
82
#ifdef %s
83
    REGISTER_LONG_CONSTANT("%s", 1, CONST_CS|CONST_PERSISTENT);
84
#else
85
    REGISTER_LONG_CONSTANT("%s", 0, CONST_CS|CONST_PERSISTENT);
86
#endif''' % (c[1], c[1], c[1]), file=self.fd)
87
            else:
88
                six.print_('E: unknown constant type: %r' % c[0], file=sys.stderr)
89
        six.print_('', file=self.fd)
90

  
91
    def generate_middle(self):
92
        six.print_('''\
93
    return SUCCESS;
94
}
95

  
96
PHP_MSHUTDOWN_FUNCTION(lasso)
97
{
98
    lasso_shutdown();
99
    return SUCCESS;
100
}
101

  
102
''', file=self.fd)
103

  
104
    def set_zval(self, zval_name, c_variable, type, free = False):
105
        '''Emit code to set a zval* of name zval_name, from the value of the C variable called c_variable type, type.
106
        '''
107
        # first we free the previous value
108
        p = (zval_name, c_variable)
109
        q = { 'zval_name' : zval_name, 'c_variable' : c_variable }
110
        six.print_('    zval_dtor(%s);' % zval_name, file=self.fd)
111
        if is_pointer(type):
112
            six.print_('    if (! %s) {' % c_variable, file=self.fd)
113
            six.print_('       ZVAL_NULL(%s);' % zval_name, file=self.fd)
114
            six.print_('    } else {', file=self.fd)
115
        if is_int(type, self.binding_data):
116
            six.print_('    ZVAL_LONG(%s, %s);' % p, file=self.fd)
117
        elif is_boolean(type):
118
            six.print_('    ZVAL_BOOL(%s, %s);' % p, file=self.fd)
119
        elif is_cstring(type):
120
            six.print_('    ZVAL_STRING(%s, (char*)%s);' % p, file=self.fd)
121
            if free and not is_const(type):
122
                six.print_('g_free(%s)' % c_variable, file=self.fd)
123
        elif arg_type(type) == 'xmlNode*':
124
            six.print_('''\
125
    {
126
        char* xmlString = get_string_from_xml_node(%(c_variable)s);
127
        if (xmlString) {
128
            ZVAL_STRING(%(zval_name)s, xmlString);
129
        } else {
130
            ZVAL_NULL(%(zval_name)s);
131
        }
132
    }
133
''' % q, file=self.fd)
134
        elif is_glist(type):
135
            elem_type = make_arg(element_type(type))
136
            if not arg_type(elem_type):
137
                raise Exception('unknown element-type: ' + repr(type))
138
            if is_cstring(elem_type):
139
                function = 'set_array_from_list_of_strings'
140
                free_function = 'free_glist(&%(c_variable)s, (GFunc)free);'
141
            elif arg_type(elem_type).startswith('xmlNode'):
142
                function = 'set_array_from_list_of_xmlnodes'
143
                free_function = 'free_glist(&%(c_variable)s, (GFunc)xmlFree);'
144
            elif is_object(elem_type):
145
                function = 'set_array_from_list_of_objects'
146
                free_function = 'g_list_free(%(c_variable)s);'
147
            else:
148
                raise Exception('unknown element-type: ' + repr(type))
149
            six.print_('     %s((GList*)%s, &%s);' % (function, c_variable, zval_name), file=self.fd)
150
            if free:
151
                six.print_('   ', free_function % q, file=self.fd)
152
        elif is_object(type):
153
            six.print_('''\
154
    if (G_IS_OBJECT(%(c_variable)s)) {
155
        PhpGObjectPtr *obj = PhpGObjectPtr_New(G_OBJECT(%(c_variable)s));
156
        zend_resource *res = zend_register_resource(obj, le_lasso_server);
157
        ZVAL_RES(%(zval_name)s, res);
158
    } else {
159
        ZVAL_NULL(%(zval_name)s);
160
    }''' % q, file=self.fd)
161
            if free:
162
                six.print_('''\
163
    if (%(c_variable)s) {
164
        g_object_unref(%(c_variable)s); // If constructor ref is off by one'
165
    }''' % q, file=self.fd)
166

  
167
        else:
168
            raise Exception('unknown type: ' + repr(type) + unconstify(arg_type(type)))
169
        if is_pointer(type):
170
            six.print_('    }', file=self.fd)
171

  
172

  
173

  
174
    def return_value(self, arg, free = False):
175
        if arg is None:
176
            return
177

  
178
        if is_boolean(arg):
179
            six.print_('    RETVAL_BOOL(return_c_value);', file=self.fd)
180
        elif is_int(arg, self.binding_data):
181
            six.print_('    RETVAL_LONG(return_c_value);', file=self.fd)
182
        elif is_cstring(arg):
183
            six.print_('''\
184
    if (return_c_value) {
185
        RETVAL_STRING((char*)return_c_value);
186
    } else {
187
        RETVAL_NULL();
188
    }''', file=self.fd)
189
            if free:
190
                six.print_('    free(return_c_value);', file=self.fd)
191
        elif is_xml_node(arg):
192
            six.print_('''\
193
    {
194
        char* xmlString = get_string_from_xml_node(return_c_value);
195
        if (xmlString) {
196
            RETVAL_STRING(xmlString);
197
        } else {
198
            RETVAL_NULL();
199
        }
200
    }
201
''', file=self.fd)
202
            if free:
203
                six.print_('    lasso_release_xml_node(return_c_value);', file=self.fd)
204
        elif is_glist(arg):
205
            el_type = element_type(arg)
206
            if is_cstring(el_type):
207
                six.print_('''\
208
    set_array_from_list_of_strings((GList*)return_c_value, &return_value);
209
''', file=self.fd)
210
                if free:
211
                    six.print_('    lasso_release_list_of_strings(return_c_value);', file=self.fd)
212
            elif is_xml_node(el_type):
213
                six.print_('''\
214
    set_array_from_list_of_xmlnodes((GList*)return_c_value, &return_value);
215
''', file=self.fd)
216
                if free or is_transfer_full(arg):
217
                    six.print_('    lasso_release_list_of_xml_node(return_c_value);', file=self.fd)
218
            elif is_object(el_type):
219
                six.print_('''\
220
    set_array_from_list_of_objects((GList*)return_c_value, &return_value);
221
''', file=self.fd)
222
                if free:
223
                    six.print_('    lasso_release_list_of_gobjects(return_c_value);', file=self.fd)
224
            else:
225
                raise Exception('cannot return value for %s' % (arg,))
226
        elif is_hashtable(arg):
227
            el_type = element_type(arg)
228
            if is_object(el_type):
229
                six.print_('''\
230
    set_array_from_hashtable_of_objects(return_c_value, &return_value);
231
''', file=self.fd)
232
            else:
233
                if not is_cstring(arg):
234
                    print >>sys.stderr, 'W: %s has no explicit string annotation' % (arg,)
235
                six.print_('''\
236
    set_array_from_hashtable_of_strings(return_c_value, &return_value);
237
''', file=self.fd)
238
        elif is_object(arg):
239
            six.print_('''\
240
    if (return_c_value) {
241
        PhpGObjectPtr *self;
242
        self = PhpGObjectPtr_New(G_OBJECT(return_c_value));
243
        zend_resource *res = zend_register_resource(self, le_lasso_server);
244
        ZVAL_RES(return_value, res);
245
    } else {
246
        RETVAL_NULL();
247
    }''', file=self.fd)
248
            if free:
249
                six.print_('    lasso_release_gobject(return_c_value);', file=self.fd)
250
        else:
251
            raise Exception('cannot return value for %s' % (arg,))
252

  
253
    def generate_function(self, m):
254
        if m.name in ('lasso_init','lasso_shutdown'):
255
            return
256
        if m.rename:
257
            name = m.rename
258
        else:
259
            name = m.name
260
        self.functions_list.append(name)
261
        six.print_('''PHP_FUNCTION(%s)
262
{''' % name, file=self.fd)
263
        parse_tuple_format = []
264
        parse_tuple_args = []
265
        for arg in m.args:
266
            if is_out(arg):
267
                six.print_('   zval *php_out_%s = NULL;' % arg_name(arg), file=self.fd)
268
                six.print_('   %s %s;' % (var_type(arg), arg_name(arg)), file=self.fd)
269
                parse_tuple_format.append('z!')
270
                parse_tuple_args.append('&php_out_%s' % arg_name(arg))
271
            elif is_cstring(arg):
272
                parse_tuple_format.append('s!')
273
                parse_tuple_args.append('&%s_str, &%s_len' % (arg_name(arg), arg_name(arg)))
274
                six.print_('    %s %s = NULL;' % ('char*', arg_name(arg)), file=self.fd)
275
                six.print_('    %s %s_str = NULL;' % ('char*', arg_name(arg)), file=self.fd)
276
                six.print_('    %s %s_len = 0;' % ('size_t', arg_name(arg)), file=self.fd)
277
            elif is_int(arg, self.binding_data) or is_boolean(arg):
278
                parse_tuple_format.append('l')
279
                parse_tuple_args.append('&%s' % arg_name(arg))
280
                six.print_('    %s %s;' % ('long', arg_name(arg)), file=self.fd)
281
            elif is_time_t_pointer(arg):
282
                parse_tuple_format.append('l')
283
                parse_tuple_args.append('&%s' % (arg_name(arg),))
284
                print >>self.fd,  '    time_t %s = 0;' % (arg_name(arg),)
285
            elif is_xml_node(arg):
286
                parse_tuple_format.append('s!')
287
                parse_tuple_args.append('&%s_str, &%s_len' % (arg_name(arg), arg_name(arg)))
288
                six.print_('    %s %s = NULL;' % ('xmlNode*', arg_name(arg)), file=self.fd)
289
                six.print_('    %s %s_str = NULL;'  % ('char*', arg_name(arg)), file=self.fd)
290
                six.print_('    %s %s_len = 0;' % ('size_t', arg_name(arg)), file=self.fd)
291
            elif is_glist(arg):
292
                parse_tuple_format.append('a!')
293
                parse_tuple_args.append('&zval_%s' % arg_name(arg))
294
                six.print_('    %s zval_%s = NULL;' % ('zval*', arg_name(arg)), file=self.fd)
295
                six.print_('    %s %s = NULL;' % ('GList*', arg_name(arg)), file=self.fd)
296
            elif is_object(arg):
297
                parse_tuple_format.append('r')
298
                parse_tuple_args.append('&zval_%s' % arg_name(arg))
299
                six.print_('    %s %s = NULL;' % (arg_type(arg), arg_name(arg)), file=self.fd)
300
                six.print_('    %s zval_%s = NULL;' % ('zval*', arg_name(arg)), file=self.fd)
301
                six.print_('    %s cvt_%s = NULL;' % ('PhpGObjectPtr*', arg_name(arg)), file=self.fd)
302
            else:
303
                raise Exception('Unsupported type %s %s' % (arg, m))
304

  
305
        if m.return_type:
306
            six.print_('    %s return_c_value;' % m.return_type, file=self.fd)
307
        if m.return_type is not None and self.is_object(m.return_arg):
308
            six.print_('    G_GNUC_UNUSED PhpGObjectPtr *self;', file=self.fd)
309
        six.print_('', file=self.fd)
310

  
311
        parse_tuple_args = ', '.join(parse_tuple_args)
312
        if parse_tuple_args:
313
            parse_tuple_args = ', ' + parse_tuple_args
314

  
315
        six.print_('''\
316
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "%s"%s) == FAILURE) {
317
        RETURN_FALSE;
318
    }
319
''' % (''.join(parse_tuple_format), parse_tuple_args), file=self.fd)
320

  
321
        for f, arg in zip(parse_tuple_format, m.args):
322
            if is_out(arg):
323
                continue
324
            elif is_xml_node(arg):
325
                six.print_('''\
326
        %(name)s = get_xml_node_from_string(%(name)s_str);''' % {'name': arg[1]}, file=self.fd)
327
            elif f.startswith('s'):
328
                six.print_('''\
329
        %(name)s = %(name)s_str;''' % {'name': arg[1]}, file=self.fd)
330
            elif f.startswith('r'):
331
                six.print_('    if ((cvt_%s = (PhpGObjectPtr *)zend_fetch_resource(Z_RES_P(zval_%s), PHP_LASSO_SERVER_RES_NAME, le_lasso_server)) == NULL) {' % (arg[1], arg[1]), file=self.fd)
332
                six.print_('        RETURN_FALSE;', file=self.fd)
333
                six.print_('    }', file=self.fd)
334
                six.print_('    %s = (%s)cvt_%s->obj;' % (arg[1], arg[0], arg[1]), file=self.fd)
335
            elif f.startswith('a'):
336
                el_type = element_type(arg)
337
                if is_cstring(el_type):
338
                    six.print_('    %(name)s = get_list_from_array_of_strings(zval_%(name)s);' % {'name': arg[1]}, file=self.fd)
339
                elif is_object(el_type):
340
                    six.print_('    %(name)s = get_list_from_array_of_objects(zval_%(name)s);' % {'name': arg[1]}, file=self.fd)
341
                else:
342
                    six.print_('E: In %(function)s arg %(name)s is of type GList<%(elem)s>' % { 'function': m.name, 'name': arg[1], 'elem': el_type }, file=sys.stderr)
343
            elif f == 'l':
344
                pass
345
            else:
346
                raise Exception('%s format inconnu' % f)
347

  
348

  
349
        if m.return_type is not None:
350
            six.print_('    return_c_value = ', file=self.fd)
351
            if 'new' in m.name:
352
                six.print_('(%s)' % m.return_type, file=self.fd)
353
        else:
354
            six.print_('   ', file=self.fd)
355
        def special(x):
356
            if is_time_t_pointer(x):
357
                return '%(name)s ? &%(name)s : NULL' % { 'name': arg_name(x) }
358
            else:
359
                return ref_name(x)
360
        six.print_('%s(%s);' % (m.name, ', '.join([special(x) for x in m.args])), file=self.fd)
361
        # Free the converted arguments
362

  
363
        for f, arg in zip(parse_tuple_format, m.args):
364
            argtype, argname, argoptions = arg
365
            if is_out(arg):
366
                # export the returned variable
367
                free = is_transfer_full(unref_type(arg))
368
                self.set_zval('php_out_%s' % argname, argname, unref_type(arg), free = free)
369
                pass
370
            elif argtype == 'xmlNode*':
371
                six.print_('    xmlFree(%s);' % argname, file=self.fd)
372
            elif f.startswith('a'):
373
                el_type = element_type(arg)
374
                if is_cstring(el_type):
375
                    six.print_('    if (%(name)s) {' % { 'name': arg[1] }, file=self.fd)
376
                    six.print_('        free_glist(&%(name)s,(GFunc)free);' % { 'name': arg[1] }, file=self.fd)
377
                    six.print_('    }', file=self.fd)
378

  
379
        try:
380
            self.return_value(m.return_arg, is_transfer_full(m.return_arg, default=True))
381
        except:
382
            raise Exception('Cannot return value for function %s' % m)
383

  
384
        six.print_('}', file=self.fd)
385
        six.print_('', file=self.fd)
386

  
387
    def generate_members(self, c):
388
        for m in c.members:
389
            self.generate_getter(c, m)
390
            self.generate_setter(c, m)
391

  
392
    def generate_getter(self, c, m):
393
        klassname = c.name
394
        name = arg_name(m)
395
        type = arg_type(m)
396

  
397
        function_name = '%s_%s_get' % (klassname, format_as_camelcase(name))
398
        six.print_('''PHP_FUNCTION(%s)
399
{''' % function_name, file=self.fd)
400
        self.functions_list.append(function_name)
401

  
402
        six.print_('    %s return_c_value;' % type, file=self.fd)
403
        six.print_('    %s* this;' % klassname, file=self.fd)
404
        six.print_('    zval* zval_this;', file=self.fd)
405
        six.print_('    PhpGObjectPtr *cvt_this;', file=self.fd)
406
        six.print_('', file=self.fd)
407
        six.print_('''\
408
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zval_this) == FAILURE) {
409
        RETURN_FALSE;
410
    }
411

  
412
    if ((cvt_this = (PhpGObjectPtr *)zend_fetch_resource(Z_RES_P(zval_this), PHP_LASSO_SERVER_RES_NAME, le_lasso_server)) == NULL) {
413
        RETURN_FALSE;
414
    }
415
    this = (%s*)cvt_this->obj;
416
''' % (klassname), file=self.fd)
417
        six.print_('    return_c_value = (%s)this->%s;' % (type, name), file=self.fd)
418
        self.return_value(m)
419
        six.print_('}', file=self.fd)
420
        six.print_('', file=self.fd)
421

  
422
    def generate_setter(self, c, m):
423
        klassname = c.name
424
        name = arg_name(m)
425
        type = arg_type(m)
426
        function_name = '%s_%s_set' % (klassname, format_as_camelcase(name))
427
        six.print_('''PHP_FUNCTION(%s)
428
{''' % function_name, file=self.fd)
429
        self.functions_list.append(function_name)
430

  
431
        six.print_('    %s* this;' % klassname, file=self.fd)
432
        six.print_('    zval* zval_this;', file=self.fd)
433
        six.print_('    PhpGObjectPtr *cvt_this;', file=self.fd)
434

  
435
        # FIXME: This bloc should be factorised
436
        parse_tuple_format = ''
437
        parse_tuple_args = []
438
        if is_cstring(m) or is_xml_node(m):
439
            # arg_type = arg_type.replace('const ', '')
440
            parse_tuple_format += 's'
441
            parse_tuple_args.append('&%s_str, &%s_len' % (name, name))
442
            six.print_('    %s %s_str = NULL;' % ('char*', name), file=self.fd)
443
            six.print_('    %s %s_len = 0;' % ('size_t', name), file=self.fd)
444
        elif is_int(m, self.binding_data) or is_boolean(m):
445
            parse_tuple_format += 'l'
446
            parse_tuple_args.append('&%s' % name)
447
            six.print_('    %s %s;' % ('long', name), file=self.fd)
448
        # Must also handle lists of Objects
449
        elif is_glist(m) or is_hashtable(m):
450
            parse_tuple_format += 'a'
451
            parse_tuple_args.append('&zval_%s' % name)
452
            six.print_('    %s zval_%s;' % ('zval*', name), file=self.fd)
453
        elif is_object(m):
454
            parse_tuple_format += 'r'
455
            parse_tuple_args.append('&zval_%s' % name)
456
            six.print_('    %s zval_%s = NULL;' % ('zval*', name), file=self.fd)
457
            six.print_('    %s cvt_%s = NULL;' % ('PhpGObjectPtr*', name), file=self.fd)
458
        else:
459
            raise Exception('Cannot make a setter for %s.%s' % (c,m))
460

  
461
        if parse_tuple_args:
462
            parse_tuple_arg = parse_tuple_args[0]
463
        else:
464
            six.print_('}', file=self.fd)
465
            six.print_('', file=self.fd)
466
            return
467

  
468
        six.print_('', file=self.fd)
469
        six.print_('''\
470
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r%s", &zval_this, %s) == FAILURE) {
471
        return;
472
    }
473
''' % (parse_tuple_format, parse_tuple_arg), file=self.fd)
474

  
475
        # Get 'this' object
476
        six.print_('''\
477
    if ((cvt_this = (PhpGObjectPtr *)zend_fetch_resource(Z_RES_P(zval_this), PHP_LASSO_SERVER_RES_NAME, le_lasso_server)) == NULL) {
478
        RETURN_FALSE;
479
    }
480
    this = (%s*)cvt_this->obj;
481
''' % klassname, file=self.fd)
482

  
483
        # Set new value
484
        d = { 'name': name, 'type': type }
485
        if is_int(m, self.binding_data) or is_boolean(m):
486
            six.print_('    this->%s = %s;' % (name, name), file=self.fd)
487
        elif is_cstring(m):
488
            six.print_('    lasso_assign_string(this->%(name)s, %(name)s_str);' % d, file=self.fd)
489
        elif is_xml_node(m):
490
            six.print_('    lasso_assign_new_xml_node(this->%(name)s, get_xml_node_from_string(%(name)s_str));' % d, file=self.fd)
491
        elif is_glist(m):
492
            el_type = element_type(m)
493
            if is_cstring(el_type):
494
                six.print_('    lasso_assign_new_list_of_strings(this->%(name)s, get_list_from_array_of_strings(zval_%(name)s));' % d, file=self.fd)
495
            elif is_xml_node(el_type):
496
                six.print_('    lasso_assign_new_list_of_xml_node(this->%(name)s, get_list_from_array_of_xmlnodes(zval_%(name)s))' % d, file=self.fd)
497
            elif is_object(el_type):
498
                six.print_('    lasso_assign_new_list_of_gobjects(this->%(name)s, get_list_from_array_of_objects(zval_%(name)s));' % d, file=self.fd)
499
            else:
500
                raise Exception('Cannot create C setter for %s.%s' % (c,m))
501
        elif is_hashtable(m):
502
            el_type = element_type(m)
503
            six.print_('''\
504
        {
505
            GHashTable *oldhash = this->%(name)s;''' % d, file=self.fd)
506
            if is_object(el_type):
507
                six.print_('            this->%(name)s = get_hashtable_from_array_of_objects(zval_%(name)s);' % d, file=self.fd)
508
            else:
509
                six.print_('            this->%(name)s = get_hashtable_from_array_of_strings(zval_%(name)s);' % d, file=self.fd)
510
            six.print_('            g_hash_table_destroy(oldhash);', file=self.fd)
511
            six.print_('        }', file=self.fd)
512
        elif is_object(m):
513
            six.print_('    if ((cvt_%(name)s = (PhpGObjectPtr*)zend_fetch_resource(Z_RES_P(zval_%(name)s), PHP_LASSO_SERVER_RES_NAME, le_lasso_server)) == NULL) {' % d, file=self.fd)
514
            six.print_('        RETURN_FALSE;', file=self.fd)
515
            six.print_('    }', file=self.fd)
516
            six.print_('    lasso_assign_gobject(this->%(name)s, cvt_%(name)s->obj);' % d, file=self.fd)
517

  
518
        six.print_('}', file=self.fd)
519
        six.print_('', file=self.fd)
520

  
521
    def generate_functions_list(self):
522
        six.print_('''\
523
static zend_function_entry lasso_functions[] = {''', file=self.fd)
524
        for m in self.functions_list:
525
            six.print_('    PHP_FE(%s, NULL)' % m, file=self.fd)
526
        six.print_('''\
527
    {NULL, NULL, NULL, 0, 0}
528
};
529
''', file=self.fd)
530

  
531
    def generate_footer(self):
532
        six.print_('''\
533
zend_module_entry lasso_module_entry = {
534
#if ZEND_MODULE_API_NO >= 20010901
535
    STANDARD_MODULE_HEADER,
536
#endif
537
    PHP_LASSO_EXTNAME,
538
    lasso_functions,
539
    PHP_MINIT(lasso),
540
    PHP_MSHUTDOWN(lasso),
541
    NULL,
542
    NULL,
543
    NULL,
544
#if ZEND_MODULE_API_NO >= 20010901
545
    PHP_LASSO_VERSION,
546
#endif
547
    STANDARD_MODULE_PROPERTIES
548
};
549
''', file=self.fd)
550

  
bindings/php7/wrapper_source_top.c
1
#include <php.h>
2
#undef PACKAGE_BUGREPORT
3
#undef PACKAGE_NAME
4
#undef PACKAGE_STRING
5
#undef PACKAGE_TARNAME
6
#undef PACKAGE_VERSION
7
#include <lasso/lasso.h>
8
#include "php_lasso.h"
9
#include "../ghashtable.h"
10
#define LASSO_LOG_STATIC
11

  
12
#if defined(__GNUC__)
13
#  define lasso_log(level, filename, line, function, format, args...) \
14
        g_log("Lasso", level, "%s:%i:%s" format, filename, line, function, ##args)
15
#elif defined(HAVE_VARIADIC_MACROS)
16
#  define lasso_log(level, format, line, function, ...)  \
17
        g_log("Lasso", leve, "%s:%i:%s" format, filename, line, function, __VA_ARGS__)
18
#else
19
static inline void lasso_log(GLogLevelFlags level, const char *filename,
20
    int line, const char *function, const char *format, ...)
21
{
22
	va_list ap;
23
	char s[1024];
24
	va_start(ap, format);
25
	g_vsnprintf(s, 1024, format, ap);
26
	va_end(ap);
27
    g_log("Lasso", level, "%s:%i:%s %s", filename, line, function, s);
28
}
29
#define lasso_log lasso_log
30
#endif
31

  
32
#include "../../lasso/utils.h"
33
#include "../utils.c"
34

  
35
/* utility functions */
36
static void free_glist(GList **list, GFunc free_function);
37

  
38
/* Define the Lasso PHP module */
39

  
40
int le_lasso_server;
41

  
42
ZEND_GET_MODULE(lasso)
43

  
44
/* Wrapper around GObject to get the dynamic typename */
45

  
46
typedef struct {
47
	GObject *obj;
48
	char *typename;
49
} PhpGObjectPtr;
50

  
51
/** FIXME: implement caching of objects inside GObjects using a GQuark */
52
static PhpGObjectPtr*
53
PhpGObjectPtr_New(GObject *obj)
54
{
55
	PhpGObjectPtr *self;
56

  
57
	if (obj == NULL) {
58
		return NULL;
59
	}
60

  
61
	self = (PhpGObjectPtr *)malloc(sizeof(PhpGObjectPtr));
62
	self->obj = g_object_ref(obj);
63
	self->typename = strdup(G_OBJECT_TYPE_NAME(obj));
64
        //printf("Allocating container %p for object %p of type %s with refcnt %i\n", self, obj, self->typename, obj->ref_count);
65

  
66
	return self;
67
}
68
PHP_FUNCTION(lasso_init)
69
{
70
	RETURN_NULL();
71
}
72
PHP_FUNCTION(lasso_shutdown)
73
{
74
	RETURN_NULL();
75
}
76
PHP_FUNCTION(lasso_get_object_typename)
77
{
78
	PhpGObjectPtr *self;
79
	zval *zval_self;
80

  
81
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zval_self) == FAILURE) {
82
		RETURN_FALSE;
83
	}
84

  
85
	if ((self = (PhpGObjectPtr *)zend_fetch_resource(Z_RES_P(zval_self), PHP_LASSO_SERVER_RES_NAME, le_lasso_server)) == NULL) {
86
		RETURN_FALSE;
87
	}
88
	RETURN_STRING(self->typename);
89
}
90

  
91
/* Generic destructor for PHP GObject  */
92
static void php_gobject_generic_destructor(zend_resource *rsrc TSRMLS_DC)
93
{
94
    PhpGObjectPtr* gobject = (PhpGObjectPtr*)rsrc->ptr;
95

  
96
    if (gobject) {
97
        if (gobject->obj) {
98
            //printf("Deallocating container %p\n", gobject);
99
            //printf("Deallocating %p that has %u refcounts\n", gobject->obj, gobject->obj->ref_count);
100
            g_object_unref(G_OBJECT(gobject->obj));
101
            //printf("now %u refcounts\n", gobject->obj->ref_count);
102
        }
103
        if (gobject->typename) {
104
            free(gobject->typename);
105
        }
106
        free(gobject);
107
    }
108
}
109

  
110
/* List handling */
111
static void
112
free_glist(GList **list, GFunc free_function) {
113
    lasso_return_if_fail(list);
114
    if (*list) {
115
        if (free_function) {
116
            g_list_foreach(*list, free_function, NULL);
117
        }
118
        g_list_free(*list);
119
    }
120
    *list = NULL;
121
}
122
/* Conversion functions */
123

  
124
static xmlBuffer*
125
xmlnode_to_xmlbuffer(xmlNode *node)
126
{
127
	xmlOutputBufferPtr output_buffer;
128
	xmlBuffer *buffer;
129

  
130
	if (! node)
131
		return NULL;
132

  
133
	buffer = xmlBufferCreate();
134
	output_buffer = xmlOutputBufferCreateBuffer(buffer, NULL);
135
	xmlNodeDumpOutput(output_buffer, NULL, node, 0, 0, NULL);
136
	xmlOutputBufferClose(output_buffer);
137
	xmlBufferAdd(buffer, BAD_CAST "", 1);
138

  
139
	return buffer;
140
}
141

  
142
static char*
143
get_string_from_xml_node(xmlNode *xmlnode)
144
{
145
	xmlBuffer *buffer;
146
	char *result;
147

  
148
	if (xmlnode == NULL) {
149
		return NULL;
150
	}
151
	buffer = xmlnode_to_xmlbuffer(xmlnode);
152
	if (buffer == NULL) {
153
		result = NULL;
154
	} else {
155
		result = estrdup((char*)xmlBufferContent(buffer));
156
		xmlBufferFree(buffer);
157
	}
158
	return result;
159
}
160

  
161
static xmlNode*
162
get_xml_node_from_string(char *string)
163
{
164
	return lasso_string_fragment_to_xmlnode(string, 0);
165
}
166

  
167
static GList*
168
get_list_from_array_of_strings(zval* array)
169
{
170
	HashTable* hashtable;
171
	HashPosition pointer;
172
	zval* data;
173
	zval temp;
174
	GList* result = NULL;
175

  
176
	hashtable = Z_ARRVAL_P(array);
177
	for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
178
			(data = zend_hash_get_current_data_ex(hashtable, &pointer)) != NULL;
179
			zend_hash_move_forward_ex(hashtable, &pointer)) {
180
		temp = *data;
181
		zval_copy_ctor(&temp);
182
		convert_to_string(&temp);
183
		result = g_list_append(result, g_strndup(Z_STRVAL(temp), Z_STRLEN(temp)));
184
		zval_dtor(&temp);
185
	}
186
	return result;
187
}
188

  
189
static void
190
set_array_from_list_of_strings(GList* list, zval **array) {
191
	GList* item;
192

  
193
	array_init(*array);
194
	for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
195
		if (item->data != NULL) {
196
			add_next_index_string(*array, item->data);
197
		} else {
198
			add_next_index_null(*array);
199
		}
200
	}
201
}
202

  
203
static GList*
204
get_list_from_array_of_xmlnodes(zval* array)
205
{
206
	HashTable* hashtable;
207
	HashPosition pointer;
208
	zval* data;
209
	zval temp;
210
	GList* result = NULL;
211

  
212
	hashtable = Z_ARRVAL_P(array);
213
	for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
214
			(data = zend_hash_get_current_data_ex(hashtable, &pointer)) != NULL;
215
			zend_hash_move_forward_ex(hashtable, &pointer)) {
216
		xmlNode *value;
217

  
218
		temp = *data;
219
		zval_copy_ctor(&temp);
220
		convert_to_string(&temp);
221
		value = get_xml_node_from_string(Z_STRVAL(temp));
222
		if (value) {
223
			lasso_list_add_new_xml_node(result, value);
224
		}
225
		zval_dtor(&temp);
226
	}
227
	return result;
228
}
229

  
230
static void
231
set_array_from_list_of_xmlnodes(GList* list, zval **array) {
232
	GList* item;
233

  
234
	array_init(*array);
235
	for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
236
		if (item->data != NULL) {
237
			add_next_index_string(*array, get_string_from_xml_node(item->data));
238
		} else {
239
			add_next_index_null(*array);
240
		}
241
	}
242
}
243

  
244
static GList*
245
get_list_from_array_of_objects(zval *array)
246
{
247
	HashTable *hashtable;
248
	HashPosition pointer;
249
	zval *data;
250
	PhpGObjectPtr *cvt_temp;
251
	GList *result = NULL;
252

  
253
	hashtable = Z_ARRVAL_P(array);
254
	for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
255
			(data = zend_hash_get_current_data_ex(hashtable, &pointer)) != NULL;
256
			zend_hash_move_forward_ex(hashtable, &pointer)) {
257
		cvt_temp = (PhpGObjectPtr*) zend_fetch_resource(Z_RES_P(data), PHP_LASSO_SERVER_RES_NAME, le_lasso_server);
258
		if (cvt_temp != NULL) {
259
                        g_object_ref(cvt_temp->obj);
260
			result = g_list_append(result, cvt_temp->obj);
261
		} else {
262
			result = g_list_append(result, NULL);
263
		}
264
	}
265
	return result;
266
}
267

  
268
static void
269
set_array_from_list_of_objects(GList *list, zval **array)
270
{
271
	GList *item = NULL;
272
	zend_resource *res_item;
273
	zval zval_item;
274

  
275
	array_init(*array);
276
	for (item = g_list_first(list); item != NULL; item = g_list_next(item)) {
277
		if (item->data != NULL) {
278
			res_item = zend_register_resource(PhpGObjectPtr_New(item->data), le_lasso_server);
279
			ZVAL_RES(&zval_item, res_item);
280
			add_next_index_zval(*array, &zval_item);
281
		} else {
282
			add_next_index_null(*array);
283
		}
284
	}
285
}
286

  
287
/* FIXME: This function doesn't work yet */
288
static GHashTable*
289
get_hashtable_from_array_of_objects(zval *array)
290
{
291
	HashTable *hashtable = NULL;
292
	HashPosition pointer;
293
	zend_string *key;
294
	zend_ulong index;
295
	zval *data = NULL;
296
	PhpGObjectPtr *cvt_temp = NULL;
297
	GHashTable *result = NULL;
298

  
299
	result = g_hash_table_new(g_str_hash, g_str_equal);
300
	hashtable = Z_ARRVAL_P(array);
301
	for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
302
			(data = zend_hash_get_current_data_ex(hashtable, &pointer)) != NULL;
303
			zend_hash_move_forward_ex(hashtable, &pointer)) {
304
		cvt_temp = (PhpGObjectPtr*) zend_fetch_resource(Z_RES_P(data), PHP_LASSO_SERVER_RES_NAME, le_lasso_server);
305
		if (zend_hash_get_current_key_ex(hashtable, &key, &index, &pointer) == HASH_KEY_IS_STRING) {
306
			g_hash_table_insert(result, ZSTR_VAL(key), lasso_ref(cvt_temp->obj));
307
		} else {
308
			/* FIXME: throw an exception */
309
		}
310
	}
311
	return result;
312
}
313

  
314
G_GNUC_UNUSED static GHashTable*
315
get_hashtable_from_array_of_strings(zval *array)
316
{
317
	HashTable *hashtable = NULL;
318
	HashPosition pointer;
319
	zend_string *key = NULL;
320
	zend_ulong index;
321
	zval *data = NULL;
322
	GHashTable *result = NULL;
323

  
324
	result = g_hash_table_new(g_str_hash, g_str_equal);
325
	hashtable = Z_ARRVAL_P(array);
326
	for (zend_hash_internal_pointer_reset_ex(hashtable, &pointer);
327
			(data = zend_hash_get_current_data_ex(hashtable, &pointer)) != NULL;
328
			zend_hash_move_forward_ex(hashtable, &pointer)) {
329
		if (Z_TYPE_P(data) == IS_STRING) {
330
			if (zend_hash_get_current_key_ex(hashtable, &key, &index, &pointer) == HASH_KEY_IS_STRING) {
331
				g_hash_table_insert(result, g_strdup(ZSTR_VAL(key)), g_strdup(Z_STRVAL_P(data)));
332
			} else {
333
				/* FIXME: throw an exception */
334
			}
335
		}
336
	}
337
	return result;
338
}
339

  
340
static void
341
set_array_from_hashtable_of_objects(GHashTable *hashtable, zval **array)
342
{
343
	GList *keys = NULL;
344
	GObject *item = NULL;
345
	zend_resource *res_item;
346
	zval zval_item;
347

  
348
	array_init(*array);
349
	for (keys = g_hash_table_get_keys(hashtable); keys; keys = g_list_next(keys)) {
350
		item = g_hash_table_lookup(hashtable, keys->data);
351
		if (item) {
352
			res_item = zend_register_resource(PhpGObjectPtr_New(item), le_lasso_server);
353
			ZVAL_RES(&zval_item, res_item);
354
			add_assoc_zval(*array, (char*)keys->data, &zval_item);
355
		} else {
356
			add_assoc_null(*array, (char*)keys->data);
357
		}
358
	}
359
	g_list_free(keys);
360
}
361

  
362
G_GNUC_UNUSED static void
363
set_array_from_hashtable_of_strings(GHashTable *hashtable, zval **array)
364
{
365
	GList *keys = NULL;
366
	zval zval_item;
367

  
368
	array_init(*array);
369
	for (keys = g_hash_table_get_keys(hashtable); keys; keys = g_list_next(keys)) {
370
		char *item = g_hash_table_lookup(hashtable, keys->data);
371
		if (item) {
372
			ZVAL_STRING(&zval_item, item);
373
			add_assoc_zval(*array, (char*)keys->data, &zval_item);
374
		} else {
375
			add_assoc_null(*array, (char*)keys->data);
376
		}
377
	}
378
	g_list_free(keys);
379
}
380

  
configure.ac
131 131
AC_CHECK_PROGS(PERL, perl)
132 132
AC_CHECK_PROGS(PHP5, php5 php)
133 133
AC_CHECK_PROGS(PHP5_CONFIG, php-config5 php-config)
134
AC_CHECK_PROGS(PHP7, php7)
135
AC_CHECK_PROGS(PHP7_CONFIG, php-config7.4 php-config7.3 php-config7.2 php-config7.1 php-config7.0 php-config7)
134 136
AC_CHECK_PROGS(PYTHON, python3 python python2)
135 137
AC_CHECK_PROGS(SWIG, swig)
136 138

  
......
433 435
AC_SUBST(PHP5_VERSION)
434 436

  
435 437

  
438
# -----------
439
# PHP 7 binding
440
# -----------
441

  
442
dnl Check if php is explicitly enabled.
443
AC_ARG_ENABLE(php7, [  --enable-php7          enable the PHP 7 binding],,
444
              enable_php7="yes")
445

  
446
AC_ARG_WITH(php7-config,
447
            [  --with-php7-config=(PHP7_CONFIG)      Specify full path to php-config7.])
448

  
449
AC_ARG_ENABLE(php7-force, [  --enable-php7-force     always enable of the PHP 7 binding (win32)],
450
              [ENABLE_PHP7_FORCE="yes"],
451
              [ENABLE_PHP7_FORCE="no"])
452

  
453

  
454
dnl Check if user passed a specific php-config program.
455
if test "X$with_php7_config" != "X" ; then
456
    PHP7_CONFIG=$with_php7_config
457
fi
458

  
459
if test "X$PHP7_CONFIG" != "X" ; then
460
  PHP7_INCLUDES=`$PHP7_CONFIG --includes`
461
  PHP7_LDFLAGS=`$PHP7_CONFIG --ldflags`
462
  PHP7_LIBS=`$PHP7_CONFIG --libs`
463
  PHP7_PREFIX=`$PHP7_CONFIG --prefix`
464
  PHP7_QUOTED_PREFIX=$(echo $PHP7_PREFIX | $SED 's/\//\\\//g')
465
  PHP7_UNPREFIXED_EXTENSION_DIR=$($PHP7_CONFIG --extension-dir | $SED "s/$PHP7_QUOTED_PREFIX//g")
466
else
467
  # We assume PHP are in /usr/local directory.
468
  if test $MINGW -eq 1; then 
469
    CFLAGS="$CFLAGS -DZTS -DZEND_WIN32 -DWIN32 -D_MBCS"
470
  fi
471
  PHP7_INCLUDES="-I/usr/local/include/php7 -I/usr/local/include/php7/main -I/usr/local/include/php7/Zend -I/usr/local/include/php7/TSRM -I/usr/local/include/php7/win32"
472
  PHP7_LDFLAGS=
473
  PHP7_LIBS="-lphp7ts -lxmlparse -lxmltok"
474
  PHP7_UNPREFIXED_EXTENSION_DIR=
475
  PHP7_PREFIX=
476
fi
477

  
478
AC_ARG_WITH(php7,
479
            [  --with-php7=(PHP)      Specify full path to php 7 executable.],
480
            [PHP7="$withval"],[PHP7_INCLUDE_DIR=php7])
481

  
482
AC_ARG_WITH(php7-include-dir,
483
            [  --with-php7-include-dir=(PHP7_INCLUDE_DIR)      Specify full path to php 7 include dir.],
484
            [PHP7_INCLUDE_DIR="$withval"],[PHP7_INCLUDE_DIR=${datadir}/php])
485

  
486
AC_ARG_WITH(php7-config-dir,
487
            [  --with-php7-config-dir=(PHP7_CONFIG_DIR)      Specify full path to php 7 config dir.],
488
            [PHP7_CONFIG_DIR="$withval"],[PHP7_CONFIG_DIR=${sysconfdir}/php7/conf.d/])
489

  
490
AC_SUBST(PHP7_INCLUDES)
491
AC_SUBST(PHP7_LDFLAGS)
492
AC_SUBST(PHP7_LIBS)
493
AC_SUBST(PHP7_UNPREFIXED_EXTENSION_DIR)
494
AC_SUBST(PHP7_EXTENSION_DIR)
495
AC_SUBST(PHP7_PREFIX)
496
AC_SUBST(PHP7_INCLUDE_DIR)
497
AC_SUBST(PHP7_CONFIG_DIR)
498

  
499
AC_MSG_CHECKING(for PHP 7 development files)
500
if $PHP7_CONFIG --version | grep -q "^7" || test "x$ENABLE_PHP7_FORCE" = "xyes"
501
then
502
	PHP7_VERSION=`$PHP7_CONFIG --version 2> /dev/null`
503
	languages_available="$languages_available php7($PHP7_VERSION)"
504
else
505
	enable_php7=no
506
fi
507

  
508
AC_MSG_RESULT($enable_php7)
509
AM_CONDITIONAL([PHP7_ENABLED], [test "x$enable_php7" = "xyes"])
510
AC_SUBST(PHP7_VERSION)
511

  
512

  
436 513
### # ----------
437 514
### # C# binding (disabled for the moment)
438 515
### # ----------
......
827 904
bindings/php5/Makefile
828 905
bindings/php5/examples/Makefile
829 906
bindings/php5/tests/Makefile
907
bindings/php7/Makefile
908
bindings/php7/examples/Makefile
909
bindings/php7/tests/Makefile
830 910
bindings/perl/Makefile
831 911
])
832 912

  
......
854 934
Java binding:           ${enable_java}
855 935
Perl binding:           ${enable_perl}
856 936
PHP 5 binding:          ${enable_php5}
937
PHP 7 binding:          ${enable_php7}
857 938
Python binding:         ${enable_python}
858 939

  
859 940
C API references:       ${enable_gtk_doc}
860
-