Issues (1098)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/dbo/groups.php (6 issues)

Encourage use of @property annotation when providing magic access

Documentation Minor

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
//------------------------------------------------------------------------------
4
//
5
//  eTraxis - Records tracking web-based system
6
//  Copyright (C) 2005-2011  Artem Rodygin
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 3 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
//------------------------------------------------------------------------------
22
23
/**
24
 * Groups
25
 *
26
 * This module provides API to work with eTraxis groups.
27
 * See also {@link https://github.com/etraxis/etraxis-obsolete/wiki/tbl_groups tbl_groups} database table.
28
 *
29
 * @package DBO
30
 * @subpackage Groups
31
 */
32
33
/**#@+
34
 * Dependency.
35
 */
36
require_once('../engine/engine.php');
37
require_once('../dbo/accounts.php');
38
/**#@-*/
39
40
//------------------------------------------------------------------------------
41
//  Definitions.
42
//------------------------------------------------------------------------------
43
44
/**#@+
45
 * Data restriction.
46
 */
47
define('MAX_GROUP_NAME',        25);
48
define('MAX_GROUP_DESCRIPTION', 100);
49
/**#@-*/
50
51
//------------------------------------------------------------------------------
52
//  Functions.
53
//------------------------------------------------------------------------------
54
55
/**
56
 * Finds in database and returns the information about specified group.
57
 *
58
 * @param int $id Group ID.
59
 * @return array Array with data if group is found in database, FALSE otherwise.
60
 */
61 View Code Duplication
function group_find ($id)
62
{
63
    debug_write_log(DEBUG_TRACE, '[group_find]');
64
    debug_write_log(DEBUG_DUMP,  '[group_find] $id = ' . $id);
65
66
    $rs = dal_query('groups/fndid.sql', $id);
67
68
    if ($rs->rows == 0)
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
69
    {
70
        return FALSE;
71
    }
72
73
    $row = $rs->fetch();
74
    $row['is_global'] = is_null($row['project_id']);
75
76
    return $row;
77
}
78
79
/**
80
 * Returns {@link CRecordset DAL recordset} which contains all existing global groups and all the local
81
 * groups of specified project, sorted in accordance with current sort mode.
82
 *
83
 * @param int $id Project ID.
84
 * @param int &$sort Sort mode (used as output only). The function retrieves current sort mode from
85
 * client cookie ({@link COOKIE_GROUPS_SORT}) and updates it, if it's out of valid range.
86
 * @param int &$page Number of current page tab (used as output only). The function retrieves current
87
 * page from client cookie ({@link COOKIE_GROUPS_PAGE}) and updates it, if it's out of valid range.
88
 * @return CRecordset Recordset with list of groups.
89
 */
90 View Code Duplication
function groups_list ($id, &$sort, &$page)
91
{
92
    debug_write_log(DEBUG_TRACE, '[groups_list]');
93
    debug_write_log(DEBUG_DUMP,  '[groups_list] $id = ' . $id);
94
95
    $sort_modes = array
96
    (
97
        1 => 'is_global asc, group_name asc',
98
        2 => 'description asc, is_global asc, group_name asc',
99
        3 => 'is_global desc, group_name desc',
100
        4 => 'description desc, is_global desc, group_name desc',
101
    );
102
103
    $sort = try_request('sort', try_cookie(COOKIE_GROUPS_SORT));
104
    $sort = ustr2int($sort, 1, count($sort_modes));
105
106
    $page = try_request('page', try_cookie(COOKIE_GROUPS_PAGE));
107
    $page = ustr2int($page, 1, MAXINT);
108
109
    save_cookie(COOKIE_GROUPS_SORT, $sort);
110
    save_cookie(COOKIE_GROUPS_PAGE, $page);
111
112
    return dal_query('groups/list.sql', $id, $sort_modes[$sort]);
113
}
114
115
/**
116
 * Returns {@link CRecordset DAL recordset} which contains all current members of specified group.
117
 *
118
 * @param int $id ID of group to be enumerated.
119
 * @return CRecordset Recordset with list of accounts.
120
 */
