/**
  * @static
  * @return CvsClient|SvnClient
  */
 public static function getInstance()
 {
     $appConf = AccountManager::getInstance()->appConf;
     if (!isset(self::$instance)) {
         switch ($appConf['GLOBAL_CONFIGURATION']['vcs.type']) {
             case 'cvs':
                 require_once dirname(__FILE__) . '/CvsClient.php';
                 self::$instance = CvsClient::getInstance();
                 break;
             case 'svn':
                 require_once dirname(__FILE__) . '/SvnClient.php';
                 self::$instance = SvnClient::getInstance();
                 break;
         }
     }
     return self::$instance;
 }
 /**
  * Commit file changes to repository.
  *
  * @param $ids An array of files' id to be commited.
  * @param $log The message log to use with this commit.
  * @return An associated array. The key "commitResponse" contains the response from the CVS server after commit (with HTML highlight) and the key "anode", the list of files witch have been really commited.
  */
 public function commitChanges($ids, $log)
 {
     $rf = RepositoryFetcher::getInstance();
     $commitLog = array();
     // Get informations about files we need to commit
     $fileInfos = $rf->getModifiesById($ids);
     // Task for folders
     $foldersInfos = $rf->getPendingFoldersCommit();
     // We filter this folders to return only this who want to commit according of files array
     $foldersInfos = $this->getOnlyFoldersForFiles($foldersInfos, $fileInfos);
     if ($foldersInfos) {
         // We must create this folder before commit it
         $this->ensureFoldersExists($foldersInfos);
         $c = VCSFactory::getInstance()->commitFolders($foldersInfos);
         $commitLog = array_merge($commitLog, $c);
         $this->delWork($foldersInfos);
     }
     // Task for files
     // Loop over $fileInfos to find files to be create, update or delete
     $create_stack = array();
     $update_stack = array();
     $delete_stack = array();
     for ($i = 0; $i < count($fileInfos); $i++) {
         $f = new File($fileInfos[$i]['lang'], $fileInfos[$i]['path'] . $fileInfos[$i]['name']);
         switch ($fileInfos[$i]['type']) {
             case 'new':
                 $create_stack[] = $f;
                 break;
             case 'update':
                 $update_stack[] = $f;
                 break;
             case 'delete':
                 $delete_stack[] = $f;
                 break;
         }
     }
     // Before commit, we need to update this file to find if there haven't been modified since last update process
     $create_stack = $this->beforeCommitChanges($create_stack, 'new');
     $update_stack = $this->beforeCommitChanges($update_stack, 'update');
     $delete_stack = $this->beforeCommitChanges($delete_stack, 'delete');
     // keep copy for commit failure recovery
     $this->backupCommit($create_stack, 'new');
     $this->backupCommit($update_stack, 'update');
     $this->backupCommit($delete_stack, 'delete');
     $c = VCSFactory::getInstance()->commit($log, $create_stack, $update_stack, $delete_stack);
     $commitLog = array_merge($commitLog, $c['output']);
     // html highlight commit log
     $reg = array('/(Adding )/', '/(Sending )/', '/(Deleting )/', '/(Transmitting file data)/', '/(Committed revision)/', '/(A )/', '/(D )/', '/(property )/', '/( set on )/');
     $commitLog = preg_replace($reg, '<span style="color: #15428B; font-weight: bold;">$1</span>', $commitLog);
     if (0 != $c['err']) {
         // error found in commit, rollback commit operation
         $this->rollbackCommit($create_stack, 'new');
         $this->rollbackCommit($update_stack, 'update');
         $this->rollbackCommit($delete_stack, 'delete');
     } else {
         // We fetch again the file which have been commited. All file which have been skip from beforeCommitChanges aren't in DB for now.
         $fileInfos = $rf->getModifiesById($ids);
         $ids = array();
         // Get all ids which have been really commited
         for ($i = 0; $i < count($fileInfos); $i++) {
             $ids[] = $fileInfos[$i]['id'];
         }
         // confirmed commit success. batch delete pending commit, and remove backup
         $this->afterCommitChanges($create_stack, 'new');
         $this->afterCommitChanges($update_stack, 'update');
         $this->afterCommitChanges($delete_stack, 'delete');
     }
     return array('err' => $c['err'], 'commitResponse' => $commitLog, 'anode' => $ids);
 }
 /**
  * Get the diff of a given file
  */
 public function getDiff()
 {
     if (!AccountManager::getInstance()->isLogged()) {
         return JsonResponseBuilder::failure();
     }
     $DiffType = $this->getRequestVariable('DiffType');
     $FileFullPath = $this->getRequestVariable('FilePath');
     $FileName = $this->getRequestVariable('FileName');
     $t = explode('/', $FileFullPath, 2);
     $FileLang = $t[0];
     $FilePath = $t[1];
     $opt = null;
     if ($DiffType == 'vcs') {
         $Rev1 = $this->getRequestVariable('Rev1');
         $Rev2 = $this->getRequestVariable('Rev2');
         // Ensure Rev2 is always a value greater than Rev1
         if ($Rev2 < $Rev1) {
             $tmp = $Rev2;
             $Rev2 = $Rev1;
             $Rev1 = $tmp;
         }
         $r = VCSFactory::getInstance()->diff($FileFullPath, $FileName, $Rev1, $Rev2);
     } elseif ($DiffType == 'file') {
         $patchID = $this->getRequestVariable('patchID');
         $optNbLine = $this->getRequestVariable('optNbLine');
         $optB = $this->getRequestVariable('optB');
         $optW = $this->getRequestVariable('optW');
         if ($patchID) {
             $r = File::patchDiff($patchID);
         } else {
             $file = new File($FileLang, $FilePath . $FileName);
             $r = $file->diff($optNbLine, $optB, $optW);
         }
     }
     $r = DiffGenHTMLOutput($r);
     return JsonResponseBuilder::success(array('content' => $r));
 }
 /**
  * Log into this application.
  *
  * @param $project   The project we want to work on.
  * @param $vcsLogin  The login use to identify this user into PHP VCS server.
  * @param $vcsPasswd The password, in plain text, to identify this user into PHP VCS server.
  * @param $email     The email for this user. Need to contact him via the application.
  * @param $lang      The language we want to access.
  * @return An associated array.
  */
 public function login($project, $vcsLogin, $vcsPasswd, $email, $lang = 'en', $authService = 'VCS', $authServiceID)
 {
     // Var to return into ExtJs
     $return = array();
     // We manage the project
     if (ProjectManager::getInstance()->setProject($project)) {
         $this->project = strtoupper($project);
     } else {
         $return['state'] = false;
         $return['msg'] = 'Bad project';
         $return['authMethod'] = '-';
         return $return;
     }
     $this->authService = $authService;
     $this->authServiceID = $authServiceID;
     /*
      *           VCS AUTH SYSTEM
      *
      */
     if ($this->authService == 'VCS') {
         /*
          *           ANONYMOUS VCS
          *
          */
         // Anonymous's user can logging into this app by providing this login/pass => anonymous/(empty) ou (empty)/(empty)
         // The result is the same. $this->vcsLogin will be "anonymous" and $this->vcsPasswd, (empty)
         if ($vcsLogin == "anonymous" && $vcsPasswd == "" || $vcsLogin == "" && $vcsPasswd == "") {
             $this->isAnonymous = true;
             $this->haveKarma = false;
             // Even if the user provide an empty login, we force it to be 'anonymous'
             $vcsLogin = '******';
             $this->anonymousIdent = isset($_COOKIE['anonymousIdent']) ? $_COOKIE['anonymousIdent'] : uniqid('', true);
             setcookie("anonymousIdent", $this->anonymousIdent, time() + 3600 * 24 * 365, "/");
             // One year ;)
             // Register var
             $this->vcsLogin = $vcsLogin;
             $this->vcsPasswd = '';
             $this->vcsLang = $lang;
             $this->email = $email;
             // Check DB
             $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"';
             $params = array($project, $this->vcsLogin, $this->anonymousIdent);
             $r = $this->conn->query($s, $params);
             if ($r->num_rows == 1) {
                 //This anonymous user exist into DB. We store his configuration into ...
                 $a = $r->fetch_object();
                 // ... object's property ...
                 $this->userConf = json_decode($a->conf);
                 $this->userID = $a->userID;
                 // ... and into the php's session (only specific var)
                 $_SESSION['userConf'] = $this->userConf;
                 // We update the email if this user have decided to change it.
                 $this->updateEmail();
             } else {
                 // We register this new valid user
                 $userID = $this->register();
                 $this->userID = $userID;
                 // Store in session only specific var
                 $_SESSION['userConf'] = $this->defaultConf;
             }
             // Generic session var for VALID & ANONYMOUS VCS user
             $_SESSION['userID'] = $this->userID;
             $_SESSION['project'] = $this->project;
             $_SESSION['vcsLogin'] = $this->vcsLogin = $this->vcsLogin . ' #' . $this->userID;
             $_SESSION['vcsPasswd'] = $this->vcsPasswd;
             $_SESSION['isAnonymous'] = $this->isAnonymous;
             $_SESSION['haveKarma'] = $this->haveKarma;
             $_SESSION['anonymousIdent'] = $this->anonymousIdent;
             $_SESSION['lang'] = $this->vcsLang;
             $_SESSION['email'] = $this->email;
             $_SESSION['authService'] = $this->authService;
             $_SESSION['authServiceID'] = $this->authServiceID;
             // We set up the CSRF token
             $_SESSION['csrfToken'] = sha1(uniqid(rand(), true));
             // Store some user info in cookies: we can use this to pre-fill the
             // login page if the user's session expires.
             setcookie("loginApp", 'anonymous', time() + 3600 * 24 * 365, "/");
             // One year ;)
             setcookie("email", $this->email, time() + 3600 * 24 * 365, "/");
             setcookie("lang", $this->vcsLang, time() + 3600 * 24 * 365, "/");
             // We construct the return's var for ExtJs
             $return['state'] = true;
             $return['msg'] = 'Welcome !';
             return $return;
         } else {
             $this->isAnonymous = false;
             $this->anonymousIdent = '';
             // If this app is installed into Php's server, we use the standad way to verify login/password
             if ($_SERVER["SERVER_NAME"] == "doc.php.net") {
                 // We try to authenticate this user to master php server.
                 $AuthReturn = VCSFactory::getInstance()->masterPhpAuthenticate($vcsLogin, $vcsPasswd);
                 $return['authMethod'] = 'masterPhp';
             } else {
                 // We try to authenticate this user to VCS server.
                 $AuthReturn = VCSFactory::getInstance()->svnAuthenticate($vcsLogin, $vcsPasswd);
                 $return['authMethod'] = 'svnServer';
             }
             if ($AuthReturn !== true) {
                 $return['state'] = false;
                 $return['msg'] = $AuthReturn;
                 return $return;
             } else {
                 // Check the karma
                 $karma = $this->checkKarma($vcsLogin, $lang);
                 $this->haveKarma = $karma === true;
                 // Register var
                 $this->vcsLogin = $vcsLogin;
                 $this->vcsPasswd = $vcsPasswd;
                 $this->vcsLang = $lang;
                 $this->email = $email;
                 // Check DB
                 $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "VCS" AND `vcs_login` = "%s"';
                 $params = array($project, $this->vcsLogin);
                 $r = $this->conn->query($s, $params);
                 if ($r->num_rows == 1) {
                     //This user exist into DB. We store his configuration into ...
                     $a = $r->fetch_object();
                     // ... object's property ...
                     $this->userConf = json_decode($a->conf);
                     $this->userID = $a->userID;
                     // ... and into the php's session (only specific var)
                     $_SESSION['userConf'] = $this->userConf;
                     // We update the email if this user have decided to change it.
                     $this->updateEmail();
                 } else {
                     // We register this new valid user
                     $userID = $this->register();
                     $this->userID = $userID;
                     // Store in session only specific var
                     $_SESSION['userConf'] = $this->defaultConf;
                 }
                 // Generic session var for VALID & ANONYMOUS VCS user
                 $_SESSION['userID'] = $this->userID;
                 $_SESSION['project'] = $this->project;
                 $_SESSION['vcsLogin'] = $this->vcsLogin;
                 $_SESSION['vcsPasswd'] = $this->vcsPasswd;
                 $_SESSION['isAnonymous'] = $this->isAnonymous;
                 $_SESSION['haveKarma'] = $this->haveKarma;
                 $_SESSION['anonymousIdent'] = $this->anonymousIdent;
                 $_SESSION['lang'] = $this->vcsLang;
                 $_SESSION['email'] = $this->email;
                 $_SESSION['authService'] = $this->authService;
                 $_SESSION['authServiceID'] = $this->authServiceID;
                 // We set up the CSRF token
                 $_SESSION['csrfToken'] = sha1(uniqid(rand(), true));
                 // Store some user info in cookies: we can use this to pre-fill the
                 // login page if the user's session expires.
                 setcookie("loginApp", utf8_encode($this->vcsLogin), time() + 3600 * 24 * 365, "/");
                 // One year ;)
                 setcookie("email", $this->email, time() + 3600 * 24 * 365, "/");
                 setcookie("lang", $this->vcsLang, time() + 3600 * 24 * 365, "/");
                 // We construct the return's var for ExtJs
                 $return['state'] = true;
                 $return['msg'] = 'Welcome !';
                 return $return;
             }
         }
     } else {
         if ($this->authService == 'google' || $this->authService == 'facebook' || $this->authService == 'github' || $this->authService == 'stackoverflow' || $this->authService == 'linkedin' || $this->authService == 'instagram' || $this->authService == 'twitter') {
             $this->isAnonymous = true;
             $this->haveKarma = false;
             $this->anonymousIdent = $this->authService . '-' . $this->authServiceID;
             // Register var
             $this->vcsLogin = $vcsLogin;
             $this->vcsPasswd = '';
             $this->vcsLang = $lang;
             $this->email = $email;
             // Check DB
             $s = 'SELECT * FROM `users` WHERE `project` = "%s" AND `authService` = "%s" AND `authServiceID` = "%s" AND `vcs_login` = "%s" AND `anonymousIdent` = "%s"';
             $params = array($project, $this->authService, $this->authServiceID, $this->vcsLogin, $this->anonymousIdent);
             $r = $this->conn->query($s, $params);
             if ($r->num_rows == 1) {
                 //This anonymous user exist into DB. We store his configuration into ...
                 $a = $r->fetch_object();
                 // ... object's property ...
                 $this->userConf = json_decode($a->conf);
                 $this->userID = $a->userID;
                 // ... and into the php's session (only specific var)
                 $_SESSION['userConf'] = $this->userConf;
                 // We update the email if this user have decided to change it.
                 $this->updateEmail();
             } else {
                 // We register this new valid user
                 $userID = $this->register();
                 $this->userID = $userID;
                 // Store in session only specific var
                 $_SESSION['userConf'] = $this->defaultConf;
             }
             // Generic session var for VALID & ANONYMOUS VCS user
             $_SESSION['userID'] = $this->userID;
             $_SESSION['project'] = $this->project;
             $_SESSION['vcsLogin'] = $this->vcsLogin;
             $_SESSION['vcsPasswd'] = $this->vcsPasswd;
             $_SESSION['isAnonymous'] = $this->isAnonymous;
             $_SESSION['haveKarma'] = $this->haveKarma;
             $_SESSION['anonymousIdent'] = $this->anonymousIdent;
             $_SESSION['lang'] = $this->vcsLang;
             $_SESSION['email'] = $this->email;
             $_SESSION['authService'] = $this->authService;
             $_SESSION['authServiceID'] = $this->authServiceID;
             // We set up the CSRF token
             $_SESSION['csrfToken'] = sha1(uniqid(rand(), true));
             // Store some user info in cookies: we can use this to pre-fill the
             // login page if the user's session expires.
             setcookie("loginApp", htmlentities($this->vcsLogin), time() + 3600 * 24 * 365, "/");
             // One year ;)
             setcookie("email", $this->email, time() + 3600 * 24 * 365, "/");
             setcookie("lang", $this->vcsLang, time() + 3600 * 24 * 365, "/");
             // We construct the return's var for ExtJs
             $return['state'] = true;
             $return['msg'] = 'Welcome !';
             return $return;
         } else {
             $return['state'] = false;
             $return['msg'] = 'Bad authService';
             $return['authMethod'] = '-';
             return $return;
         }
     }
 }
 /**
  * Check VCS keyWords
  * Add an entry into the error's stack if keywords are dirty
  *
  */
 function checkVCSKeyWords()
 {
     $result = VCSFactory::getInstance()->checkKeyWords($this->lang, $this->filePath, $this->fileName);
     if ($result) {
         $errLibel = "";
         if ($result["keyWords"]) {
             $errLibel .= "keyWords : " . $result["keyWords"] . " ; ";
         }
         if ($result["EolStyle"]) {
             $errLibel .= "EolStyle : " . $result["EolStyle"] . " ; ";
         }
         $this->addError(array('value_en' => $errLibel, 'value_lang' => '', 'type' => 'VCSKeyWordsEolStyle'));
     }
 }