9 include_once (
"FDL/freedom_util.php");
35 protected $xsd =
"USERCARD/Layout/accounts.xsd";
45 private $needSyncAccounts =
false;
49 private $workAccount = null;
51 public function import()
54 $this->xml = new \DOMDocument();
55 $this->xml->load($this->file);
56 $this->xml->preserveWhiteSpace =
false;
57 $this->xml->formatOutput =
true;
58 $this->xpath = new \DOMXPath($this->xml);
61 $this->validateShema();
62 $this->workAccount = new \Account();
64 if ($this->transactionMode || $this->analyzeOnly) {
65 $this->workAccount->savePoint(
"AccountsExport");
67 $this->workAccount->setMasterLock(
true);
73 if ($this->transactionMode && !$this->
hasErrors() && !$this->analyzeOnly) {
74 $this->workAccount->commitPoint(
"AccountsExport");
75 if ($this->needSyncAccounts) {
78 $g->resetAccountMemberOf(
false);
86 $this->
addToReport(
"",
"userAbort",
___(
"Import Aborted",
"fuserimport") ,
"", null);
89 $this->
addToReport(
"",
"stopOnError",
"",
"", null);
130 if ($this->sessionKey) {
132 $action->session->register($this->sessionKey .
"::ABORT", self::ABORTORDER);
137 if ($this->sessionKey) {
140 $action->session->register($this->sessionKey, $text);
141 $msg = $action->session->read($this->sessionKey .
"::ABORT");
142 if ($msg === self::ABORTORDER) {
143 $this->stopOnError =
false;
144 $action->session->register($this->sessionKey .
"::ABORT",
"CATCHED");
153 if ($this->sessionKey) {
155 return $action->session->read($this->sessionKey);
163 switch ($error->level) {
164 case LIBXML_ERR_WARNING:
165 $return.=
"Warning $error->code: ";
168 case LIBXML_ERR_ERROR:
169 $return.=
"Error $error->code: ";
172 case LIBXML_ERR_FATAL:
173 $return.=
"Fatal Error $error->code: ";
176 $return.= trim($error->message);
178 $return.=
" in $error->file";
180 $return.=
" on line $error->line\n";
187 $errors = libxml_get_errors();
189 foreach ($errors as $error) {
192 libxml_clear_errors();
200 protected function validateShema()
202 libxml_use_internal_errors(
true);
203 $xmlWithoutDocument = new \DOMDocument();
205 $xmlWithoutDocument->load($this->file);
206 $xmlWithoutDocument->preserveWhiteSpace =
false;
207 $xpath = new \DOMXPath($xmlWithoutDocument);
209 $documents =
$xpath->query(
"//document");
213 foreach ($documents as $nodeDocument) {
214 while ($nodeDocument->hasChildNodes()) {
215 $nodeDocument->removeChild($nodeDocument->firstChild);
219 if (!$xmlWithoutDocument->schemaValidate($this->xsd)) {
220 throw new Exception(
"ACCT0201", $this->
getXmlError());
223 $documents = $this->xpath->query(
"//document/*");
224 $docDOM = new \DOMDocument();
225 foreach ($documents as $nodeDocument) {
226 $rootTag = $nodeDocument->tagName;
227 $docDOM->loadXML($this->xml->saveXML($nodeDocument));
228 if (!$docDOM->schemaValidateSource($this->getFamilyXsd($rootTag))) {
229 throw new Exception(
"ACCT0201", $this->
getXmlError());
232 $this->xml->normalize();
247 protected function getFamilyXsd($familyName)
249 if (!isset($this->familiesXsd[$familyName])) {
254 if (!$family->isAlive()) {
255 throw new Exception(
"ACCT0202", $familyName);
257 $this->familiesXsd[$familyName] = $family->getXmlSchema();
260 return $this->familiesXsd[$familyName];
265 $roles = $this->xpath->query(
"/accounts/roles/role");
266 $count = $roles->length;
267 foreach ($roles as $k => $role) {
269 $this->importRole($role);
274 $groups = $this->xpath->query(
"/accounts/groups/group");
275 $count = $groups->length;
276 foreach ($groups as $k => $group) {
278 $this->importGroup($group);
283 $users = $this->xpath->query(
"/accounts/users/user");
285 $count = $users->length;
286 foreach ($users as $k =>
$user) {
288 $this->importUser(
$user);
295 protected function importUser($node)
300 "firstname" =>
"firstname",
301 "lastname" =>
"lastname",
303 "substitute" =>
"substitute",
304 "password" =>
"password",
307 foreach ($matchings as $xmlTag => $varId) {
311 $nodeInfo = $this->xpath->query($xmlTag, $node)->item(0);
315 $substituteLogin = $nodeInfo->getAttribute(
"reference");
317 $subs = $this->getWorkingAccount();
318 $subs->setLoginName($substituteLogin);
320 throw new Exception(
"ACCT0200", $substituteLogin, $values[
"login"]);
323 $values[$varId] = $subs->id;
328 $status = $nodeInfo->getAttribute(
"activated");
330 $values[$varId] =
"A";
331 } elseif (
$status ===
"false") {
332 $values[$varId] =
"D";
338 $crypted = $nodeInfo->getAttribute(
"crypted") ===
"true";
340 if (substr($nodeInfo->nodeValue, 0, 3) !==
'$5$') {
341 $this->
addToReport($values[
"login"],
"changePassword",
"Not a SHA256 crypt",
"", $nodeInfo);
343 $values[
"password"] = $nodeInfo->nodeValue;
346 $values[
"password_new"] = $nodeInfo->nodeValue;
347 $this->
addToReport($values[
"login"],
"changePassword",
"",
"", $nodeInfo);
352 if (mb_strtolower($nodeInfo->nodeValue) !== $nodeInfo->nodeValue) {
353 $this->
addToReport($nodeInfo->nodeValue,
"users update",
"Login must not contains uppercase characters",
"", $nodeInfo);
355 $values[$varId] = $nodeInfo->nodeValue;
359 $values[$varId] = $nodeInfo->nodeValue;
363 $account = $this->importAccount($node,
"user",
"IUSER", $values);
364 if (isset($subs) && $subs->id) {
367 $this->importParent($node,
"associatedRole",
$account);
368 $this->importParent($node,
"parentGroup",
$account);
373 protected function importGroup($node)
378 "reference" =>
"login",
379 "displayName" =>
"lastname"
381 foreach ($matchings as $xmlTag => $varId) {
385 $value = $this->xpath->query($xmlTag, $node);
386 $values[$varId] =
$value->item(0)->nodeValue;
387 if ($varId ===
"login" && mb_strtolower($values[$varId]) !== $values[$varId]) {
388 $this->
addToReport($values[$varId],
"group update",
"Reference must not contains uppercase characters",
"",
$value->item(0));
392 $account = $this->importAccount($node,
"group",
"IGROUP", $values);
393 $this->importParent($node,
"associatedRole",
$account);
394 $this->importParent($node,
"parentGroup",
$account);
403 $listNode = $this->xpath->query(sprintf(
"%ss", $tagName) , $node);
404 if ($listNode->length > 0) {
405 $parents = $this->xpath->query(sprintf(
"%ss/%s", $tagName, $tagName) , $node);
409 $listNodeItem = $listNode->item(0);
410 $reset = $listNodeItem->getAttribute(
"reset") ===
"true";
414 if ($tagName ===
"parentGroup") {
416 } elseif ($tagName ===
"associatedRole") {
419 $sql = sprintf(
"delete from groups using users where iduser=%d and users.id=groups.idgroup and users.accounttype= %s", $account->id, pg_escape_literal(
$type));
421 $this->
addToReport($account->login,
"reset$tagName",
"",
"", $listNodeItem);
422 $this->needSyncAccounts =
true;
424 $account->synchroAccountDocument();
426 $needUpdate = array();
430 foreach ($parents as $parentNode) {
431 $parentLogin = $parentNode->getAttribute(
"reference");
432 $groupAccount = $this->getWorkingAccount();
434 if ($groupAccount->setLoginName($parentLogin)) {
435 $group = new \Group();
436 $group->setSyncAccount(
false);
437 $group->idgroup = $groupAccount->id;
438 $group->iduser = $account->id;
439 $alreadyExists = ($group->preInsert() ===
"OK");
441 if (!$alreadyExists) {
442 $err = $group->add();
443 $this->needSyncAccounts =
true;
444 $this->
addToReport($account->login,
"add$tagName",
$err, $groupAccount->login, $parentNode);
446 $needUpdate[] = $groupAccount->fid;
449 $this->
addToReport($account->login,
"already$tagName",
"", $groupAccount->login, $parentNode);
452 $this->
addToReport($account->login,
"add $tagName", sprintf(
"$tagName reference %s not exists", $parentLogin) ,
"", $parentNode);
456 $account->synchroAccountDocument();
457 if ($tagName ===
"parentGroup") {
458 $dl = new \DocumentList();
460 $needUpdate[] = $account->fid;
462 $dl->addDocumentIdentifiers($needUpdate);
466 foreach ($dl as $iGroup) {
467 $iGroup->refreshGroup();
476 protected function importRole($node)
480 "reference" =>
"login",
481 "displayName" =>
"lastname"
483 foreach ($matchings as $xmlTag => $varId) {
487 $value = $this->xpath->query($xmlTag, $node);
488 $values[$varId] =
$value->item(0)->nodeValue;
489 if ($varId ===
"login" && mb_strtolower($values[$varId]) !== $values[$varId]) {
490 $this->
addToReport($values[$varId],
"role update",
"Reference must not contains uppercase characters",
"",
$value->item(0));
493 $this->importAccount($node,
"role",
"ROLE", $values);
503 protected function importAccount($node, $tag, $defaultFamily, array $values)
505 $newDocAccount = null;
510 $documentNode = $this->xpath->query(
"document", $node)->item(0);
511 $family = $defaultFamily;
513 $family = $documentNode->getAttribute(
"family");
515 $account = new \Account();
519 $msg =
___(
"Updated values",
"dcp:import") .
" :\n" . substr(print_r($values,
true) , 7, -2);
526 if ($tag ===
"role") {
528 } elseif ($tag ===
"group") {
534 $err =
"Not found family $family";
535 $this->
addToReport($values[
"login"],
"documentCreation",
$err,
"", $documentNode);
539 if ($newDocAccount) {
540 $err = $newDocAccount->add();
542 $account->fid = $newDocAccount->id;
543 $this->
addToReport($values[
"login"],
"documentCreation",
"", sprintf(
___(
"Family %s",
"fusersimport") , $newDocAccount->getFamilyDocument()->getTitle()) , $documentNode ? ($documentNode->cloneNode(
false)) : null);
545 $this->
addToReport($values[
"login"],
"documentCreation",
$err,
"", $documentNode);
548 $this->
addToReport($values[
"login"],
"documentCreation",
"Cannot create $family",
"", $documentNode);
554 $roleDocumentNode = $this->xpath->query(
"document/" . strtolower($family) , $node)->item(0);
556 $account->
affect($values);
560 $uNode = $node->cloneNode(
true);
566 $delNode = $uNode->getElementsByTagName($delTag);
567 if ($delNode->length > 0) {
568 $uNode->removeChild($delNode->item(0));
571 $msg = sprintf(
___(
"Account Type \"%s\"") , $tag) .
"\n" . $msg;
572 if ($account->id > 0) {
575 $this->
addToReport($account->login,
"updateAccount",
$err, $msg, $uNode);
576 if ($roleDocumentNode) {
577 $docName = $roleDocumentNode->getAttribute(
"name");
579 $docAccount = \new_doc(
"", $account->fid);
580 if (!$docAccount->name) {
581 $docAccount->setLogicalName($docName);
583 if ($docAccount->name != $docName) {
584 throw new Exception(
"ACCT0209", $docName, $docAccount);
590 if (!$account->password) {
591 $account->password =
"-";
593 $err = $account->add();
596 $newDocAccount->setValue(\Dcp\AttributeIdentifiers\Role::us_whatid, $account->id);
597 $newDocAccount->modify();
598 if ($roleDocumentNode) {
599 $docName = $roleDocumentNode->getAttribute(
"name");
601 $newDocAccount->setLogicalName($docName);
604 $account->synchroAccountDocument();
607 if ($roleDocumentNode) {
616 $node->setAttribute(
"id", $account->fid);
620 file_put_contents($tmpFile, $this->xml->saveXML($node));
622 $importXml->importXmlFileDocument($tmpFile,
$log);
624 if (
$log[
"values"]) {
625 $msg =
___(
"Updated values",
"dcp:import") .
" :\n" . substr(print_r(
$log[
"values"],
true) , 7, -2);
628 $this->
addToReport($account->login,
"documentUpdate",
$log[
"err"], $msg, $node);
633 return \LibSystem::tempnam(null,
"importXml");
638 switch ($actionType) {
639 case "documentCreation":
640 $msgType =
___(
"Document creation",
"fusersimport");
643 case "documentUpdate":
644 $msgType =
___(
"Document update",
"fusersimport");
647 case "updateAccount":
648 $msgType =
___(
"Update account",
"fusersimport");
652 $msgType =
___(
"Create account",
"fusersimport");
655 case "addparentGroup":
656 $msgType =
___(
"Add group reference",
"fusersimport");
659 case "addassociatedRole":
660 $msgType =
___(
"Add role reference",
"fusersimport");
663 case "alreadyparentGroup":
664 $msgType =
___(
"Group reference already added",
"fusersimport");
667 case "alreadyassociatedRole":
668 $msgType =
___(
"Role reference already added",
"fusersimport");
672 $msgType =
___(
"Reset all group attachment",
"fusersimport");
676 $msgType =
___(
"Reset all direct associated roles",
"fusersimport");
679 case "changePassword":
680 $msgType =
___(
"New password",
"fusersimport");
684 $msgType =
___(
"Stopped on first error",
"fusersimport");
688 $msgType = $actionType;
692 $msgType.=
" : \n" . $msg;
695 $this->report[] = array(
697 "action" => $actionType,
699 "message" => $msgType,
700 "node" => ($node) ? $this->xml->saveXML($node) :
""
703 if ($error && $this->stopOnError) {
715 foreach ($this->report as
$report) {
716 if ($report[
"error"]) {
725 private function getWorkingAccount()
727 foreach ($this->workAccount->fields as $field) {
728 $this->workAccount->$field =
"";
730 $this->workAccount->isset =
false;
731 return $this->workAccount;
setAnalyzeOnly($analyzeOnly)
updateMemberOf($updateSubstitute=true)
if(!function_exists('pgettext')) ___($message, $context="")
modify($nopost=false, $sfields="", $nopre=false)
libxml_display_error($error)
setTransactionMode($transactionMode)
createDoc($dbaccess, $fromid, $control=true, $defaultvalues=true, $temporary=false)
getFamIdFromName($dbaccess, $name)
importXMLDocument(\DOMElement $node,\Account $account)
setStopOnError($stopOnError)
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
if($file) if($subject==""&&$file) if($subject=="") $err
affect($array, $more=false, $reset=true)
addToReport($login, $actionType, $error, $msg="", $node=null)
setSessionKey($sessionKey)