121 View Code Duplication
function group_amongs ($id)
122
{
123
    debug_write_log(DEBUG_TRACE, '[group_amongs]');
124
    debug_write_log(DEBUG_DUMP,  '[group_amongs] $id = ' . $id);
125
126
    return dal_query('groups/mamongs.sql', $id);
127
}
128
129
/**
130
 * Returns {@link CRecordset DAL recordset} which contains all non-members of specified group.
131
 *
132
 * @param int $id ID of group to be enumerated.
133
 * @return CRecordset Recordset with list of accounts.
134
 */
135
function group_not_amongs ($id)
136
{
137
    debug_write_log(DEBUG_TRACE, '[group_not_amongs]');
138
    debug_write_log(DEBUG_DUMP,  '[group_not_amongs] $id = ' . $id);
139
140
    // Create list of user names for all current members.
141
    $members = array();
142
143
    $list = dal_query('groups/mamongs.sql', $id);
144
145
    while (($row = $list->fetch()))
146
    {
147
        array_push($members, ustrtolower($row['username']));
148
    }
149
150
    // Arrays to store resulted data.
151
    $account_id = array();
152
    $username   = array();
153
    $fullname   = array();
154
155
    // Enumerate all registered accounts.
156
    $list = dal_query('accounts/list.sql', 'username asc');
157
158
    // Push to arrays everyone, who is not in list of current members.
159
    while (($user = $list->fetch()))
160
    {
161 View Code Duplication
        if (!in_array(ustrtolower($user['username']), $members))
162
        {
163
            array_push($account_id, $user['account_id']);
164
            array_push($username,   $user['username']);
165
            array_push($fullname,   $user['fullname']);
166
        }
167
    }
168
169
    // If LDAP is enabled, add all LDAP non-members too.
170
    if (LDAP_ENABLED)
171
    {
172
        // Enumerate all LDAP accounts from LDAP server.
173
        $list = ldap_findallusers();
174
175
        // Push to arrays everyone, who is not in list of current members.
176
        foreach ($list as $user)
177
        {
178 View Code Duplication
            if (!in_array(ustrtolower($user['username']), $members))
179
            {
180
                array_push($account_id, NULL);
181
                array_push($username,   $user['username']);
182
                array_push($fullname,   $user['fullname']);
183
            }
184
        }
185
    }
186
187
    // Sort all found ono-members in alphabetical order.
188
    array_multisort($fullname, $username, $account_id);
189
190
    // Compose (fake) resulted "recordset".
191
    $retval = array();
192
193
    for ($i = 0; $i < count($fullname); $i++)
194
    {
195
        $entry = array('account_id' => $account_id[$i],
196
                       'username'   => $username[$i],
197
                       'fullname'   => $fullname[$i]);
198
199
        array_push($retval, $entry);
200
    }
201
202
    return $retval;
203
}
204
205
/**
206
 * Validates group information before creation or modification.
207
 *
208
 * @param string $group_name Group name.
209
 * @return int Error code:
210
 * <ul>
211
 * <li>{@link NO_ERROR} - data are valid</li>
212
 * <li>{@link ERROR_INCOMPLETE_FORM} - at least one of required field is empty</li>
213
 * </ul>
214
 */
215 View Code Duplication
function group_validate ($group_name)
216
{
217
    debug_write_log(DEBUG_TRACE, '[group_validate]');
218
    debug_write_log(DEBUG_DUMP,  '[group_validate] $group_name = ' . $group_name);
219
220
    if (ustrlen($group_name) == 0)
221
    {
222
        debug_write_log(DEBUG_NOTICE, '[group_validate] At least one required field is empty.');
223
        return ERROR_INCOMPLETE_FORM;
224
    }
225
226
    return NO_ERROR;
227
}
228
229
/**
230
 * Creates new group.
231
 *
232
 * @param int $project_id ID of project which new group should be created in. NULL should be used to create a global group.
233
 * @param string $group_name Group name.
234
 * @param string $description Optional description.
235
 * @return int Error code:
236
 * <ul>
237
 * <li>{@link NO_ERROR} - group is successfully created</li>
238
 * <li>{@link ERROR_ALREADY_EXISTS} - group with specified group name already exists</li>
239
 * </ul>
240
 */
