| <?php␊ |
| /* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */␊ |
| /*␊ |
| # ***** BEGIN LICENSE BLOCK *****␊ |
| # This file is part of InDefero, an open source project management application.␊ |
| # Copyright (C) 2008 CĂ©ondo Ltd and contributors.␊ |
| #␊ |
| # InDefero is free software; you can redistribute it and/or modify␊ |
| # it under the terms of the GNU General Public License as published by␊ |
| # the Free Software Foundation; either version 2 of the License, or␊ |
| # (at your option) any later version.␊ |
| #␊ |
| # InDefero is distributed in the hope that it will be useful,␊ |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of␊ |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the␊ |
| # GNU General Public License for more details.␊ |
| #␊ |
| # You should have received a copy of the GNU General Public License␊ |
| # along with this program; if not, write to the Free Software␊ |
| # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA␊ |
| #␊ |
| # ***** END LICENSE BLOCK ***** */␊ |
| ␊ |
| /**␊ |
| * This classes is a plugin which allows to synchronise access rights␊ |
| * between indefero and mercurial web-published repositories.␊ |
| */␊ |
| class IDF_Plugin_SyncMercurial␊ |
| {␊ |
| ␊ |
| /**␊ |
| * Entry point of the plugin.␊ |
| */␊ |
| static public function entry($signal, &$params)␊ |
| {␊ |
| // First check for the 3 mandatory config variables.␊ |
| if (!Pluf::f('idf_plugin_syncmercurial_passwd_file', false) or␊ |
| !Pluf::f('idf_plugin_syncmercurial_path', false) or␊ |
| !Pluf::f('idf_plugin_syncmercurial_hgrc', false)) {␊ |
| return;␊ |
| }␊ |
| include_once 'File/Passwd/Authdigest.php';␊ |
| $plug = new IDF_Plugin_SyncMercurial();␊ |
| switch ($signal) {␊ |
| case 'IDF_Project::created':␊ |
| $plug->processMercurialCreate($params['project']);␊ |
| break;␊ |
| case 'IDF_Project::membershipsUpdated':␊ |
| $plug->processSyncAuthz($params['project']);␊ |
| break;␊ |
| case 'Pluf_User::passwordUpdated':␊ |
| $plug->processSyncPasswd($params['user']);␊ |
| break;␊ |
| }␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Run hg init command to create the corresponding Mercurial␊ |
| * repository.␊ |
| *␊ |
| * @param IDF_Project ␊ |
| * @return bool Success␊ |
| */␊ |
| function processMercurialCreate($project)␊ |
| {␊ |
| $shortname = $project->shortname;␊ |
| ␊ |
| if (false===($mercurial_path=Pluf::f('idf_plugin_syncmercurial_path',false))) {␊ |
| throw new Pluf_Exception_SettingError("'idf_plugin_syncmercurial_path' must be defined in your configuration file.");␊ |
| }␊ |
| ␊ |
| if (file_exists($mercurial_path.'/'.$shortname)) {␊ |
| throw new Exception(sprintf(__('The repository %s already exists.'),␊ |
| $mercurial_path.'/'.$shortname));␊ |
| }␊ |
| $return = 0;␊ |
| $output = array();␊ |
| $cmd = sprintf('hg init %s', ␊ |
| escapeshellarg($mercurial_path.'/'.$shortname));␊ |
| $ll = exec($cmd, $output, $return);␊ |
| return ($return == 0);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Synchronise an user's password.␊ |
| *␊ |
| * @param Pluf_User␊ |
| */␊ |
| function processSyncPasswd($user)␊ |
| {␊ |
| $passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file');␊ |
| if (!file_exists($passwd_file) or !is_writable($passwd_file)) {␊ |
| return false;␊ |
| }␊ |
| $ht = new File_Passwd_Authbasic($passwd_file);␊ |
| $ht->load();␊ |
| $ht->setMode(FILE_PASSWD_SHA); ␊ |
| if ($ht->userExists($user->login)) {␊ |
| $ht->changePasswd($user->login, $this->getMercurialPass($user));␊ |
| } else {␊ |
| $ht->addUser($user->login, $this->getMercurialPass($user));␊ |
| }␊ |
| $ht->save();␊ |
| return true;␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Synchronize the hgrc file and the passwd file for the project.␊ |
| *␊ |
| * @param IDF_Project␊ |
| */␊ |
| function processSyncAuthz($project)␊ |
| {␊ |
| $this->SyncAccess($project);␊ |
| $this->generateProjectPasswd($project);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Get the repository password for the user␊ |
| */␊ |
| function getMercurialPass($user){␊ |
| return substr(sha1($user->password.Pluf::f('secret_key')), 0, 8);␊ |
| }␊ |
| ␊ |
| /**␊ |
| * For a particular project: update all passwd information␊ |
| */␊ |
| function generateProjectPasswd($project)␊ |
| {␊ |
| $passwd_file = Pluf::f('idf_plugin_syncmercurial_passwd_file');␊ |
| if (!file_exists($passwd_file) or !is_writable($passwd_file)) {␊ |
| throw new Exception (sprintf(__('%s does not exist or is not writable.'), $passwd_file));␊ |
| }␊ |
| $ht = new File_Passwd_Authbasic($passwd_file);␊ |
| $ht->setMode(FILE_PASSWD_SHA); ␊ |
| $ht->load();␊ |
| $mem = $project->getMembershipData();␊ |
| $members = array_merge((array)$mem['members'], (array)$mem['owners'], ␊ |
| (array)$mem['authorized']);␊ |
| foreach($members as $user) {␊ |
| if ($ht->userExists($user->login)) {␊ |
| $ht->changePasswd($user->login, $this->getMercurialPass($user));␊ |
| } else {␊ |
| $ht->addUser($user->login, $this->getMercurialPass($user));␊ |
| }␊ |
| }␊ |
| $ht->save();␊ |
| }␊ |
| ␊ |
| /**␊ |
| * Generate the hgrc file␊ |
| */␊ |
| function SyncAccess($project)␊ |
| {␊ |
| $shortname = $project->shortname;␊ |
| $hgrc_file = Pluf::f('idf_plugin_syncmercurial_path').sprintf('/%s/.hg/hgrc', $shortname);␊ |
| ␊ |
| // Get allow_push list␊ |
| $allow_push = '';␊ |
| $mem = $project->getMembershipData();␊ |
| foreach ($mem['owners'] as $v) {␊ |
| $allow_push .= $v->login.' ';␊ |
| }␊ |
| foreach ($mem['members'] as $v) {␊ |
| $allow_push .= $v->login.' ';␊ |
| }␊ |
| ␊ |
| // Generate hgrc content ␊ |
| if (is_file($hgrc_file)) {␊ |
| $tmp_content = parse_ini_file($hgrc_file, true);␊ |
| $tmp_content['web']['allow_push'] = $allow_push;␊ |
| }␊ |
| else {␊ |
| $tmp_content = Pluf::f('idf_plugin_syncmercurial_hgrc');␊ |
| $tmp_content['web']['allow_push'] = $allow_push;␊ |
| }␊ |
| $fcontent = '';␊ |
| foreach ($tmp_content as $key => $elem){␊ |
| $fcontent .= '['.$key."]\n";␊ |
| foreach ($elem as $key2 => $elem2){␊ |
| $fcontent .= $key2.' = '.$elem2."\n"; ␊ |
| }␊ |
| }␊ |
| file_put_contents($hgrc_file, $fcontent, LOCK_EX);␊ |
| ␊ |
| // Generate private repository config file␊ |
| $private_file = Pluf::f('idf_plugin_syncmercurial_private_include');␊ |
| $notify_file = Pluf::f('idf_plugin_syncmercurial_private_notify');␊ |
| $fcontent = '';␊ |
| foreach (Pluf::factory('IDF_Project')->getList() as $project) {␊ |
| $conf = new IDF_Conf();␊ |
| $conf->setProject($project);␊ |
| if ($project->private == true){␊ |
| $mem = $project->getMembershipData();␊ |
| $user = '';␊ |
| foreach ($mem['owners'] as $v) {␊ |
| $user .= $v->login.' ';␊ |
| }␊ |
| foreach ($mem['members'] as $v) {␊ |
| $user .= $v->login.' ';␊ |
| }␊ |
| foreach ($mem['authorized'] as $v) {␊ |
| $user .= $v->login.' ';␊ |
| }␊ |
| $fcontent .= '<Location '. sprintf(Pluf::f('idf_plugin_syncmercurial_private_url'), $project->shortname).'>'."\n";␊ |
| $fcontent .= 'AuthType Basic'."\n";␊ |
| $fcontent .= 'AuthName "Restricted"'."\n";␊ |
| $fcontent .= sprintf('AuthUserFile %s', Pluf::f('idf_plugin_syncmercurial_passwd_file'))."\n";␊ |
| $fcontent .= sprintf('Require user %s', $user)."\n";␊ |
| $fcontent .= '</Location>'."\n\n";␊ |
| }␊ |
| }␊ |
| file_put_contents($private_file, $fcontent, LOCK_EX);␊ |
| file_put_contents($notify_file, ' ', LOCK_EX);␊ |
| return true;␊ |
| }␊ |
| }␊ |