1 /**
2  *     Copyright 2017 Couchbase, Inc.
3  *
4  *   Licensed under the Apache License, Version 2.0 (the "License");
5  *   you may not use this file except in compliance with the License.
6  *   You may obtain a copy of the License at
7  *
8  *       http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *   Unless required by applicable law or agreed to in writing, software
11  *   distributed under the License is distributed on an "AS IS" BASIS,
12  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *   See the License for the specific language governing permissions and
14  *   limitations under the License.
15  */
16 
17 #include "couchbase.h"
18 
19 #define LOGARGS(lvl) LCB_LOG_##lvl, NULL, "pcbc/user_settings", __FILE__, __LINE__
20 
21 zend_class_entry *pcbc_user_settings_ce;
22 
23 /* {{{ proto void UserSettings::__construct() */
PHP_METHOD(UserSettings,__construct)24 PHP_METHOD(UserSettings, __construct)
25 {
26     pcbc_user_settings_t *obj;
27     int rv;
28 
29     rv = zend_parse_parameters_none();
30     if (rv == FAILURE) {
31         throw_pcbc_exception("Invalid arguments.", LCB_EINVAL);
32         RETURN_NULL();
33     }
34     obj = Z_USER_SETTINGS_OBJ_P(getThis());
35     obj->full_name = NULL;
36     obj->full_name_len = 0;
37     obj->password = NULL;
38     obj->password_len = 0;
39     memset(&obj->roles, 0, sizeof(obj->roles));
40 }
41 /* }}} */
42 
43 /* {{{ proto \Couchbase\UserSettings UserSettings::fullName(string $fullName)
44  */
PHP_METHOD(UserSettings,fullName)45 PHP_METHOD(UserSettings, fullName)
46 {
47     pcbc_user_settings_t *obj;
48     char *full_name = NULL;
49     int rv;
50     pcbc_str_arg_size full_name_len;
51 
52     rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &full_name, &full_name_len);
53     if (rv == FAILURE) {
54         RETURN_NULL();
55     }
56 
57     obj = Z_USER_SETTINGS_OBJ_P(getThis());
58     if (obj->full_name) {
59         efree(obj->full_name);
60     }
61     obj->full_name = estrndup(full_name, full_name_len);
62     obj->full_name_len = full_name_len;
63 
64     RETURN_ZVAL(getThis(), 1, 0);
65 } /* }}} */
66 
67 /* {{{ proto \Couchbase\UserSettings UserSettings::password(string $password)
68  */
PHP_METHOD(UserSettings,password)69 PHP_METHOD(UserSettings, password)
70 {
71     pcbc_user_settings_t *obj;
72     char *password = NULL;
73     int rv;
74     pcbc_str_arg_size password_len;
75 
76     rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &password, &password_len);
77     if (rv == FAILURE) {
78         RETURN_NULL();
79     }
80 
81     obj = Z_USER_SETTINGS_OBJ_P(getThis());
82     if (obj->password) {
83         efree(obj->password);
84     }
85     obj->password = estrndup(password, password_len);
86     obj->password_len = password_len;
87 
88     RETURN_ZVAL(getThis(), 1, 0);
89 } /* }}} */
90 
91 /* {{{ proto \Couchbase\UserSettings UserSettings::role(string $role, string $bucket = NULL)
92  */
PHP_METHOD(UserSettings,role)93 PHP_METHOD(UserSettings, role)
94 {
95     pcbc_user_settings_t *obj;
96     char *role = NULL, *bucket = NULL;
97     int rv;
98     pcbc_str_arg_size role_len = 0, bucket_len = 0;
99 
100     rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &role, &role_len, &bucket, &bucket_len);
101     if (rv == FAILURE) {
102         RETURN_NULL();
103     }
104 
105     obj = Z_USER_SETTINGS_OBJ_P(getThis());
106     if (PCBC_SMARTSTR_LEN(obj->roles)) {
107         smart_str_appendc(&obj->roles, ',');
108     }
109     smart_str_appendl(&obj->roles, role, role_len);
110     if (bucket_len) {
111         smart_str_appendc(&obj->roles, '[');
112         smart_str_appendl(&obj->roles, bucket, bucket_len);
113         smart_str_appendc(&obj->roles, ']');
114     }
115 
116     RETURN_ZVAL(getThis(), 1, 0);
117 } /* }}} */
118 
119 ZEND_BEGIN_ARG_INFO_EX(ai_UserSettings_none, 0, 0, 0)
120 ZEND_END_ARG_INFO()
121 
122 ZEND_BEGIN_ARG_INFO_EX(ai_UserSettings_fullName, 0, 0, 1)
123 ZEND_ARG_INFO(0, fullName)
124 ZEND_END_ARG_INFO()
125 
126 ZEND_BEGIN_ARG_INFO_EX(ai_UserSettings_password, 0, 0, 1)
127 ZEND_ARG_INFO(0, password)
128 ZEND_END_ARG_INFO()
129 
130 ZEND_BEGIN_ARG_INFO_EX(ai_UserSettings_role, 0, 0, 2)
131 ZEND_ARG_INFO(0, role)
132 ZEND_ARG_INFO(0, bucket)
133 ZEND_END_ARG_INFO()
134 
135 // clang-format off
136 zend_function_entry user_settings_methods[] = {
137     PHP_ME(UserSettings, __construct, ai_UserSettings_none, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
138     PHP_ME(UserSettings, fullName, ai_UserSettings_fullName, ZEND_ACC_PUBLIC)
139     PHP_ME(UserSettings, password, ai_UserSettings_password, ZEND_ACC_PUBLIC)
140     PHP_ME(UserSettings, role, ai_UserSettings_role, ZEND_ACC_PUBLIC)
141     PHP_FE_END
142 };
143 // clang-format on
144 
145 zend_object_handlers user_settings_handlers;
146 
user_settings_free_object(pcbc_free_object_arg * object TSRMLS_DC)147 static void user_settings_free_object(pcbc_free_object_arg *object TSRMLS_DC) /* {{{ */
148 {
149     pcbc_user_settings_t *obj = Z_USER_SETTINGS_OBJ(object);
150 
151     if (obj->full_name) {
152         efree(obj->full_name);
153     }
154     if (obj->password) {
155         efree(obj->password);
156     }
157     if (PCBC_SMARTSTR_LEN(obj->roles)) {
158         smart_str_free(&obj->roles);
159     }
160 
161     zend_object_std_dtor(&obj->std TSRMLS_CC);
162 #if PHP_VERSION_ID < 70000
163     efree(obj);
164 #endif
165 } /* }}} */
166 
user_settings_create_object(zend_class_entry * class_type TSRMLS_DC)167 static pcbc_create_object_retval user_settings_create_object(zend_class_entry *class_type TSRMLS_DC)
168 {
169     pcbc_user_settings_t *obj = NULL;
170 
171     obj = PCBC_ALLOC_OBJECT_T(pcbc_user_settings_t, class_type);
172 
173     zend_object_std_init(&obj->std, class_type TSRMLS_CC);
174     object_properties_init(&obj->std, class_type);
175 
176 #if PHP_VERSION_ID >= 70000
177     obj->std.handlers = &user_settings_handlers;
178     return &obj->std;
179 #else
180     {
181         zend_object_value ret;
182         ret.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object,
183                                             user_settings_free_object, NULL TSRMLS_CC);
184         ret.handlers = &user_settings_handlers;
185         return ret;
186     }
187 #endif
188 }
189 
pcbc_user_settings_get_debug_info(zval * object,int * is_temp TSRMLS_DC)190 static HashTable *pcbc_user_settings_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
191 {
192     pcbc_user_settings_t *obj = NULL;
193 #if PHP_VERSION_ID >= 70000
194     zval retval;
195 #else
196     zval retval = zval_used_for_init;
197 #endif
198 
199     *is_temp = 1;
200     obj = Z_USER_SETTINGS_OBJ_P(object);
201 
202     array_init(&retval);
203     if (obj->full_name) {
204         ADD_ASSOC_STRINGL(&retval, "fullName", obj->full_name, obj->full_name_len);
205     }
206     if (PCBC_SMARTSTR_LEN(obj->roles)) {
207         ADD_ASSOC_STRINGL(&retval, "roles", PCBC_SMARTSTR_VAL(obj->roles), PCBC_SMARTSTR_LEN(obj->roles));
208     }
209     return Z_ARRVAL(retval);
210 } /* }}} */
211 
PHP_MINIT_FUNCTION(UserSettings)212 PHP_MINIT_FUNCTION(UserSettings)
213 {
214     zend_class_entry ce;
215 
216     INIT_NS_CLASS_ENTRY(ce, "Couchbase", "UserSettings", user_settings_methods);
217     pcbc_user_settings_ce = zend_register_internal_class(&ce TSRMLS_CC);
218     pcbc_user_settings_ce->create_object = user_settings_create_object;
219     PCBC_CE_DISABLE_SERIALIZATION(pcbc_user_settings_ce);
220 
221     memcpy(&user_settings_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
222     user_settings_handlers.get_debug_info = pcbc_user_settings_get_debug_info;
223 #if PHP_VERSION_ID >= 70000
224     user_settings_handlers.free_obj = user_settings_free_object;
225     user_settings_handlers.offset = XtOffsetOf(pcbc_user_settings_t, std);
226 #endif
227 
228     return SUCCESS;
229 }
230