241
function group_create ($project_id, $group_name, $description)
242
{
243
    debug_write_log(DEBUG_TRACE, '[group_create]');
244
    debug_write_log(DEBUG_DUMP,  '[group_create] $project_id  = ' . $project_id);
245
    debug_write_log(DEBUG_DUMP,  '[group_create] $group_name  = ' . $group_name);
246
    debug_write_log(DEBUG_DUMP,  '[group_create] $description = ' . $description);
247
248
    // Check that there is no group with the same name and in the same project.
249
    $rs = dal_query('groups/fndk.sql', ($project_id == 0 ? 'is null' : '=' . $project_id), ustrtolower($group_name));
250
251
    if ($rs->rows != 0)
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
252
    {
253
        debug_write_log(DEBUG_NOTICE, '[group_create] Group already exists.');
254
        return ERROR_ALREADY_EXISTS;
255
    }
256
257
    // Create a group.
258
    dal_query('groups/create.sql',
259
              $project_id == 0 ? NULL : $project_id,
260
              $group_name,
261
              ustrlen($description) == 0 ? NULL : $description);
262
263
    return NO_ERROR;
264
}
265
266
/**
267
 * Modifies specified group.
268
 *
269
 * @param int $id ID of group to be modified.
270
 * @param int $project_id ID of project which the group belongs to. NULL should be used to specify a global group.
271
 * @param string $group_name New group name.
272
 * @param string $description New description.
273
 * @return int Error code:
274
 * <ul>
275
 * <li>{@link NO_ERROR} - group is successfully modified</li>
276
 * <li>{@link ERROR_ALREADY_EXISTS} - another group with specified group name already exists</li>
277
 * </ul>
278
 */
279 View Code Duplication
function group_modify ($id, $project_id, $group_name, $description)
280
{
281
    debug_write_log(DEBUG_TRACE, '[group_modify]');
282
    debug_write_log(DEBUG_DUMP,  '[group_modify] $id          = ' . $id);
283
    debug_write_log(DEBUG_DUMP,  '[group_create] $project_id  = ' . $project_id);
284
    debug_write_log(DEBUG_DUMP,  '[group_modify] $group_name  = ' . $group_name);
285
    debug_write_log(DEBUG_DUMP,  '[group_modify] $description = ' . $description);
286
287
    // Check that there is no group with the same group name, besides this one.
288
    $rs = dal_query('groups/fndku.sql', $id, (is_null($project_id) ? 'is null' : '=' . $project_id), ustrtolower($group_name));
289
290
    if ($rs->rows != 0)
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
291
    {
292
        debug_write_log(DEBUG_NOTICE, '[group_modify] Group already exists.');
293
        return ERROR_ALREADY_EXISTS;
294
    }
295
296
    // Modify the group.
297
    dal_query('groups/modify.sql',
298
              $id,
299
              $group_name,
300
              ustrlen($description) == 0 ? NULL : $description);
301
302
    return NO_ERROR;
303
}
304
305
/**
306
 * Checks whether group can be deleted.
307
 *
308
 * @param int $id ID of group to be deleted.
309
 * @return bool TRUE if group can be deleted, FALSE otherwise.
310
 */
311
function is_group_removable ($id)
312
{
313
    debug_write_log(DEBUG_TRACE, '[is_group_removable]');
314
    debug_write_log(DEBUG_DUMP,  '[is_group_removable] $id = ' . $id);
315
316
    return TRUE;
317
}
318
319
/**
320
 * Deletes specified group.
321
 *
322
 * @param int $id ID of group to be deleted.
323
 * @return int Always {@link NO_ERROR}.
324
 */
