Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.DocCtrl.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 /**
7  * Control Access Document
8  *
9  * @author Anakeen
10  * @version $Id: Class.DocCtrl.php,v 1.54 2008/08/05 15:16:58 eric Exp $
11  * @package FDL
12  */
13 /**
14  */
15 
16 include_once ("Class.DocLDAP.php");
17 include_once ("FDL/Class.DocPerm.php");
18 include_once ("FDL/Class.VGroup.php");
19 
20 define("POS_INIT", 0);
21 define("POS_VIEW", 1);
22 define("POS_EDIT", 2);
23 define("POS_DEL", 3);
24 define("POS_SEND", 4);
25 // common part are 0-4 and 7-8
26 define("POS_OPEN", 5);
27 define("POS_EXEC", 5); // idem OPEN : alias
28 define("POS_CONT", 6); // view containt
29 define("POS_VACL", 7);
30 define("POS_MACL", 8);
31 define("POS_ULCK", 9);
32 define("POS_CONF", 10); // confidential
33 define("POS_WASK", 12); // view all askes
34 // family profil
35 define("POS_CREATE", 5);
36 define("POS_ICREATE", 6);
37 // 11 undefined for the moment
38 define("POS_WF", 12); // begin of workflow privilege definition
39 // end of privilege is 31 : (coded on 32bits)
40 
41 /**
42  * Control Access Document Class
43  * @package FDL
44  * @class DocCtrl
45  * @method getRawValue($id)
46  * @method getAttribute($a)
47  * @method canEdit
48  * @method control($acl)
49  * @method addHistoryEntry($comment = '', $level = DocHisto::INFO)
50  * @property int $fromid
51  * @property Doc $doc
52  *
53  */
54 class DocCtrl extends DocLDAP
55 {
56  public $title = '';
57  // --------------------------------------------------------------------
58  //---------------------- OBJECT CONTROL PERMISSION --------------------
59  // access privilege definition
60  var $dacls = array(
61  "init" => array(
62  "pos" => POS_INIT,
63  "description" => "control initialized"
64  ) ,
65 
66  "view" => array(
67  "pos" => POS_VIEW, # N_("view document")
68  "description" => "view document"
69  ) , # N_("view")
70  "send" => array(
71  "pos" => POS_SEND, # N_("send document")
72  "description" => "send document"
73  ) , # N_("send")
74  "edit" => array(
75  "pos" => POS_EDIT, # N_("edit document")
76  "description" => "edit document"
77  ) , # N_("edit")
78  "delete" => array(
79  "pos" => POS_DEL, # N_("delete document")
80  "description" => "delete document"
81  ) , # N_("delete")
82  "open" => array(
83  "pos" => POS_OPEN, # N_("open folder")
84  "description" => "open folder"
85  ) , # N_("open")
86  "execute" => array(
87  "pos" => POS_EXEC, # N_("execute search")
88  "description" => "execute search"
89  ) , # N_("execute")
90  "modify" => array(
91  "pos" => POS_CONT, # N_("modify folder")
92  "description" => "modify folder"
93  ) , # N_("modify")
94  "viewacl" => array(
95  "pos" => POS_VACL, # N_("view acl")
96  "description" => "view acl"
97  ) , # N_("viewacl")
98  "modifyacl" => array(
99  "pos" => POS_MACL, # N_("modify acl")
100  "description" => "modify acl"
101  ) , # N_("modifyacl")
102  "create" => array(
103  "pos" => POS_CREATE, # N_("modify acl")
104  "description" => "create doc"
105  ) , # N_("create doc")
106  "unlock" => array(
107  "pos" => POS_ULCK, # N_("unlock")
108  "description" => "unlock unowner locked doc"
109  ) , # N_("unlock unowner locked doc")
110  "icreate" => array(
111  "pos" => POS_ICREATE, # N_("icreate")
112  "description" => "create doc manually"
113  ) , # N_("create doc manually")
114  "confidential" => array(
115  "pos" => POS_CONF, # N_("confidential")
116  "description" => "view confidential"
117  ) , # N_("view confidential")
118  "wask" => array(
119  "pos" => POS_WASK, # N_("wask")
120  "description" => "view answers"
121  ) # N_("view answers")
122 
123  );
124  /**
125  * extend acl definition
126  * used in WDoc and CVDoc
127  * @var array
128  */
129  public $extendedAcls = array();
130  /**
131  * @var int profil identifier
132  */
133  public $profid;
134  /**
135  * @var int dynamic profil identifier
136  */
137  public $dprofid;
138  public $views;
139  /**
140  * @var ADoc
141  */
142  public $attributes = null;
143  public $doctype;
144  /**
145  * @var int document identifier
146  */
147  public $id;
148  /**
149  * @var int document initial identifier
150  */
151  public $initid;
152  /**
153  * @var int user permission mask
154  */
155  public $uperm;
156  /**
157  * @var string view control identifier
158  */
159  public $cvid;
160  /**
161  * @var Doc profil
162  */
163  private $pdoc;
164  /**
165  * @var int current user id
166  */
167  public $userid;
168  /**
169  * To prevent to lock to many objects
170  * @var bool
171  */
172  static private $globalDocPermLock = false;
173  // --------------------------------------------------------------------
174  function __construct($dbaccess = '', $id = '', $res = '', $dbid = 0)
175  {
176  // --------------------------------------------------------------------
177  global $action; // necessary to see information about user privilege
178  if (isset($action)) {
179  $app = $action->parent;
180  $this->userid = $app->user->id;
181  }
182 
183  if (!isset($this->attributes->attr)) {
184  if (!isset($this->attributes)) $this->attributes = new stdClass();
185  $this->attributes->attr = array();
186  }
187  parent::__construct($dbaccess, $id, $res, $dbid);
188  }
189 
190  function isControlled()
191  {
192  return ($this->profid != 0);
193  }
194 
195  function unsetControl()
196  {
197  if ($this->id == $this->profid) {
198  // inhibated all doc references this profil
199  if ($this->doctype == 'P') $this->exec_query("update doc set profid=-profid where profid=" . $this->id . " and locked != -1;");
200  }
201  $this->profid = "0";
202  $this->modify(true, array(
203  "profid"
204  ));
205  }
206  /**
207  * Unset all Acl for document (for everybody)
208  * @param int $userid user system identifier
209  * @return string
210  */
211  function removeControl($userid = - 1)
212  {
213  if ($this->id == $this->profid) {
214  if ($userid == - 1) {
215  // inhibated all doc references this profil
216  $this->exec_query(sprintf("delete from docperm where docid=%d", $this->id));
217  $this->exec_query(sprintf("delete from docpermext where docid=%d", $this->id));
218  } else {
219  $this->exec_query(sprintf("delete from docperm where docid=%d and userid=%d", $this->id, $userid));
220  $this->exec_query(sprintf("delete from docpermext where docid=%d and userid=%d", $this->id, $userid));
221  }
222  }
223  return $this->modify();
224  }
225  /**
226  * activate access specific control
227  * @param bool $userctrl if true add all acls for current user
228  * @return string
229  */
230  function setControl($userctrl = true)
231  {
232  if ($userctrl) {
233  $perm = new DocPerm($this->dbaccess, array(
234  $this->id,
235  $this->userid
236  ));
237  $perm->docid = $this->id;
238  $perm->userid = $this->userid;
239  $perm->upacl = - 2; // all privileges
240  if (!$perm->IsAffected()) {
241  // add all privileges to current user
242  $perm->Add();
243  } else {
244  $perm->Modify();
245  }
246  }
247  // reactivation of doc with its profil
248  if ($this->doctype == 'P') $this->exec_query("update doc set profid=-profid where profid=-" . $this->id . " and locked != -1;");
249 
250  $this->profid = $this->id;
251  $err = $this->modify(true, array(
252  "profid"
253  ) , true);
254  return $err;
255  }
256  /**
257  * set profil for document
258  *
259  * @param int $profid identifier for profil document
260  * @param Doc $fromdocidvalues
261  * @return string
262  */
263  function setProfil($profid, $fromdocidvalues = null)
264  {
265  $err = '';
266  if (!is_numeric($profid)) $profid = getIdFromName($this->dbaccess, $profid);
267  if (empty($profid)) {
268  $profid = 0;
269  $this->dprofid = 0;
270  $this->views = '{0}';
271  }
272  $this->profid = $profid;
273  if (($profid > 0) && ($profid != $this->id)) {
274  // make sure that the profil is activated
275  $pdoc = new_Doc($this->dbaccess, $profid);
276  if ($pdoc->getRawValue("DPDOC_FAMID") > 0) {
277  // dynamic profil
278  $this->dprofid = $profid;
279  $this->computeDProfil($this->dprofid, $fromdocidvalues);
280  unset($this->uperm); // force recompute privileges
281 
282  } else {
283  $this->dprofid = 0;
284  $this->setViewProfil();
285  }
286  if ($pdoc->profid == 0) $this->profid = - $profid; // inhibition
287 
288  } elseif (($profid > 0) && ($profid == $this->id)) {
289  $this->dprofid = 0;
290  $this->setViewProfil();
291  }
292  if ($this->id > 0) {
293  $err = $this->modify(true, array(
294  "profid",
295  "dprofid",
296  "views"
297  ) , true);
298  }
299  return $err;
300  }
301  /**
302  * reset right for dynamic profil
303  *
304  * @param int $dprofid identifier for dynamic profil document
305  * @param Doc $fromdocidvalues other document to reference dynamic profiling (default itself)
306  * @return string error message
307  */
308  private function computeDProfilExt($dprofid, $fromdocidvalues = null)
309  {
310  $err = '';
311  if (count($this->extendedAcls) == 0) return '';
312 
313  $tVgroup2attrid = array();
314  $query = new QueryDb($this->dbaccess, "DocPermExt");
315  $query->AddQuery(sprintf("docid=%d", $dprofid));
316  $tacl = $query->Query(0, 0, "TABLE");
317  if (!is_array($tacl)) {
318  // print "err $tacl";
319  $tacl = array();
320  }
321  if (!$tacl) return ''; // no ext acl
322  $tgnum = array(); // list of virtual user/group
323  foreach ($tacl as $v) {
324  if ($v["userid"] >= STARTIDVGROUP) {
325  $tgnum[] = $v["userid"];
326  }
327  }
328  if (count($tgnum) > 0) {
329  $query = new QueryDb($this->dbaccess, "VGroup");
330  $query->AddQuery(GetSqlCond($tgnum, "num", true));
331  $tg = $query->Query(0, 0, "TABLE");
332  if ($query->nb > 0) {
333  foreach ($tg as $vg) {
334  $tVgroup2attrid[$vg["num"]] = $vg["id"];
335  }
336  }
337  }
338  $this->exec_query(sprintf("delete from docpermext where docid=%d", $this->id));
339  if ($fromdocidvalues == null) $fromdocidvalues = & $this;
340  $greenUid = array();
341  foreach ($tacl as $v) {
342 
343  if ($v["userid"] < STARTIDVGROUP) {
344  } else {
345  $aid = $tVgroup2attrid[$v["userid"]];
346  /*
347  * @var Doc $fromdocidvalues
348  */
349  $duid = $fromdocidvalues->getRawValue($aid);
350  if ($duid == "") $duid = $fromdocidvalues->getFamilyParameterValue($aid);
351  if ($duid != "") {
352  $duid = str_replace("<BR>", "\n", $duid); // docid multiple
353  $tduid = Doc::rawValueToArray($duid);
354  foreach ($tduid as $duid) {
355  if ($duid > 0) {
356  $docu = getTDoc($fromdocidvalues->dbaccess, intval($duid)); // not for idoc list for the moment
357  $greenUid[$docu["us_whatid"] . $v["acl"]] = array(
358  "uid" => $docu["us_whatid"],
359  "acl" => $v["acl"]
360  );
361  //print "<br>$aid:$duid:".$docu["us_whatid"];
362 
363  }
364  }
365  }
366  }
367  }
368 
369  $pe = new DocPermExt($this->dbaccess);
370  $pe->docid = $this->id;
371  foreach ($greenUid as $ku => $uid) {
372  // add right in case of multiple use of the same user : possible in dynamic profile
373  $pe->userid = $uid["uid"];
374  $pe->acl = $uid["acl"];
375  $err.= $pe->add();
376  }
377 
378  return $err;
379  }
380  /**
381  * reset right for dynamic profil
382  *
383  * @param int $dprofid identifier for dynamic profil document
384  * @param Doc $fromdocidvalues other document to reference dynamic profiling (default itself)
385  * @return string error message
386  */
387  function computeDProfil($dprofid = 0, $fromdocidvalues = null)
388  {
389  $err = '';
390  if ($this->id == 0) return '';
391  if ($dprofid == 0) $dprofid = $this->dprofid;
392  if ($dprofid <= 0) return '';
393  $perm = null;
394  $vupacl = array();
395 
396  $tVgroup2attrid = array();
397  $pdoc = new_Doc($this->dbaccess, $dprofid);
398  $pfamid = $pdoc->getRawValue("DPDOC_FAMID");
399  if ($pfamid > 0) {
400  if ($this->profid != $this->id) {
401  $this->profid = $this->id; //private profil
402  $this->modify(true, array(
403  "profid"
404  ));
405  }
406 
407  $query = new QueryDb($this->dbaccess, "DocPerm");
408  $query->AddQuery(sprintf("docid=%d", $pdoc->id));
409  $tacl = $query->Query(0, 0, "TABLE");
410  if (!is_array($tacl)) {
411  // print "err $tacl";
412  $tacl = array();
413  }
414  $tgnum = array(); // list of virtual user/group
415  foreach ($tacl as $v) {
416  if ($v["userid"] >= STARTIDVGROUP) {
417  $tgnum[] = $v["userid"];
418  }
419  }
420  if (count($tgnum) > 0) {
421  $query = new QueryDb($this->dbaccess, "VGroup");
422  $query->AddQuery(GetSqlCond($tgnum, "num", true));
423  $tg = $query->Query(0, 0, "TABLE");
424  if ($query->nb > 0) {
425  foreach ($tg as $vg) {
426  $tVgroup2attrid[$vg["num"]] = $vg["id"];
427  }
428  }
429  }
430  $point = uniqid("dcp:docperm");
431  $this->savePoint($point);
432  if (!self::$globalDocPermLock) {
433  $this->lockPoint($this->initid, "PERM");
434  }
435  // Need to lock to avoid constraint errors when concurrent docperm update
436  $this->exec_query(sprintf("delete from docperm where docid=%d", $this->id));
437  if ($fromdocidvalues == null) $fromdocidvalues = & $this;
438  $greenUid = array();
439  foreach ($tacl as $v) {
440 
441  if ($v["userid"] < STARTIDVGROUP) {
442  $tuid = array(
443  $v["userid"]
444  );
445  } else {
446  $tuid = array();
447  $aid = $tVgroup2attrid[$v["userid"]];
448  /*
449  * @var Doc $fromdocidvalues
450  */
451  $duid = $fromdocidvalues->getRawValue($aid);
452  if ($duid == "") $duid = $fromdocidvalues->getFamilyParameterValue($aid);
453  if ($duid != "") {
454  $duid = str_replace("<BR>", "\n", $duid); // docid multiple
455  $tduid = Doc::rawValueToArray($duid);
456  foreach ($tduid as $duid) {
457  if ($duid > 0) {
458  $docu = getTDoc($fromdocidvalues->dbaccess, intval($duid));
459  if (!is_array($docu)) {
460  // No use exception because document may has been deleted
461  $errorMessage = ErrorCode::getError('DOC0127', var_export($duid, true) , var_export($aid, true));
462  $this->log->error($errorMessage);
463  $this->addHistoryEntry($errorMessage, \DocHisto::ERROR);
464  } elseif (!array_key_exists('us_whatid', $docu)) {
465  $errorMessage = ErrorCode::getError('DOC0128', var_export($duid, true) , var_export($aid, true));
466  $this->log->error($errorMessage);
467  $this->addHistoryEntry($errorMessage, \DocHisto::ERROR);
468  } elseif (empty($docu['us_whatid'])) {
469  // No use exception because account may has been deleted
470  $errorMessage = ErrorCode::getError('DOC0129', var_export($duid, true) , var_export($aid, true));
471  $this->log->error($errorMessage);
472  $this->addHistoryEntry($errorMessage, \DocHisto::ERROR);
473  } else {
474  $tuid[] = $docu["us_whatid"];
475  }
476  }
477  }
478  }
479  }
480  foreach ($tuid as $ku => $uid) {
481  // add right in case of multiple use of the same user : possible in dynamic profile
482  if (($v["upacl"] & 2) && $uid) $greenUid[$uid] = $uid;
483  if (!isset($vupacl[$uid])) $vupacl[$uid] = 0;
484  $vupacl[$uid] = (intval($vupacl[$uid]) | intval($v["upacl"]));
485  if ($uid > 0) {
486  $perm = new DocPerm($this->dbaccess, array(
487  $this->id,
488  $uid
489  ));
490  $perm->upacl = $vupacl[$uid];
491  // print "<BR>\nset perm $uid : ".$this->id."/".$perm->upacl.'/'.$vupacl[$uid]."\n";
492  if ($perm->isAffected()) $err = $perm->modify();
493  else {
494  if ($perm->upacl) {
495  // add if necessary
496  $err = $perm->Add();
497  }
498  }
499  }
500  }
501  }
502 
503  $this->commitPoint($point);
504  $this->views = '{' . implode(',', $greenUid) . '}';
505  $this->Modify(true, array(
506  'views'
507  ) , true);
508  $err.= $this->computeDProfilExt($pdoc->id, $fromdocidvalues);
509  }
510  unset($this->uperm); // force recompute privileges
511  return $err;
512  }
513  /**
514  * recompute view vector privilege
515  */
516  public function setViewProfil()
517  {
518  if ($this->dprofid) {
519  $this->computeDProfil();
520  } else {
521  if ($this->profid == $this->id) {
522  simpleQuery($this->dbaccess, sprintf("select userid from docperm where docid=%d and upacl & 2 != 0", $this->id) , $uids, true, false);
523  $this->views = '{' . implode(',', $uids) . '}';
524  $this->modify(true, array(
525  'views'
526  ) , true);
527  if ($this->isRealProfile()) {
528  //propagate static profil views on linked documents
529  simpleQuery($this->dbaccess, sprintf("update doc set views='%s' where profid=%d and (dprofid is null or dprofid = 0)", $this->views, $this->id));
530  }
531  } else {
532  // static profil
533  if ($this->profid > 0) {
534  simpleQuery($this->dbaccess, sprintf("select views from docread where id=%d", $this->profid) , $view, true, true);
535  } else {
536  $view = '{0}';
537  }
538  $this->views = $view;
539  if ($this->id) {
540  $this->modify(true, array(
541  'views'
542  ) , true);
543  }
544  }
545  }
546  }
547  /**
548  * return true if document is profile document PDOC, PDIR, ...
549  * @return bool
550  */
551  public function isRealProfile()
552  {
553  return ($this->getAttribute("dpdoc_famid") != null);
554  }
555  /**
556  * modify control for a specific user
557  *
558  * @param string $uName user identifier
559  * @param string $aclname name of the acl (edit, view,...)
560  * @param bool $deletecontrol set true if want delete a control
561  * @return string error message (empty if no errors)
562  */
563  private function modifyExtendedControl($uName, $aclname, $deletecontrol = false)
564  {
565  $err = '';
566  $uid = $this->getUid($uName);
567  $eacl = new DocPermExt($this->dbaccess, array(
568  $this->id,
569  $uid,
570  $aclname
571  ));
572  if ($deletecontrol) {
573  if ($eacl->isAffected()) $err = $eacl->Delete();
574  } else {
575  // add extended acl
576  if (!$eacl->isAffected()) {
577  $eacl->userid = $uid;
578  $eacl->acl = $aclname;
579  $eacl->docid = $this->id;
580  $err = $eacl->add();
581  }
582  }
583  return $err;
584  }
585  /**
586  * If reference is not a number => try to get user id from document logical name
587  * if not found try to get user id from attribute
588  * @param string $accountReference
589  * @return string
590  */
591  private function getUid($accountReference)
592  {
593  // Test logical name
594  if (!is_numeric($accountReference) && strpos($accountReference, importDocumentDescription::attributePrefix) !== 0) {
595  if (strpos($accountReference, importDocumentDescription::documentPrefix) === 0) {
596  $accountReference = substr($accountReference, strlen(importDocumentDescription::documentPrefix));
597  }
598  $uiid = getIdFromName($this->dbaccess, $accountReference);
599  if ($uiid) {
600  $udoc = new_Doc($this->dbaccess, $uiid);
601  if ($udoc->isAlive()) $accountReference = $udoc->getRawValue("us_whatid");
602  }
603  }
604  // Test account attribute reference
605  if (!is_numeric($accountReference) && strpos($accountReference, importDocumentDescription::documentPrefix) !== 0) {
606  if (strpos($accountReference, importDocumentDescription::attributePrefix) === 0) {
607  $accountReference = substr($accountReference, strlen(importDocumentDescription::attributePrefix));
608  }
609  // logical name
610  $vg = new VGroup($this->dbaccess, strtolower($accountReference));
611  if (!$vg->isAffected()) {
612  // try to add
613  $ddoc = new_Doc($this->dbaccess, $this->getRawValue("dpdoc_famid"));
614  $oa = $ddoc->getAttribute($accountReference);
615  if (($oa->type == "docid") || ($oa->type == "account")) {
616  $vg->id = $oa->id;
617  $vg->Add();
618  $accountReference = $vg->num;
619  } else {
620  //$err = sprintf(_("unknow virtual user identificateur %s") , $uid);
621 
622  }
623  } else {
624  $accountReference = $vg->num;
625  }
626  }
627  return $accountReference;
628  }
629  /**
630  * modify control for a specific user
631  *
632  * @param int $uid user identifier
633  * @param string $aclname name of the acl (edit, view,...)
634  * @param bool $deletecontrol set true if want delete a control
635  * @return string error message (empty if no errors)
636  */
637  function modifyControl($uid, $aclname, $deletecontrol = false)
638  {
639  $err = '';
640  if (!isset($this->dacls[$aclname])) {
641  return sprintf(_("unknow privilege %s") , $aclname);
642  }
643  $pos = $this->dacls[$aclname]["pos"];
644  $uid = $this->getUid($uid);
645 
646  if ($uid > 0) {
647  $perm = new DocPerm($this->dbaccess, array(
648  $this->id,
649  $uid
650  ));
651  if ($deletecontrol) {
652  $perm->UnsetControlP($pos);
653  } else {
654  $perm->SetControlP($pos);
655  }
656  if ($perm->isAffected()) $err = $perm->modify();
657  else {
658  $err = $perm->Add();
659  }
660  }
661  $this->setViewProfil();
662  return $err;
663  }
664  /**
665  * add control for a specific user
666  *
667  * @param int $uid user identifier
668  * @param string $aclname name of the acl (edit, view,...)
669  * @return string error message (empty if no errors)
670  */
671  function addControl($uid, $aclname)
672  {
673  if ($this->isExtendedAcl($aclname)) {
674  return $this->modifyExtendedControl($uid, $aclname, false);
675  } else {
676  return $this->modifyControl($uid, $aclname, false);
677  }
678  }
679 
680  public function isExtendedAcl($aclname)
681  {
682  return (!empty($this->extendedAcls[$aclname]));
683  }
684  /**
685  * suppress control for a specific user
686  *
687  * is not a negative control
688  * @param int $uid user identifier
689  * @param string $aclname name of the acl (edit, view,...)
690  * @return string error message (empty if no errors)
691  */
692  function delControl($uid, $aclname)
693  {
694  if ($this->isExtendedAcl($aclname)) {
695  return $this->modifyExtendedControl($uid, $aclname, true);
696  } else {
697  return $this->ModifyControl($uid, $aclname, true);
698  }
699  }
700  /**
701  * set control view for document
702  *
703  * @param int $cvid identifier for control view document
704  */
705  function setCvid($cvid)
706  {
707  if (!is_numeric($cvid)) $cvid = getIdFromName($this->dbaccess, $cvid);
708  $this->cvid = $cvid;
709  }
710  /**
711  * use to know if current user has access privilege
712  *
713  * @param int $docid profil identifier
714  * @param string $aclname name of the acl (edit, view,...)
715  * @param bool $strict set to true to not use substitute
716  * @return string if empty access granted else error message
717  */
718  function controlId($docid, $aclname, $strict = false)
719  {
720  if ($this->isExtendedAcl($aclname)) {
721  return $this->controlExtId($docid, $aclname, $strict);
722  } else {
723  if ($strict) {
724  $uperm = DocPerm::getUperm($docid, $this->userid, $strict);
725  return $this->ControlUp($uperm, $aclname);
726  } else {
727  if ($this->profid == $docid) {
728  if (!isset($this->uperm)) {
729  $this->uperm = DocPerm::getUperm($docid, $this->userid);
730  }
731  return $this->ControlUp($this->uperm, $aclname);
732  } else {
733  $uperm = DocPerm::getUperm($docid, $this->userid);
734  return $this->ControlUp($uperm, $aclname);
735  }
736  }
737  }
738  }
739  /**
740  * use to know if current user has access privilege
741  *
742  * @param int $docid profil identifier
743  * @param string $aclname name of the acl (edit, view,...)
744  * @param bool $strict set to true to not use substitute
745  * @return string if empty access granted else error message
746  */
747  function controlExtId($docid, $aclname, $strict = false)
748  {
749  $err = '';
750  $grant = DocPermExt::isGranted($this->userid, $aclname, $docid, $strict);
751 
752  if (!$grant) $err = sprintf(_("no privilege %s for %s [%d]") , $aclname, $this->title, $this->id);
753  return $err;
754  }
755  /**
756  * use to know if current user has access privilege
757  *
758  * @param int $docid profil identifier
759  * @param int $uid user identifier
760  * @param string $aclname name of the acl (edit, view,...)
761  * @return string if empty access granted else error message
762  */
763  function controlUserId($docid, $uid, $aclname)
764  {
765  $perm = new DocPerm($this->dbaccess, array(
766  $docid,
767  $uid
768  ));
769 
770  if ($perm->isAffected()) $uperm = $perm->uperm;
771  else $uperm = $perm->getUperm($docid, $uid);
772 
773  return $this->controlUp($uperm, $aclname);
774  }
775  /**
776  * use to know if permission has access privilege
777  *
778  * @param int $uperm permission mask
779  * @param string $aclname name of the acl (edit, view,...)
780  * @return string if empty access granted else error message
781  */
782  function controlUp($uperm, $aclname)
783  {
784  if (isset($this->dacls[$aclname])) {
785  return (($uperm & (1 << ($this->dacls[$aclname]["pos"]))) != 0) ? "" : sprintf(_("no privilege %s for %s [%d]") , $aclname, $this->title, $this->id);
786  } else {
787  return sprintf(_("unknow privilege %s") , $aclname);
788  }
789  }
790  /**
791  * return all users which has a control for a document
792  * @param string $aclname the name of acl to search
793  * @return array of the system users informations
794  */
795  function getUsersForAcl($aclname)
796  {
797  $pos = 0;
798  $pdoc = null;
799  if (isset($this->dacls[$aclname])) {
800  $pos = $this->dacls[$aclname]["pos"];
801 
802  if ($this->getRawValue("DPDOC_FAMID") > 0) {
803  if ($this->doc) {
804  if (!isset($this->pdoc)) {
805  $pdoc = createTmpDoc($this->dbaccess, $this->fromid);
806  $err = $pdoc->Add();
807  if ($err != "") return "getUsersForAcl:" . $err; // can't create profil
808  $pdoc->setProfil($this->profid, $this->doc);
809  $this->pdoc = & $pdoc;
810  } else {
811  $pdoc = $this->pdoc;
812  }
813  }
814  }
815  }
816  if ($pdoc) $pdocid = $pdoc->id;
817  else $pdocid = $this->profid;
818 
819  $query = new QueryDb($this->dbaccess, "DocPerm");
820  $query->AddQuery("docid=" . $pdocid);
821  $query->AddQuery(sprintf("(upacl & %d) != 0", 1 << $pos));
822  $tperm = $query->Query(0, 0, "TABLE");
823  $u = new Account("");
824  $ru = array();
825  if ($query->nb > 0) {
826  foreach ($tperm as $perm) {
827  $u->select($perm["userid"]);
828  if ($u->login) {
829  if ($u->accounttype != 'U') {
830  $ru+= $u->GetRUsersList($u->id);
831  } else {
832  $ru[$u->id] = $u->getValues();
833  }
834  }
835  }
836 
837  foreach ($ru as $k => $v) { // delete groups
838  if ($v["accounttype"] == "G") unset($ru[$k]);
839  }
840  }
841  return $ru;
842  }
843  /**
844  * apply computeDProfil in all documents with this profile
845  * @apiExpose to force apply profiling
846  * @return void
847  */
848  public function recomputeProfiledDocument()
849  {
850  if ($this->isRealProfile()) {
851  include_once ("FDL/Class.SearchDoc.php");
852  if ($this->getRawValue("dpdoc_famid") > 0) {
853  // dynamic profil
854  // recompute associated documents
856 
857  if (!empty(self::$savepoint[intval($this->dbid) ])) {
858  // when are in transaction must lock complete table to avoid too many locks on each rows
859  simpleQuery($this->dbaccess, "lock table docperm in exclusive mode");
860  self::$globalDocPermLock = true;
861  }
862  $s = new SearchDoc($this->dbaccess);
863  $s->addFilter("dprofid = %d", $this->id);
864  $s->setObjectReturn();
865  $s->overrideViewControl();
866  $s->search();
867  while ($doc = $s->getNextDoc()) {
868  $doc->computeDProfil();
869  }
870  // in case of change profil status (static -> dynamic)
871  $s = new SearchDoc($this->dbaccess);
872  $s->addFilter("profid = %d", $this->id);
873  $s->setObjectReturn();
874  $s->overrideViewControl();
875  $s->search();
876  while ($doc = $s->getNextDoc()) {
877  $doc->setProfil($this->id);
878  }
879  } else {
880  // static profil
881  // revert to static profiling
882  $s = new SearchDoc($this->dbaccess);
883  $s->addFilter("dprofid = %d", $this->id);
884  $s->setObjectReturn();
885  $s->overrideViewControl();
886  $s->search();
887  while ($doc = $s->getNextDoc()) {
888  $doc->setProfil($this->id);
889  }
890  }
891  }
892  }
893  // // --------------------------------------------------------------------
894  // function ControlUserId ($userid,$aclname) {
895  // // --------------------------------------------------------------------
896  // if (isset($this->dacls[$aclname])) {
897  // $perm = new DocPerm($this->dbaccess, array($this->id,$userid));
898  // if ($perm -> IsAffected()) $uperm = $perm->uperm;
899  // else $uperm = $perm->getUperm($this->id,$userid);
900  // return (($uperm & (1 << ($this->dacls[$aclname]["pos"] ))) != 0)?"":sprintf(_("no privilege %s"),$aclname);
901  // } else {
902  // return sprintf(_("unknow privilege %s"),$aclname);
903  // }
904  // }
905  static public function parseMail($Email)
906  {
907  $sug = array(); // suggestions
908  $err = "";
909 
910  if ($Email != "") {
911  if ($Email[0] == "<") {
912  $sug[] = _("<it's a message>");
913  } else {
914  if (preg_match("/^[_\.0-9\/'?$&\+~`%|*a-z=^{}-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,6}$/i", $Email)) {
915  return true;
916  }
917  $err = _("the email syntax is like : john.doe@anywhere.org");
918  if (!preg_match("/@/", $Email)) {
919  $err = _("the email must containt the @ character");
920  }
921  }
922  }
923  return array(
924  "err" => $err,
925  "sug" => $sug
926  );
927  }
928  /**
929  * return true if the date is in the future (one day after at less)
930  * @param string $date date JJ/MM/AAAA or AAAA-MM-DD
931  * @return array
932  */
933  static public function isFutureDate($date)
934  {
935 
936  $err = "";
937  $sug = array(); // suggestions
938  if ($date != "") {
939  $date = stringDateToIso($date);
940  if (!preg_match("|^[0-9]{4}-[0-9]{2}-[0-9]{2}|", $date)) {
941  $err = _("the date syntax must be like : AAAA-MM-DD");
942  } else {
943 
944  list($yy, $mm, $dd) = explode("-", $date);
945  $yy = intval($yy);
946  $mm = intval($mm);
947  $dd = intval($dd);
948  $ti = mktime(0, 0, 0, $mm, $dd + 1, $yy);
949  if ($ti < time()) {
950  $err = sprintf(_("the date %s is in the past: today is %s") , date("d/m/Y", mktime(0, 0, 0, $mm, $dd, $yy)) , date("d/m/Y", time()));
951  $sug[] = date("d/m/Y", time());
952  }
953  }
954  }
955  return array(
956  "err" => $err,
957  "sug" => $sug
958  );
959  }
960  /**
961  * verify if a document title and its link are for the same document
962  * @param string $title document title use for verification
963  * @param string $docid document identifier use for verification
964  * @return array constraint response
965  */
966  public function isDocLinked($title, $docid)
967  {
968 
969  $err = "";
970  $sug = array(); // suggestions
971  if (trim($title) != "") {
972  if (trim($docid) == "") $err = _("need to select the document with the list");
973  else {
974  $d = new_doc($this->dbaccess, $docid);
975  if (!$d->isAlive()) $err = sprintf(_("the document id [%s] for this attribute is not valid") , $docid);
976  else if ($d->title != $title) $err = sprintf(_("the title of document [%s] is not conform to original [%s]") , $title, $d->title);
977  }
978  if ($err) {
979  $sug[] = _("clic to the ... button to link document correctly");
980  }
981  }
982  return array(
983  "err" => $err,
984  "sug" => $sug
985  );
986  }
987  /**
988  * verify if a link of document is alive
989  * @param string $title document title use for verification
990  * @param string $docid document identifier use for verification
991  * @return array constraint response
992  */
993  public function isValidLink($title, $docid)
994  {
995  $err = "";
996  $sug = array();
997  if (trim($title) != "") {
998  if (trim($docid) == "") {
999  $err = _("the document id is empty");
1000  } else {
1001  $d = new_doc($this->dbaccess, $docid);
1002  if (!$d->isAlive()) $err = sprintf(_("the document id [%s] for this attribute is not valid") , $docid);
1003  }
1004  if ($err) {
1005  $sug[] = _("clic to the [...] button to link document correctly");
1006  }
1007  } else {
1008  if (trim($docid) != "") $err = _("the document title is empty");
1009  }
1010  return array(
1011  "err" => $err,
1012  "sug" => $sug
1013  );
1014  }
1015  /**
1016  * return true it is a number
1017  * use for constraint
1018  * @param float $x the number to test
1019  * @param float $min the minimum of the number (null to indicate no limit)
1020  * @param float $max the maximum of the number (null to indicate no limit)
1021  * @return array err if cannot match range
1022  */
1023  static public function isFloat($x, $min = null, $max = null)
1024  {
1025  $err = "";
1026  if ($x === "" || $x == '-') return "";
1027  if (!is_numeric($x)) $err = sprintf(_("[%s] must be a number") , $x);
1028  if (($min !== null) && ($x < $min)) $err = sprintf(_("[%s] must be greater than %s") , $x, $min);
1029  if (($max !== null) && ($x > $max)) $err = sprintf(_("[%s] must be lower than %s") , $x, $max);
1030  return $err;
1031  }
1032  /**
1033  * return true it is a integer
1034  * use for constraint
1035  * @param float $x the number to test
1036  * @param float $min the minimum of the number (null to indicate no limit)
1037  * @param float $max the maximum of the number (null to indicate no limit)
1038  * @return array err if cannot match range
1039  */
1040  static public function isInteger($x, $min = null, $max = null)
1041  {
1042  if ($x === "") return "";
1043  if (($err = DocCtrl::isFloat($x, $min, $max)) != "") {
1044  return $err;
1045  }
1046  if (floatval($x) < - floatval(pow(2, 31)) || floatval($x) > floatval(pow(2, 31) - 1)) {
1047  // signed int32 overflow
1048  return sprintf(_("[%s] must be between %s and %s") , $x, -floatval(pow(2, 31)) , floatval(pow(2, 31) - 1));
1049  }
1050  if (intval($x) != floatval($x)) {
1051  return sprintf(_("[%s] must be a integer") , $x);
1052  }
1053 
1054  return '';
1055  }
1056  /**
1057  * return true if string match regexp
1058  * @param string $x
1059  * @param string $p regexp pattern
1060  * @return array|string constraint response
1061  */
1062  static public function isString($x, $p)
1063  {
1064  $err = "";
1065  if ($x === "") return "";
1066  if (!preg_match("/^$p$/", $x)) $err = sprintf(_("[%s] must match /%s/") , $x, $p);
1067  return array(
1068  "err" => $err
1069  );
1070  }
1071  /**
1072  * return MENU_ACTIVE if user can execute the specified action
1073  * @param string $appname application name
1074  * @param string $actname action name
1075  * @return int
1076  */
1077  static public function canExecute($appname, $actname)
1078  {
1079  /*
1080  * @var Action $action
1081  */
1082  global $action;
1083 
1084  $err = $action->canExecute($actname, $appname);
1085 
1086  if ($err == "") return MENU_ACTIVE;
1087  return MENU_INVISIBLE;
1088  }
1089  /**
1090  * return MENU_ACTIVE if user can edit document
1091  * @return int
1092  */
1093  public function canEditMenu()
1094  {
1095 
1096  $err = $this->canEdit();
1097 
1098  if ($err == "") return MENU_ACTIVE;
1099  return MENU_INVISIBLE;
1100  }
1101  /**
1102  * return MENU_ACTIVE if user can view or modify access in a profil document
1103  * @param string $acl acl name
1104  * @return int
1105  */
1106  public function controlAclAccess($acl)
1107  {
1108  // if ($this->profid != $this->id) return MENU_INVISIBLE;
1109  $err = $this->control($acl);
1110 
1111  if ($err == "") return MENU_ACTIVE;
1112  return MENU_INVISIBLE;
1113  }
1114  /**
1115  * return MENU_ACTIVE if profil is actvate
1116  * @return int
1117  */
1119  {
1120  $m = $this->controlAclAccess('modifyacl');
1121  if ($m == MENU_ACTIVE) $m = $this->profilIsActivate("true");
1122  return $m;
1123  }
1124  /**
1125  * return MENU_ACTIVE if user can view or modify access in a profil document
1126  * @param string|bool $yes if "false" invert return
1127  * @return int
1128  */
1129  public function profilIsActivate($yes = true)
1130  {
1131  $err = $this->control('modifyacl');
1132  if ($err != "") return MENU_INVISIBLE;
1133  $err = $this->control('edit');
1134  if ($err != "") return MENU_INVISIBLE;
1135 
1136  $r = ($this->profid == $this->id);
1137  if ($yes == 'false') $r = !$r;
1138 
1139  if ($r) return MENU_ACTIVE;
1140  return MENU_INVISIBLE;
1141  }
1142 }
static isGranted($userid, $acl, $profid, $strict=false)
static isFutureDate($date)
$appname
const POS_WASK
delControl($uid, $aclname)
static isString($x, $p)
getTDoc($dbaccess, $id, $sqlfilters=array(), $result=array())
addControl($uid, $aclname)
global $action
stringDateToIso($date, $format=false, $withT=false)
Definition: Lib.Util.php:246
modifyControl($uid, $aclname, $deletecontrol=false)
const MENU_INVISIBLE
Definition: Class.Doc.php:37
exec_query($sql, $lvl=0, $prepare=false)
static rawValueToArray($v)
Definition: Class.Doc.php:6228
const POS_EDIT
const POS_CONT
const POS_VACL
const STARTIDVGROUP
static canExecute($appname, $actname)
const POS_CREATE
const POS_INIT
const POS_ULCK
if($famId) $s
static getError($code, $args=null)
Definition: ErrorCode.php:27
static parseMail($Email)
$d
Definition: dav.php:77
controlUp($uperm, $aclname)
setControl($userctrl=true)
const POS_DEL
savePoint($point)
controlActifProfil()
const MENU_ACTIVE
Definition: Class.Doc.php:36
modify($nopost=false, $sfields="", $nopre=false)
static getUperm($profid, $userid, $strict=false)
isValidLink($title, $docid)
static isInteger($x, $min=null, $max=null)
const POS_SEND
$docid
Definition: cleanFamily.php:13
__construct($dbaccess= '', $id= '', $res= '', $dbid=0)
lockPoint($exclusiveLock, $exclusiveLockPrefix= '')
const POS_CONF
recomputeProfiledDocument()
controlId($docid, $aclname, $strict=false)
setProfil($profid, $fromdocidvalues=null)
$app
removeControl($userid=-1)
getUsersForAcl($aclname)
if($updateExistingTable) $point
Definition: updateclass.php:88
const POS_OPEN
controlExtId($docid, $aclname, $strict=false)
static isFloat($x, $min=null, $max=null)
new_Doc($dbaccess, $id= '', $latest=false)
GetSqlCond($Table, $column, $integer=false)
const POS_EXEC
const POS_MACL
setCvid($cvid)
commitPoint($point)
controlAclAccess($acl)
setMaxExecutionTimeTo($limit)
Definition: Lib.Common.php:121
if(($docid!==0)&&(!is_numeric($docid))) $query
getIdFromName($dbaccess, $name)
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
Definition: Lib.Common.php:484
createTmpDoc($dbaccess, $fromid, $defaultvalue=true)
if($file) if($subject==""&&$file) if($subject=="") $err
profilIsActivate($yes=true)
const POS_VIEW
const POS_ICREATE
N_($s)
Definition: Lib.Common.php:18
isExtendedAcl($aclname)
computeDProfil($dprofid=0, $fromdocidvalues=null)
controlUserId($docid, $uid, $aclname)
isDocLinked($title, $docid)
← centre documentaire © anakeen