325
function group_delete ($id)
326
{
327
    debug_write_log(DEBUG_TRACE, '[group_delete]');
328
    debug_write_log(DEBUG_DUMP,  '[group_delete] $id = ' . $id);
329
330
    dal_query('groups/rdelall.sql',   $id);
331
    dal_query('groups/fshdelall.sql', $id);
332
    dal_query('groups/fpdelall.sql',  $id);
333
    dal_query('groups/gtdelall.sql',  $id);
334
    dal_query('groups/gpdelall.sql',  $id);
335
    dal_query('groups/msdelall.sql',  $id);
336
    dal_query('groups/sadelall.sql',  $id);
337
    dal_query('groups/delete.sql',    $id);
338
339
    return NO_ERROR;
340
}
341
342
/**
343
 * Adds specified account to list of members of specified group.
344
 *
345
 * @param int $gid ID of group which the account should be added to.
346
 * @param int $aid ID of account to be added.
347
 * @return int Always {@link NO_ERROR}.
348
 */
349
function group_membership_add ($gid, $aid)
350
{
351
    debug_write_log(DEBUG_TRACE, '[group_membership_add]');
352
    debug_write_log(DEBUG_DUMP,  '[group_membership_add] $gid = ' . $gid);
353
    debug_write_log(DEBUG_DUMP,  '[group_membership_add] $aid = ' . $aid);
354
355
    dal_query('groups/mremove.sql', $gid, $aid);
356
    dal_query('groups/madd.sql',    $gid, $aid);
357
358
    return NO_ERROR;
359
}
360
361
/**
362
 * Removes specified account from list of members of specified group.
363
 *
364
 * @param int $gid ID of group which the account should be removed from.
365
 * @param int $aid ID of account to be removed.
366
 * @return int Always {@link NO_ERROR}.
367
 */
368
function group_membership_remove ($gid, $aid)
369
{
370
    debug_write_log(DEBUG_TRACE, '[group_membership_remove]');
371
    debug_write_log(DEBUG_DUMP,  '[group_membership_remove] $gid = ' . $gid);
372
    debug_write_log(DEBUG_DUMP,  '[group_membership_remove] $aid = ' . $aid);
373
374
    dal_query('groups/mremove.sql', $gid, $aid);
375
376
    return NO_ERROR;
377
}
378
379
/**
380
 * Finds in database and returns current permissions of specified group for specified template.
381
 *
382
 * @param int $gid ID of group whose permissions should be retrieved.
383
 * @param int $tid ID of template which permissions should be retrieved for.
384
 * @return int Current permissions set, or 0 if no permissions are set.
385
 */
386 View Code Duplication
function group_get_permissions ($gid, $tid)
387
{
388
    debug_write_log(DEBUG_TRACE, '[group_get_permissions]');
389
    debug_write_log(DEBUG_DUMP,  '[group_get_permissions] $gid = ' . $gid);
390
    debug_write_log(DEBUG_DUMP,  '[group_get_permissions] $tid = ' . $tid);
391
392
    $rs = dal_query('groups/gpget.sql', $gid, $tid);
393
394
    return ($rs->rows == 0 ? 0 : $rs->fetch('perms'));
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
395
}
396
397
/**
398
 * Sets permissions of specified group for specified template.
399
 *
400
 * @param int $gid ID of group whose permissions should be set.
401
 * @param int $tid ID of template which permissions should be set for.
402
 * @param int $perm New permissions set.
403
 * @return int Always {@link NO_ERROR}.
404
 */
405 View Code Duplication
function group_set_permissions ($gid, $tid, $perm)
406
{
407
    debug_write_log(DEBUG_TRACE, '[group_set_permissions]');
408
    debug_write_log(DEBUG_DUMP,  '[group_set_permissions] $gid  = ' . $gid);
409
    debug_write_log(DEBUG_DUMP,  '[group_set_permissions] $tid  = ' . $tid);
410
    debug_write_log(DEBUG_DUMP,  '[group_set_permissions] $perm = ' . $perm);
411
412
    dal_query('groups/gpremove.sql', $gid, $tid);
413
    dal_query('groups/gpadd.sql',    $gid, $tid, $perm);
414
415
    return NO_ERROR;
416
}
417
418
/**
419
 * Exports groups of specified group IDs to XML code (see also {@link project_import}).
420
 *
421
 * @param array Array with Group IDs.
422
 * @return string Generated XML code for specified group IDs.
423
 */
424
function groups_export ($groups)
425
{
426
    debug_write_log(DEBUG_TRACE, '[groups_export]');
427
428
    if (count($groups) == 0)
429
    {
430
        return NULL;
431
    }
432
433
    // List all global and local project groups.
434
    $rs = dal_query('templates/glist.sql', implode(',', $groups));
435
436
    $xml = NULL;
437
438
    if ($rs->rows != 0)
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
439
    {
440
        // Add XML code for all enumerated groups.
441
        while (($group = $rs->fetch()))
442
        {
443
            // Add XML code for general group information.
444
            $xml .= sprintf("  <group name=\"%s\" type=\"%s\" description=\"%s\">\n",
445
                            ustr2html($group['group_name']),
446
                            (is_null($group['project_id']) ? 'global' : 'local'),
447
                            ustr2html($group['description']));
448
449
            // List all members of this group.
450
            $rsm = dal_query('groups/mamongs.sql', $group['group_id']);
451
452
            // Add XML code for name and type of each account.
453
            while (($account = $rsm->fetch()))
454
            {
455
                $xml .= sprintf("    <account type=\"%s\">%s</account>\n",
456
                                ($account['is_ldapuser'] ? 'ldap' : 'local'),
457
                                account_get_username($account['username'], FALSE));
458
            }
459
460
            $xml .= "  </group>\n";
461
        }
462
    }
463
464
    return $xml;
465
}
466
467
/**
468
 * Imports groups described as XML code into the specified project.
469
 *
470
 * @param int $project_id ID of destination project.
471
 * @param string $xml Valid XML code.
472
 * @param string &$error In case of failure - the error message (used as output only).
473
 * @return bool Whether the import was successful.
474
 */
475
function groups_import ($project_id, $xml, &$error)
476
{
477
    debug_write_log(DEBUG_TRACE, '[groups_import]');
478
    debug_write_log(DEBUG_DUMP,  '[groups_import] $project_id = ' . $project_id);
479
480
    // Enumerate groups.
481
    $groups = $xml->xpath('/project/group');
482
483
    if ($groups !== FALSE)
484
    {
485
        foreach ($groups as $group)
486
        {
487
            $group['name']        = ustrcut($group['name'],        MAX_GROUP_NAME);
488
            $group['description'] = ustrcut($group['description'], MAX_GROUP_DESCRIPTION);
489
490
            // Validate group.
491 View Code Duplication
            switch (group_validate($group['name']))
492
            {
493
                case NO_ERROR:
494
                    break;  // nop
495
                case ERROR_INCOMPLETE_FORM:
496
                    $error = get_html_resource(RES_ALERT_REQUIRED_ARE_EMPTY_ID);
497
                    return FALSE;
498
                default:
499
                    debug_write_log(DEBUG_WARNING, '[groups_import] Group validation failure.');
500
                    $error = get_html_resource(RES_ALERT_UNKNOWN_ERROR_ID);
501
                    return FALSE;
502
            }
503
504
            // Create group.
505
            group_create($group['type'] == 'global' ? NULL : $project_id,
506
                         $group['name'],
507
                         $group['description']);
508
509
            $rs = dal_query('groups/fndk.sql',
510
                            $group['type'] == 'global' ? 'is null' : '=' . $project_id,
511
                            ustrtolower($group['name']));
512
513
            if ($rs->rows != 0)
0 ignored issues
show
The property $rows is declared protected in CRecordset. Since you implemented __get(), maybe consider adding a @property or @property-read annotation. This makes it easier for IDEs to provide auto-completion.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
514
            {
515
                $group_id = $rs->fetch('group_id');
516
517
                // Add members.
518
                if (isset($group->account))
519
                {
520
                    foreach ($group->account as $account)
521
                    {
522
                        $username     = ustrcut(strval($account), MAX_ACCOUNT_USERNAME);
523
                        $account_info = account_find_username($account['type'] == 'local' ? $username . ACCOUNT_SUFFIX : $username);
524
525
                        if ($account_info !== FALSE)
526
                        {
527
                            group_membership_add($group_id, $account_info['account_id']);
528
                        }
529
                    }
530
                }
531
            }
532
        }
533
    }
534
535
    return TRUE;
536
}
537
538
?>
539