Overview
Comment:Renommage des constantes GARRADIN_* en Garradin\* + support du login local par id ou email
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0f6cbac68b3da575722b74b52880fdb95e74fa51
User & Date: bohwaz on 2014-02-12 14:45:25
Other Links: manifest | tags
Context
2014-02-12
14:58
Autoriser de mettre un des comptes à NULL check-in: a66f9d3acc user: bohwaz tags: trunk
14:45
Renommage des constantes GARRADIN_* en Garradin\* + support du login local par id ou email check-in: 0f6cbac68b user: bohwaz tags: trunk
14:14
Debug des arguments check-in: dd669f5faa user: bohwaz tags: trunk
Changes

Modified src/include/class.champs_membres.php from [ae35bd1abf] to [635e79ce0b].

54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    public function toString()
    {
        return utils::write_ini_string($this->champs);
    }

	static public function importInstall()
	{
		$champs = parse_ini_file(GARRADIN_ROOT . '/include/data/champs_membres.ini', true);
        $champs = array_filter($champs, function ($row) { return !empty($row['install']); });
        return new Champs_Membres($champs);
	}

    static public function importPresets()
    {
        if (is_null(self::$presets))
        {
            self::$presets = parse_ini_file(GARRADIN_ROOT . '/include/data/champs_membres.ini', true);
        }

        return self::$presets;
    }

    static public function listUnusedPresets(Champs_Membres $champs)
    {







|








|







54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
    public function toString()
    {
        return utils::write_ini_string($this->champs);
    }

	static public function importInstall()
	{
		$champs = parse_ini_file(ROOT . '/include/data/champs_membres.ini', true);
        $champs = array_filter($champs, function ($row) { return !empty($row['install']); });
        return new Champs_Membres($champs);
	}

    static public function importPresets()
    {
        if (is_null(self::$presets))
        {
            self::$presets = parse_ini_file(ROOT . '/include/data/champs_membres.ini', true);
        }

        return self::$presets;
    }

    static public function listUnusedPresets(Champs_Membres $champs)
    {

Modified src/include/class.compta_categories.php from [e93d5c4729] to [944c6c207d].

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    const DEPENSES = -1;
    const RECETTES = 1;
    const AUTRES = 0;

    public function importCategories()
    {
        $db = DB::getInstance();
        $db->exec(file_get_contents(GARRADIN_ROOT . '/include/data/categories_comptables.sql'));
    }

    public function add($data)
    {
        $this->_checkFields($data);

        $db = DB::getInstance();







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    const DEPENSES = -1;
    const RECETTES = 1;
    const AUTRES = 0;

    public function importCategories()
    {
        $db = DB::getInstance();
        $db->exec(file_get_contents(ROOT . '/include/data/categories_comptables.sql'));
    }

    public function add($data)
    {
        $this->_checkFields($data);

        $db = DB::getInstance();

Modified src/include/class.compta_comptes.php from [36e00e33e8] to [2c9f058783].

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    const PASSIF = 0x01;
    const ACTIF = 0x02;
    const PRODUIT = 0x04;
    const CHARGE = 0x08;

    public function importPlan()
    {
        $plan = json_decode(file_get_contents(GARRADIN_ROOT . '/include/data/plan_comptable.json'), true);

        $db = DB::getInstance();
        $db->exec('BEGIN;');
        $ids = array();

        foreach ($plan as $id=>$compte)
        {







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    const PASSIF = 0x01;
    const ACTIF = 0x02;
    const PRODUIT = 0x04;
    const CHARGE = 0x08;

    public function importPlan()
    {
        $plan = json_decode(file_get_contents(ROOT . '/include/data/plan_comptable.json'), true);

        $db = DB::getInstance();
        $db->exec('BEGIN;');
        $ids = array();

        foreach ($plan as $id=>$compte)
        {

Modified src/include/class.db.php from [55b4328232] to [70706b161b].

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        $flags = SQLITE3_OPEN_READWRITE;

        if ($create)
        {
            $flags |= SQLITE3_OPEN_CREATE;
        }

        parent::__construct(GARRADIN_DB_FILE, $flags);

        $this->enableExceptions(true);

        // Activer les contraintes des foreign keys
        $this->exec('PRAGMA foreign_keys = ON;');

        $this->createFunction('transliterate_to_ascii', array('Garradin\utils', 'transliterateToAscii'));







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        $flags = SQLITE3_OPEN_READWRITE;

        if ($create)
        {
            $flags |= SQLITE3_OPEN_CREATE;
        }

        parent::__construct(DB_FILE, $flags);

        $this->enableExceptions(true);

        // Activer les contraintes des foreign keys
        $this->exec('PRAGMA foreign_keys = ON;');

        $this->createFunction('transliterate_to_ascii', array('Garradin\utils', 'transliterateToAscii'));

Modified src/include/class.membres.php from [e67112c5ee] to [3ac66530b1].

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
146
147
148
149
150
151
152






















153
154
155
156
157
158










159
160
161
162
163
164
165
        }

        $config = Config::getInstance();

        $dest = trim($email);

        $this->_sessionStart(true);
        $hash = sha1($dest . $id . 'recover' . GARRADIN_ROOT . time());
        $_SESSION['recover_password'] = array('id' => (int) $id, 'email' => $dest, 'hash' => $hash);

        $message = "Bonjour,\n\nVous avez oublié votre mot de passe ? Pas de panique !\n\n";
        $message.= "Il vous suffit de cliquer sur le lien ci-dessous pour recevoir un nouveau mot de passe.\n\n";
        $message.= WWW_URL . 'admin/password.php?c=' . substr($hash, -10);
        $message.= "\n\nSi vous n'avez pas demandé à recevoir ce message, ignorez-le, votre mot de passe restera inchangé.";

................................................................................
            $droits = $this->getDroits($membre['id_categorie']);
        }

        $membre['droits'] = $droits;
        $_SESSION['logged_user'] = $membre;
        return true;
    }























    public function isLogged()
    {
        $this->_sessionStart();

        return empty($_SESSION['logged_user']) ? false : true;










    }

    public function getLoggedUser()
    {
        if (!$this->isLogged())
            return false;








|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>





|
>
>
>
>
>
>
>
>
>
>







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
        }

        $config = Config::getInstance();

        $dest = trim($email);

        $this->_sessionStart(true);
        $hash = sha1($dest . $id . 'recover' . ROOT . time());
        $_SESSION['recover_password'] = array('id' => (int) $id, 'email' => $dest, 'hash' => $hash);

        $message = "Bonjour,\n\nVous avez oublié votre mot de passe ? Pas de panique !\n\n";
        $message.= "Il vous suffit de cliquer sur le lien ci-dessous pour recevoir un nouveau mot de passe.\n\n";
        $message.= WWW_URL . 'admin/password.php?c=' . substr($hash, -10);
        $message.= "\n\nSi vous n'avez pas demandé à recevoir ce message, ignorez-le, votre mot de passe restera inchangé.";

................................................................................
            $droits = $this->getDroits($membre['id_categorie']);
        }

        $membre['droits'] = $droits;
        $_SESSION['logged_user'] = $membre;
        return true;
    }

    public function localLogin()
    {
        if (!defined('Garradin\LOCAL_LOGIN'))
            return false;

        if (trim(LOCAL_LOGIN) == '')
            return false;

        $db = DB::getInstance();
        
        if (is_int(LOCAL_LOGIN) && ($membre = $db->simpleQuerySingle('SELECT * FROM membres WHERE id = ? LIMIT 1;', true, LOCAL_LOGIN)))
        {
            return $this->updateSessionData($membre);
        }
        elseif ($membre = $db->simpleQuerySingle('SELECT * FROM membres WHERE email = ? LIMIT 1;', true, LOCAL_LOGIN))
        {
            return $this->updateSessionData($membre);
        }

        throw new UserException('Le membre ' . LOCAL_LOGIN . ' n\'existe pas, merci de modifier la directive Garradin\LOCAL_LOGIN.');
    }

    public function isLogged()
    {
        $this->_sessionStart();

        if (empty($_SESSION['logged_user']))
        {
            if (defined('Garradin\LOCAL_LOGIN'))
            {
                return $this->localLogin();
            }

            return false;
        }

        return true;
    }

    public function getLoggedUser()
    {
        if (!$this->isLogged())
            return false;

Modified src/include/class.plugin.php from [3a51ee530c] to [fc8588c2e1].

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
	}

	static public function listDownloaded()
	{
		$installed = self::listInstalled();

		$list = [];
		$dir = dir(GARRADIN_PLUGINS_PATH);

		while ($file = $dir->read())
		{
			if (substr($file, 0, 1) == '.')
				continue;

			if (!preg_match('!^([a-z0-9_-]+)\.phar$!', $file, $match))
				continue;
			
			if (array_key_exists($match[1], $installed))
				continue;

			$list[$match[1]] = parse_ini_file('phar://' . GARRADIN_PLUGINS_PATH . '/' . $match[1] . '.phar/infos.ini', false);
		}

		$dir->close();

		return $list;
	}

	static public function listOfficial()
	{
		if (Static_Cache::expired('plugins_list', 3600 * 24))
		{
			$url = parse_url(GARRADIN_PLUGINS_URL);

			$context_options = [
				'ssl' => [
					'verify_peer'   => TRUE,
					'cafile'        => GARRADIN_ROOT . '/include/data/cacert.pem',
					'verify_depth'  => 5,
					'CN_match'      => $url['host'],
				]
			];

			$context = stream_context_create($context_options);

			try {
				$result = file_get_contents(GARRADIN_PLUGINS_URL, NULL, $context);
			}
			catch (\Exception $e)
			{
				throw new UserException('Le téléchargement de la liste des plugins a échoué : ' . $e->getMessage())
			}

			Static_Cache::store('plugins_list', $result);
................................................................................
	static public function checkHash($id)
	{
		$list = self::fetchOfficialList();

		if (!array_key_exists($id, $list))
			return null;

		$hash = sha1_file(GARRADIN_PLUGINS_PATH . '/' . $id . '.phar');

		return ($hash === $list[$id]['hash']);
	}

	static public function isOfficial($id)
	{
		$list = self::fetchOfficialList();
................................................................................
		$list = self::fetchOfficialList();

		if (!array_key_exists($id, $list))
		{
			throw new \LogicException($id . ' n\'est pas un plugin officiel (absent de la liste)');
		}

		if (file_exists(GARRADIN_PLUGINS_PATH . '/' . $id . '.phar'))
		{
			throw new UserException('Le plugin '.$id.' existe déjà.');
		}

		$url = parse_url(GARRADIN_PLUGINS_URL);

		$context_options = [
			'ssl' => [
				'verify_peer'   => TRUE,
				'cafile'        => GARRADIN_ROOT . '/include/data/cacert.pem',
				'verify_depth'  => 5,
				'CN_match'      => $url['host'],
			]
		];

		$context = stream_context_create($context_options);

		try {
			copy($list[$id]['phar'], GARRADIN_PLUGINS_PATH . '/' . $id . '.phar', $context);
		}
		catch (\Exception $e)
		{
			throw new \RuntimeException('Le téléchargement du plugin '.$id.' a échoué : ' . $e->getMessage())
		}

		if (!self::checkHash($id))
		{
			unlink(GARRADIN_PLUGINS_PATH . '/' . $id . '.phar');
			throw new \RuntimeException('L\'archive du plugin '.$id.' est corrompue (le hash SHA1 ne correspond pas).');
		}

		self::install($id, true);

		return true;
	}
................................................................................
	static public function install($id, $official = true)
	{
		if ($official && !self::checkHash($id))
		{
			throw new \RuntimeException('L\'archive du plugin '.$id.' est corrompue (le hash SHA1 ne correspond pas).');
		}

		if (file_exists('phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/install.php'))
		{
			include 'phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/install.php';
		}

		$infos = parse_ini_file('phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/infos.ini', false);

		$db = DB::getInstance();
		$db->simpleInsert('plugins', [
			'id' 		=> 	$id,
			'officiel' 	=> 	(int)(bool)$official,
			'nom'		=>	$infos['nom'],
			'description'=>	$infos['description'],
................................................................................
			'menu'		=>	(int)(bool)$infos['menu'],
			'config'	=>	'',
		]);
	}
	
	static public function uninstall($id)
	{
		if (file_exists('phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/uninstall.php'))
		{
			include 'phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/uninstall.php';
		}
		
		$db = DB::getInstance();
		return $db->simpleExec('DELETE FROM plugins WHERE id = ?;', $id);
	}

	static public function needUpgrade($id)
	{
		$infos = parse_ini_file('phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/infos.ini', false);
		$version = $db->simpleQuerySingle('SELECT version FROM plugins WHERE id = ?;', false, $id);

		if (version_compare($version, $infos['version'], '!='))
			return true;

		return false;
	}

	static public function upgrade($id)
	{
		if (file_exists('phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/upgrade.php'))
		{
			include 'phar://' . GARRADIN_PLUGINS_PATH . '/' . $id . '.phar/upgrade.php';
		}

		$db = DB::getInstance();
		return $db->simpleUpdate('plugins', 'id = \''.$db->escapeString($id).'\'', ['version' => $infos['version']]);
	}
}







|












|











|




|








|







 







|







 







|




|




|








|








|







 







|

|


|







 







|

|








|










|

|






66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
	}

	static public function listDownloaded()
	{
		$installed = self::listInstalled();

		$list = [];
		$dir = dir(PLUGINS_PATH);

		while ($file = $dir->read())
		{
			if (substr($file, 0, 1) == '.')
				continue;

			if (!preg_match('!^([a-z0-9_-]+)\.phar$!', $file, $match))
				continue;
			
			if (array_key_exists($match[1], $installed))
				continue;

			$list[$match[1]] = parse_ini_file('phar://' . PLUGINS_PATH . '/' . $match[1] . '.phar/infos.ini', false);
		}

		$dir->close();

		return $list;
	}

	static public function listOfficial()
	{
		if (Static_Cache::expired('plugins_list', 3600 * 24))
		{
			$url = parse_url(PLUGINS_URL);

			$context_options = [
				'ssl' => [
					'verify_peer'   => TRUE,
					'cafile'        => ROOT . '/include/data/cacert.pem',
					'verify_depth'  => 5,
					'CN_match'      => $url['host'],
				]
			];

			$context = stream_context_create($context_options);

			try {
				$result = file_get_contents(PLUGINS_URL, NULL, $context);
			}
			catch (\Exception $e)
			{
				throw new UserException('Le téléchargement de la liste des plugins a échoué : ' . $e->getMessage())
			}

			Static_Cache::store('plugins_list', $result);
................................................................................
	static public function checkHash($id)
	{
		$list = self::fetchOfficialList();

		if (!array_key_exists($id, $list))
			return null;

		$hash = sha1_file(PLUGINS_PATH . '/' . $id . '.phar');

		return ($hash === $list[$id]['hash']);
	}

	static public function isOfficial($id)
	{
		$list = self::fetchOfficialList();
................................................................................
		$list = self::fetchOfficialList();

		if (!array_key_exists($id, $list))
		{
			throw new \LogicException($id . ' n\'est pas un plugin officiel (absent de la liste)');
		}

		if (file_exists(PLUGINS_PATH . '/' . $id . '.phar'))
		{
			throw new UserException('Le plugin '.$id.' existe déjà.');
		}

		$url = parse_url(PLUGINS_URL);

		$context_options = [
			'ssl' => [
				'verify_peer'   => TRUE,
				'cafile'        => ROOT . '/include/data/cacert.pem',
				'verify_depth'  => 5,
				'CN_match'      => $url['host'],
			]
		];

		$context = stream_context_create($context_options);

		try {
			copy($list[$id]['phar'], PLUGINS_PATH . '/' . $id . '.phar', $context);
		}
		catch (\Exception $e)
		{
			throw new \RuntimeException('Le téléchargement du plugin '.$id.' a échoué : ' . $e->getMessage())
		}

		if (!self::checkHash($id))
		{
			unlink(PLUGINS_PATH . '/' . $id . '.phar');
			throw new \RuntimeException('L\'archive du plugin '.$id.' est corrompue (le hash SHA1 ne correspond pas).');
		}

		self::install($id, true);

		return true;
	}
................................................................................
	static public function install($id, $official = true)
	{
		if ($official && !self::checkHash($id))
		{
			throw new \RuntimeException('L\'archive du plugin '.$id.' est corrompue (le hash SHA1 ne correspond pas).');
		}

		if (file_exists('phar://' . PLUGINS_PATH . '/' . $id . '.phar/install.php'))
		{
			include 'phar://' . PLUGINS_PATH . '/' . $id . '.phar/install.php';
		}

		$infos = parse_ini_file('phar://' . PLUGINS_PATH . '/' . $id . '.phar/infos.ini', false);

		$db = DB::getInstance();
		$db->simpleInsert('plugins', [
			'id' 		=> 	$id,
			'officiel' 	=> 	(int)(bool)$official,
			'nom'		=>	$infos['nom'],
			'description'=>	$infos['description'],
................................................................................
			'menu'		=>	(int)(bool)$infos['menu'],
			'config'	=>	'',
		]);
	}
	
	static public function uninstall($id)
	{
		if (file_exists('phar://' . PLUGINS_PATH . '/' . $id . '.phar/uninstall.php'))
		{
			include 'phar://' . PLUGINS_PATH . '/' . $id . '.phar/uninstall.php';
		}
		
		$db = DB::getInstance();
		return $db->simpleExec('DELETE FROM plugins WHERE id = ?;', $id);
	}

	static public function needUpgrade($id)
	{
		$infos = parse_ini_file('phar://' . PLUGINS_PATH . '/' . $id . '.phar/infos.ini', false);
		$version = $db->simpleQuerySingle('SELECT version FROM plugins WHERE id = ?;', false, $id);

		if (version_compare($version, $infos['version'], '!='))
			return true;

		return false;
	}

	static public function upgrade($id)
	{
		if (file_exists('phar://' . PLUGINS_PATH . '/' . $id . '.phar/upgrade.php'))
		{
			include 'phar://' . PLUGINS_PATH . '/' . $id . '.phar/upgrade.php';
		}

		$db = DB::getInstance();
		return $db->simpleUpdate('plugins', 'id = \''.$db->escapeString($id).'\'', ['version' => $infos['version']]);
	}
}

Modified src/include/class.sauvegarde.php from [f7fa754f2e] to [45f67dc004].

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
	 * @return array 		 Liste des fichiers
	 */	
	public function getList($auto = false)
	{
		$ext = $auto ? 'auto\.\d+\.sqlite' : 'sqlite';

		$out = array();
		$dir = dir(GARRADIN_DATA_ROOT);

		while ($file = $dir->read())
		{
			if ($file[0] != '.' && is_file(GARRADIN_DATA_ROOT . '/' . $file) 
				&& preg_match('![\w\d._-]+\.' . $ext . '$!i', $file) && $file != basename(GARRADIN_DB_FILE))
			{
				$out[$file] = filemtime(GARRADIN_DATA_ROOT . '/' . $file);
			}
		}

		$dir->close();

		ksort($out);

................................................................................
	 * Crée une nouvelle sauvegarde
	 * @param  boolean $auto Si true le nom de fichier sera celui de la sauvegarde automatique courante,
	 * sinon le nom sera basé sur la date (sauvegarde manuelle)
	 * @return string Le nom de fichier de la sauvegarde ainsi créée
	 */
	public function create($auto = false)
	{
		$backup = str_replace('.sqlite', ($auto ? '.auto.1' : date('.Y-m-d-His')) . '.sqlite', GARRADIN_DB_FILE);
		copy(GARRADIN_DB_FILE, $backup);
		return basename($backup);
	}

	/**
	 * Effectue une rotation des sauvegardes automatiques
	 * association.auto.1.sqlite deviendra association.auto.2.sqlite par exemple
	 * @return boolean true
................................................................................

		foreach ($list as $f=>$d)
		{
			$new = preg_replace_callback('!\.auto\.(\d+)\.sqlite$!', function ($m) {
				return '.auto.' . ((int) $m[1] + 1) . '.sqlite';
			}, $f);

			rename(GARRADIN_DATA_ROOT . '/' . $f, GARRADIN_DATA_ROOT . '/' . $new);
		}

		return true;
	}

	/**
	 * Crée une sauvegarde automatique si besoin est
................................................................................
		// Test de la date de création de la dernière sauvegarde
		if ($last >= (time() - ($config->get('frequence_sauvegardes') * 3600 * 24)))
		{
			return true;
		}

		// Si pas de modif depuis la dernière sauvegarde, ça sert à rien d'en faire
		if ($last >= filemtime(GARRADIN_DB_FILE))
		{
			return true;
		}

		$this->rotate();
		$this->create(true);

................................................................................
	 * Efface une sauvegarde locale
	 * @param  string $file Nom du fichier à supprimer
	 * @return boolean		true si le fichier a bien été supprimé, false sinon
	 */
	public function remove($file)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._-]+\.sqlite$!i', $file) 
			|| $file == basename(GARRADIN_DB_FILE))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		return unlink(GARRADIN_DATA_ROOT . '/' . $file);
	}

	/**
	 * Renvoie sur la sortie courante le contenu du fichier de base de données courant
	 * @return boolean true
	 */
	public function dump()
	{
		$in = fopen(GARRADIN_DB_FILE, 'r');
        $out = fopen('php://output', 'w');

        while (!feof($in))
        {
        	fwrite($out, fread($in, 8192));
        }

................................................................................
	public function restoreFromLocal($file)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._-]+$!i', $file))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		if (!file_exists(GARRADIN_DATA_ROOT . '/' . $file))
		{
			throw new UserException('Le fichier fourni n\'existe pas.');
		}

		return $this->restoreDB(GARRADIN_DATA_ROOT . '/' . $file);
	}

	/**
	 * Restaure une copie distante (fichier envoyé)
	 * @param  array  $file Tableau provenant de $_FILES
	 * @return boolean true
	 */
................................................................................
		}

		// On récupère la version pour plus tard
		$version = $db->querySingle('SELECT valeur FROM config WHERE cle=\'version\';');

		$db->close();

		$backup = str_replace('.sqlite', date('.Y-m-d-His') . '.avant_restauration.sqlite', GARRADIN_DB_FILE);
		
		if (!rename(GARRADIN_DB_FILE, $backup))
		{
			throw new \RuntimeException('Unable to backup current DB file.');
		}

		if (!copy($file, GARRADIN_DB_FILE))
		{
			rename($backup, GARRADIN_DB_FILE);
			throw new \RuntimeException('Unable to copy backup DB to main location.');
		}

		if ($version != garradin_version())
		{
			return self::NEED_UPGRADE;
		}







|



|
|

|







 







|
|







 







|







 







|







 







|




|








|







 







|




|







 







|

|




|

|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
...
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
	 * @return array 		 Liste des fichiers
	 */	
	public function getList($auto = false)
	{
		$ext = $auto ? 'auto\.\d+\.sqlite' : 'sqlite';

		$out = array();
		$dir = dir(DATA_ROOT);

		while ($file = $dir->read())
		{
			if ($file[0] != '.' && is_file(DATA_ROOT . '/' . $file) 
				&& preg_match('![\w\d._-]+\.' . $ext . '$!i', $file) && $file != basename(DB_FILE))
			{
				$out[$file] = filemtime(DATA_ROOT . '/' . $file);
			}
		}

		$dir->close();

		ksort($out);

................................................................................
	 * Crée une nouvelle sauvegarde
	 * @param  boolean $auto Si true le nom de fichier sera celui de la sauvegarde automatique courante,
	 * sinon le nom sera basé sur la date (sauvegarde manuelle)
	 * @return string Le nom de fichier de la sauvegarde ainsi créée
	 */
	public function create($auto = false)
	{
		$backup = str_replace('.sqlite', ($auto ? '.auto.1' : date('.Y-m-d-His')) . '.sqlite', DB_FILE);
		copy(DB_FILE, $backup);
		return basename($backup);
	}

	/**
	 * Effectue une rotation des sauvegardes automatiques
	 * association.auto.1.sqlite deviendra association.auto.2.sqlite par exemple
	 * @return boolean true
................................................................................

		foreach ($list as $f=>$d)
		{
			$new = preg_replace_callback('!\.auto\.(\d+)\.sqlite$!', function ($m) {
				return '.auto.' . ((int) $m[1] + 1) . '.sqlite';
			}, $f);

			rename(DATA_ROOT . '/' . $f, DATA_ROOT . '/' . $new);
		}

		return true;
	}

	/**
	 * Crée une sauvegarde automatique si besoin est
................................................................................
		// Test de la date de création de la dernière sauvegarde
		if ($last >= (time() - ($config->get('frequence_sauvegardes') * 3600 * 24)))
		{
			return true;
		}

		// Si pas de modif depuis la dernière sauvegarde, ça sert à rien d'en faire
		if ($last >= filemtime(DB_FILE))
		{
			return true;
		}

		$this->rotate();
		$this->create(true);

................................................................................
	 * Efface une sauvegarde locale
	 * @param  string $file Nom du fichier à supprimer
	 * @return boolean		true si le fichier a bien été supprimé, false sinon
	 */
	public function remove($file)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._-]+\.sqlite$!i', $file) 
			|| $file == basename(DB_FILE))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		return unlink(DATA_ROOT . '/' . $file);
	}

	/**
	 * Renvoie sur la sortie courante le contenu du fichier de base de données courant
	 * @return boolean true
	 */
	public function dump()
	{
		$in = fopen(DB_FILE, 'r');
        $out = fopen('php://output', 'w');

        while (!feof($in))
        {
        	fwrite($out, fread($in, 8192));
        }

................................................................................
	public function restoreFromLocal($file)
	{
		if (preg_match('!\.\.+!', $file) || !preg_match('!^[\w\d._-]+$!i', $file))
		{
			throw new UserException('Nom de fichier non valide.');
		}

		if (!file_exists(DATA_ROOT . '/' . $file))
		{
			throw new UserException('Le fichier fourni n\'existe pas.');
		}

		return $this->restoreDB(DATA_ROOT . '/' . $file);
	}

	/**
	 * Restaure une copie distante (fichier envoyé)
	 * @param  array  $file Tableau provenant de $_FILES
	 * @return boolean true
	 */
................................................................................
		}

		// On récupère la version pour plus tard
		$version = $db->querySingle('SELECT valeur FROM config WHERE cle=\'version\';');

		$db->close();

		$backup = str_replace('.sqlite', date('.Y-m-d-His') . '.avant_restauration.sqlite', DB_FILE);
		
		if (!rename(DB_FILE, $backup))
		{
			throw new \RuntimeException('Unable to backup current DB file.');
		}

		if (!copy($file, DB_FILE))
		{
			rename($backup, DB_FILE);
			throw new \RuntimeException('Unable to copy backup DB to main location.');
		}

		if ($version != garradin_version())
		{
			return self::NEED_UPGRADE;
		}

Modified src/include/class.squelette.php from [c933f7ee20] to [e3b0ee8047].

1
2
3
4
5
6
7
8
9
10
11
12
...
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
<?php

namespace Garradin;

require_once GARRADIN_ROOT . '/include/libs/miniskel/class.miniskel.php';

class Squelette_Snippet
{
    const TEXT = 0;
    const PHP = 1;
    const GUESS = 2;
    const OBJ = 3;
................................................................................
        return $out;
    }

    public function fetch($template, $no_display = false)
    {
        $this->currentTemplate = $template;

        $path = file_exists(GARRADIN_DATA_ROOT . '/www/squelettes/' . $template)
            ? GARRADIN_DATA_ROOT . '/www/squelettes/' . $template
            : GARRADIN_ROOT . '/www/squelettes-dist/' . $template;

        $tpl_id = basename(dirname($path)) . '/' . $template;

        if (!self::compile_check($tpl_id, $path))
        {
            if (!file_exists($path))
            {
................................................................................
            throw new UserException('Cette page n\'existe pas.');
        }
        else
        {
            $_GET['uri'] = $_REQUEST['uri'] = substr($uri, 1);

            if (preg_match('!^[\w\d_-]+$!i', $_GET['uri'])
                && file_exists(GARRADIN_DATA_ROOT . '/www/squelettes/' . strtolower($_GET['uri']) . '.html'))
            {
                $skel = strtolower($_GET['uri']) . '.html';
            }
            else
            {
                $skel = 'article.html';
            }
................................................................................

        $this->display($skel);
    }

    static private function compile_get_path($path)
    {
        $hash = sha1($path);
        return GARRADIN_DATA_ROOT . '/cache/compiled/s_' . $hash . '.php';
    }

    static private function compile_check($tpl, $check)
    {
        if (!file_exists(self::compile_get_path($tpl)))
            return false;

................................................................................
    }

    static public function getSource($template)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        $path = file_exists(GARRADIN_DATA_ROOT . '/www/squelettes/' . $template)
            ? GARRADIN_DATA_ROOT . '/www/squelettes/' . $template
            : GARRADIN_ROOT . '/www/squelettes-dist/' . $template;

        if (!file_exists($path))
            return false;

        return file_get_contents($path);
    }

    static public function editSource($template, $content)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        $path = GARRADIN_DATA_ROOT . '/www/squelettes/' . $template;

        return file_put_contents($path, $content);
    }

    static public function resetSource($template)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        if (file_exists(GARRADIN_DATA_ROOT . '/www/squelettes/' . $template))
        {
            unlink(GARRADIN_DATA_ROOT . '/www/squelettes/' . $template);
        }

        return true;
    }

    static public function listSources()
    {
        $sources = array();

        $dir = dir(GARRADIN_ROOT . '/www/squelettes-dist');

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
                $sources[] = $file;
        }

        $dir->close();

        $dir = dir(GARRADIN_DATA_ROOT . '/www/squelettes');

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
                $sources[] = $file;
        }





|







 







|
|
|







 







|







 







|







 







|
|
|












|









|

|









|









|







1
2
3
4
5
6
7
8
9
10
11
12
...
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
<?php

namespace Garradin;

require_once ROOT . '/include/libs/miniskel/class.miniskel.php';

class Squelette_Snippet
{
    const TEXT = 0;
    const PHP = 1;
    const GUESS = 2;
    const OBJ = 3;
................................................................................
        return $out;
    }

    public function fetch($template, $no_display = false)
    {
        $this->currentTemplate = $template;

        $path = file_exists(DATA_ROOT . '/www/squelettes/' . $template)
            ? DATA_ROOT . '/www/squelettes/' . $template
            : ROOT . '/www/squelettes-dist/' . $template;

        $tpl_id = basename(dirname($path)) . '/' . $template;

        if (!self::compile_check($tpl_id, $path))
        {
            if (!file_exists($path))
            {
................................................................................
            throw new UserException('Cette page n\'existe pas.');
        }
        else
        {
            $_GET['uri'] = $_REQUEST['uri'] = substr($uri, 1);

            if (preg_match('!^[\w\d_-]+$!i', $_GET['uri'])
                && file_exists(DATA_ROOT . '/www/squelettes/' . strtolower($_GET['uri']) . '.html'))
            {
                $skel = strtolower($_GET['uri']) . '.html';
            }
            else
            {
                $skel = 'article.html';
            }
................................................................................

        $this->display($skel);
    }

    static private function compile_get_path($path)
    {
        $hash = sha1($path);
        return DATA_ROOT . '/cache/compiled/s_' . $hash . '.php';
    }

    static private function compile_check($tpl, $check)
    {
        if (!file_exists(self::compile_get_path($tpl)))
            return false;

................................................................................
    }

    static public function getSource($template)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        $path = file_exists(DATA_ROOT . '/www/squelettes/' . $template)
            ? DATA_ROOT . '/www/squelettes/' . $template
            : ROOT . '/www/squelettes-dist/' . $template;

        if (!file_exists($path))
            return false;

        return file_get_contents($path);
    }

    static public function editSource($template, $content)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        $path = DATA_ROOT . '/www/squelettes/' . $template;

        return file_put_contents($path, $content);
    }

    static public function resetSource($template)
    {
        if (!preg_match('!^[\w\d_-]+(?:\.[\w\d_-]+)*$!', $template))
            return false;

        if (file_exists(DATA_ROOT . '/www/squelettes/' . $template))
        {
            unlink(DATA_ROOT . '/www/squelettes/' . $template);
        }

        return true;
    }

    static public function listSources()
    {
        $sources = array();

        $dir = dir(ROOT . '/www/squelettes-dist');

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
                $sources[] = $file;
        }

        $dir->close();

        $dir = dir(DATA_ROOT . '/www/squelettes');

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
                $sources[] = $file;
        }

Modified src/include/init.php from [f8b9ad29cf] to [3022aaf506].

6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

/*
 * Version de Garradin
 */

function garradin_version()
{
    if (defined('GARRADIN_VERSION'))
    {
        return GARRADIN_VERSION;
    }

    $file = __DIR__ . '/../VERSION';

    if (file_exists($file))
    {
        $version = trim(file_get_contents($file));
    }
    else
    {
        $version = 'unknown';
    }

    define('GARRADIN_VERSION', $version);
    return $version;
}

function garradin_manifest()
{
    $file = __DIR__ . '/../../manifest.uuid';

................................................................................

// Configuration externalisée, pour projets futurs (fermes de garradins ?)
if (file_exists(__DIR__ . '/../config.local.php'))
{
    require __DIR__ . '/../config.local.php';
}

if (!defined('GARRADIN_ROOT'))
{
    define('GARRADIN_ROOT', dirname(__DIR__));
}

if (!defined('GARRADIN_DATA_ROOT'))
{
    define('GARRADIN_DATA_ROOT', GARRADIN_ROOT);
}

if (!defined('GARRADIN_DB_FILE'))
{
    define('GARRADIN_DB_FILE', GARRADIN_DATA_ROOT . '/association.sqlite');
}

if (!defined('GARRADIN_DB_SCHEMA'))
{
    define('GARRADIN_DB_SCHEMA', GARRADIN_ROOT . '/include/data/schema.sql');
}

if (!defined('WWW_URI'))
{
    // Automagic URL discover
    $path = str_replace(GARRADIN_ROOT . '/www', '', getcwd());
    $path = str_replace($path, '', dirname($_SERVER['SCRIPT_NAME']));
    $path = (!empty($path[0]) && $path[0] != '/') ? '/' . $path : $path;
    $path = (substr($path, -1) != '/') ? $path . '/' : $path;
    define('WWW_URI', $path);
}

if (!defined('WWW_URL'))
{
    $host = isset($_SERVER['HTTP_HOST']) 
        ? $_SERVER['HTTP_HOST'] 
        : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
    define('WWW_URL', 'http' . (!empty($_SERVER['HTTPS']) ? 's' : '') . '://' . $host . WWW_URI);
}

if (!defined('GARRADIN_PLUGINS_PATH'))
{
    define('GARRADIN_PLUGINS_PATH', GARRADIN_DATA_ROOT . '/plugins');
}

// Affichage des erreurs par défaut
if (!defined('GARRADIN_SHOW_ERRORS'))
{
    define('GARRADIN_SHOW_ERRORS', true);
}

define('GARRADIN_WEBSITE', 'http://garradin.eu/');
define('GARRADIN_PLUGINS_URL', 'https://garradin.eu/plugins/list.json');

// PHP devrait être assez intelligent pour chopper la TZ système mais nan
// il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour 
// éviter le message d'erreur à la con on définit une timezone par défaut
// Pour utiliser une autre timezone, il suffit de définir date.timezone dans
// un .htaccess ou dans config.local.php
if (!ini_get('date.timezone'))
................................................................................
    }
    else
    {
        ini_set('date.timezone', 'Europe/Paris');
    }
}

if (GARRADIN_SHOW_ERRORS)
{
    // Gestion par défaut des erreurs
    ini_set('error_log', GARRADIN_DATA_ROOT . '/error.log');
    ini_set('log_errors', true);
    ini_set('display_errors', true);
    ini_set('html_errors', false);

    if (PHP_SAPI != 'cli')
    {
        ini_set('error_prepend_string', '<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">body { font-family: sans-serif; } h3 { color: darkred; } 
................................................................................
            exit;
        }
        catch (Exception $e)
        {
        }
    }

    $file = str_replace(GARRADIN_ROOT, '', $e->getFile());

    $error = "Exception of type ".get_class($e)." happened !\n\n".
        $e->getCode()." - ".$e->getMessage()."\n\nIn: ".
        $file . ":" . $e->getLine()."\n\n";

    if (!empty($_SERVER['HTTP_HOST']) && !empty($_SERVER['REQUEST_URI']))
        $error .= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."\n\n";
................................................................................
    
    $error = str_replace("\r", '', $error);
    
    if (PHP_SAPI == 'cli')
    {
        echo $error;
    }
    elseif (GARRADIN_SHOW_ERRORS)
    {
        echo '<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">body { font-family: sans-serif; } h3 { color: darkred; }
        pre { text-shadow: 2px 2px 5px black; color: darkgreen; font-size: 2em; float: left; margin: 0 1em 0 0; padding: 1em; background: #cfc; border-radius: 50px; }</style>
        <pre> \__/<br /> (xx)<br />//||\\\\</pre>
        <h1>Erreur d\'exécution</h1>
        <p>Une erreur s\'est produite à l\'exécution de Garradin. Pour rapporter ce bug
        merci d\'inclure le message suivant :</p>
................................................................................

        if (in_array($classname, self::$libs)) {
            $filename = 'lib.' . $classname . '.php';
        } else {
            $filename .= 'class.' . $classname . '.php';
        }

        $filename = GARRADIN_ROOT . '/include/' . $filename;

        if (array_key_exists($filename, self::$loaded))
        {
            return true;
        }

        if (!file_exists($filename)) {
................................................................................

$n = new Membres;

/*
 * Inclusion des fichiers de base
 */

if (!defined('GARRADIN_INSTALL_PROCESS') && !defined('GARRADIN_UPGRADE_PROCESS'))
{
    if (!file_exists(GARRADIN_DB_FILE))
    {
        utils::redirect('/admin/install.php');
    }

    $config = Config::getInstance();

    if (version_compare($config->getVersion(), garradin_version(), '<'))
    {
        utils::redirect('/admin/upgrade.php');
    }
}

?>







|

|













|







 







|

|


|

|


|

|


|

|


|


|



|


|




|


|

|



|

|


|
|







 







|


|







 







|







 







|







 







|







 







|

|













6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310

/*
 * Version de Garradin
 */

function garradin_version()
{
    if (defined('Garradin\VERSION'))
    {
        return VERSION;
    }

    $file = __DIR__ . '/../VERSION';

    if (file_exists($file))
    {
        $version = trim(file_get_contents($file));
    }
    else
    {
        $version = 'unknown';
    }

    define('Garradin\VERSION', $version);
    return $version;
}

function garradin_manifest()
{
    $file = __DIR__ . '/../../manifest.uuid';

................................................................................

// Configuration externalisée, pour projets futurs (fermes de garradins ?)
if (file_exists(__DIR__ . '/../config.local.php'))
{
    require __DIR__ . '/../config.local.php';
}

if (!defined('Garradin\ROOT'))
{
    define('Garradin\ROOT', dirname(__DIR__));
}

if (!defined('Garradin\DATA_ROOT'))
{
    define('Garradin\DATA_ROOT', ROOT);
}

if (!defined('Garradin\DB_FILE'))
{
    define('Garradin\DB_FILE', DATA_ROOT . '/association.sqlite');
}

if (!defined('Garradin\DB_SCHEMA'))
{
    define('Garradin\DB_SCHEMA', ROOT . '/include/data/schema.sql');
}

if (!defined('Garradin\WWW_URI'))
{
    // Automagic URL discover
    $path = str_replace(ROOT . '/www', '', getcwd());
    $path = str_replace($path, '', dirname($_SERVER['SCRIPT_NAME']));
    $path = (!empty($path[0]) && $path[0] != '/') ? '/' . $path : $path;
    $path = (substr($path, -1) != '/') ? $path . '/' : $path;
    define('Garradin\WWW_URI', $path);
}

if (!defined('Garradin\WWW_URL'))
{
    $host = isset($_SERVER['HTTP_HOST']) 
        ? $_SERVER['HTTP_HOST'] 
        : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
    define('Garradin\WWW_URL', 'http' . (!empty($_SERVER['HTTPS']) ? 's' : '') . '://' . $host . WWW_URI);
}

if (!defined('Garradin\PLUGINS_PATH'))
{
    define('Garradin\PLUGINS_PATH', DATA_ROOT . '/plugins');
}

// Affichage des erreurs par défaut
if (!defined('Garradin\SHOW_ERRORS'))
{
    define('Garradin\SHOW_ERRORS', true);
}

define('Garradin\WEBSITE', 'http://garradin.eu/');
define('Garradin\PLUGINS_URL', 'https://garradin.eu/plugins/list.json');

// PHP devrait être assez intelligent pour chopper la TZ système mais nan
// il sait pas faire (sauf sur Debian qui a le bon patch pour ça), donc pour 
// éviter le message d'erreur à la con on définit une timezone par défaut
// Pour utiliser une autre timezone, il suffit de définir date.timezone dans
// un .htaccess ou dans config.local.php
if (!ini_get('date.timezone'))
................................................................................
    }
    else
    {
        ini_set('date.timezone', 'Europe/Paris');
    }
}

if (SHOW_ERRORS)
{
    // Gestion par défaut des erreurs
    ini_set('error_log', DATA_ROOT . '/error.log');
    ini_set('log_errors', true);
    ini_set('display_errors', true);
    ini_set('html_errors', false);

    if (PHP_SAPI != 'cli')
    {
        ini_set('error_prepend_string', '<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">body { font-family: sans-serif; } h3 { color: darkred; } 
................................................................................
            exit;
        }
        catch (Exception $e)
        {
        }
    }

    $file = str_replace(ROOT, '', $e->getFile());

    $error = "Exception of type ".get_class($e)." happened !\n\n".
        $e->getCode()." - ".$e->getMessage()."\n\nIn: ".
        $file . ":" . $e->getLine()."\n\n";

    if (!empty($_SERVER['HTTP_HOST']) && !empty($_SERVER['REQUEST_URI']))
        $error .= 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']."\n\n";
................................................................................
    
    $error = str_replace("\r", '', $error);
    
    if (PHP_SAPI == 'cli')
    {
        echo $error;
    }
    elseif (SHOW_ERRORS)
    {
        echo '<!DOCTYPE html><meta charset="utf-8" /><style type="text/css">body { font-family: sans-serif; } h3 { color: darkred; }
        pre { text-shadow: 2px 2px 5px black; color: darkgreen; font-size: 2em; float: left; margin: 0 1em 0 0; padding: 1em; background: #cfc; border-radius: 50px; }</style>
        <pre> \__/<br /> (xx)<br />//||\\\\</pre>
        <h1>Erreur d\'exécution</h1>
        <p>Une erreur s\'est produite à l\'exécution de Garradin. Pour rapporter ce bug
        merci d\'inclure le message suivant :</p>
................................................................................

        if (in_array($classname, self::$libs)) {
            $filename = 'lib.' . $classname . '.php';
        } else {
            $filename .= 'class.' . $classname . '.php';
        }

        $filename = ROOT . '/include/' . $filename;

        if (array_key_exists($filename, self::$loaded))
        {
            return true;
        }

        if (!file_exists($filename)) {
................................................................................

$n = new Membres;

/*
 * Inclusion des fichiers de base
 */

if (!defined('Garradin\INSTALL_PROCESS') && !defined('Garradin\UPGRADE_PROCESS'))
{
    if (!file_exists(DB_FILE))
    {
        utils::redirect('/admin/install.php');
    }

    $config = Config::getInstance();

    if (version_compare($config->getVersion(), garradin_version(), '<'))
    {
        utils::redirect('/admin/upgrade.php');
    }
}

?>

Modified src/include/lib.static_cache.php from [2b38bda8cc] to [3f6dc6e023].

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Static_Cache
{
	const EXPIRE = 3600; // 1h
	const CLEAN_EXPIRE = 86400; // 1 day

	protected static function _getCacheDir()
	{
		return GARRADIN_DATA_ROOT . '/cache/static';
	}

	protected static function _getCachePath($id)
	{
		$id = 'cache_' . sha1($id);
		return self::_getCacheDir() . '/' . $id;
	}







|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Static_Cache
{
	const EXPIRE = 3600; // 1h
	const CLEAN_EXPIRE = 86400; // 1 day

	protected static function _getCacheDir()
	{
		return DATA_ROOT . '/cache/static';
	}

	protected static function _getCachePath($id)
	{
		$id = 'cache_' . sha1($id);
		return self::_getCacheDir() . '/' . $id;
	}

Modified src/include/lib.template.php from [b7a6d505ca] to [e37f68648c].

1
2
3
4
5
6
7
8
9
10
11
12
..
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?php

namespace Garradin;

require_once GARRADIN_ROOT . '/include/libs/template_lite/class.template.php';

class Template extends \Template_Lite
{
    static protected $_instance = null;

    static public function getInstance()
    {
................................................................................

    public function __construct()
    {
        parent::__construct();

        $this->cache = false;

        $this->compile_dir = GARRADIN_DATA_ROOT . '/cache/compiled';
        $this->template_dir = GARRADIN_ROOT . '/templates';

        $this->compile_check = true;

        $this->reserved_template_varname = 'tpl';

        $this->assign('www_url', WWW_URL);
        $this->assign('self_url', utils::getSelfUrl());
................................................................................
    {
        throw new Template_Exception('Paramètres old et new requis.');
    }

    $old = $params['old'];
    $new = $params['new'];

    require_once GARRADIN_ROOT . '/include/libs/diff/class.simplediff.php';
    $diff = \simpleDiff::diff_to_array(false, $old, $new, 3);

    $out = '<table class="diff">';
    $prev = key($diff);

    foreach ($diff as $i=>$line)
    {




|







 







|
|







 







|







1
2
3
4
5
6
7
8
9
10
11
12
..
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
<?php

namespace Garradin;

require_once ROOT . '/include/libs/template_lite/class.template.php';

class Template extends \Template_Lite
{
    static protected $_instance = null;

    static public function getInstance()
    {
................................................................................

    public function __construct()
    {
        parent::__construct();

        $this->cache = false;

        $this->compile_dir = DATA_ROOT . '/cache/compiled';
        $this->template_dir = ROOT . '/templates';

        $this->compile_check = true;

        $this->reserved_template_varname = 'tpl';

        $this->assign('www_url', WWW_URL);
        $this->assign('self_url', utils::getSelfUrl());
................................................................................
    {
        throw new Template_Exception('Paramètres old et new requis.');
    }

    $old = $params['old'];
    $new = $params['new'];

    require_once ROOT . '/include/libs/diff/class.simplediff.php';
    $diff = \simpleDiff::diff_to_array(false, $old, $new, 3);

    $out = '<table class="diff">';
    $prev = key($diff);

    foreach ($diff as $i=>$line)
    {

Modified src/include/lib.utils.php from [cd368939e7] to [42831a0855].

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
        return '';
    }

    static public function &getCountryList()
    {
        if (is_null(self::$country_list))
        {
            require_once GARRADIN_ROOT . '/include/libs/countries/countries_fr.php';
            self::$country_list = $countries;
        }

        return self::$country_list;
    }

    static public function getCountryName($code)
................................................................................
            }, $str);
    }

    static public function htmlGarbage2xhtml($str)
    {
        if (!self::$g2x)
        {
            require_once GARRADIN_ROOT . '/include/libs/garbage2xhtml/lib.garbage2xhtml.php';
            self::$g2x = new \garbage2xhtml;
            self::$g2x->core_attributes = array('class', 'id', 'title');
        }

        return self::$g2x->process($str);
    }

................................................................................
        {
            return mail($to, $subject, $content, $headers);
        }
    }

    static public function clearCaches()
    {
        $path = GARRADIN_ROOT . '/cache/compiled';
        $dir = dir($path);

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
            {
                unlink($path . '/' . $file);
................................................................................

        $dir->close();
        return true;
    }

    static public function suggestPassword()
    {
        require_once GARRADIN_ROOT . '/include/libs/passphrase/lib.passphrase.french.php';
        return \Passphrase::generate();
    }

    static public function checkIBAN($iban)
    {
        $iban = substr($iban, 4) . substr($iban, 0, 4);
        $iban = str_replace(range('A', 'Z'), range(10, 35), $iban);







|







 







|







 







|







 







|







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
...
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
        return '';
    }

    static public function &getCountryList()
    {
        if (is_null(self::$country_list))
        {
            require_once ROOT . '/include/libs/countries/countries_fr.php';
            self::$country_list = $countries;
        }

        return self::$country_list;
    }

    static public function getCountryName($code)
................................................................................
            }, $str);
    }

    static public function htmlGarbage2xhtml($str)
    {
        if (!self::$g2x)
        {
            require_once ROOT . '/include/libs/garbage2xhtml/lib.garbage2xhtml.php';
            self::$g2x = new \garbage2xhtml;
            self::$g2x->core_attributes = array('class', 'id', 'title');
        }

        return self::$g2x->process($str);
    }

................................................................................
        {
            return mail($to, $subject, $content, $headers);
        }
    }

    static public function clearCaches()
    {
        $path = DATA_ROOT . '/cache/compiled';
        $dir = dir($path);

        while ($file = $dir->read())
        {
            if ($file[0] != '.')
            {
                unlink($path . '/' . $file);
................................................................................

        $dir->close();
        return true;
    }

    static public function suggestPassword()
    {
        require_once ROOT . '/include/libs/passphrase/lib.passphrase.french.php';
        return \Passphrase::generate();
    }

    static public function checkIBAN($iban)
    {
        $iban = substr($iban, 4) . substr($iban, 0, 4);
        $iban = str_replace(range('A', 'Z'), range(10, 35), $iban);

Modified src/www/admin/_inc.php from [1249a3443e] to [50cf88ffa0].

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require_once __DIR__ . '/../../include/init.php';

$tpl = Template::getInstance();
$tpl->assign('admin_url', WWW_URL . 'admin/');

$membres = new Membres;

if (!defined('GARRADIN_LOGIN_PROCESS'))
{
    if (!$membres->isLogged())
    {
        utils::redirect('/admin/login.php');
    }

    $tpl->assign('config', Config::getInstance()->getConfig());







|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require_once __DIR__ . '/../../include/init.php';

$tpl = Template::getInstance();
$tpl->assign('admin_url', WWW_URL . 'admin/');

$membres = new Membres;

if (!defined('Garradin\LOGIN_PROCESS'))
{
    if (!$membres->isLogged())
    {
        utils::redirect('/admin/login.php');
    }

    $tpl->assign('config', Config::getInstance()->getConfig());

Modified src/www/admin/compta/graph.php from [1d61f36647] to [79c2b4054b].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

$graph = utils::get('g');

if (Static_Cache::expired('graph_' . $graph))
{
	$stats = new Compta_Stats;

	require_once GARRADIN_ROOT . '/include/libs/svgplot/lib.svgplot.php';

	$plot = new \SVGPlot(400, 300);

	if ($graph == 'recettes_depenses')
	{
		$r = new \SVGPlot_Data($stats->recettes());
		$r->title = 'Recettes';







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

$graph = utils::get('g');

if (Static_Cache::expired('graph_' . $graph))
{
	$stats = new Compta_Stats;

	require_once ROOT . '/include/libs/svgplot/lib.svgplot.php';

	$plot = new \SVGPlot(400, 300);

	if ($graph == 'recettes_depenses')
	{
		$r = new \SVGPlot_Data($stats->recettes());
		$r->title = 'Recettes';

Modified src/www/admin/compta/pie.php from [806430726a] to [e452ea3f35].

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$graph = utils::get('g');

if (Static_Cache::expired('graph_' . $graph))
{
	$stats = new Compta_Stats;
	$categories = new Compta_Categories;

	require_once GARRADIN_ROOT . '/include/libs/svgplot/lib.svgpie.php';

	$pie = new \SVGPie(400, 250);

	if ($graph == 'recettes')
	{
		$data = $stats->repartitionRecettes();
		$categories = $categories->getList(Compta_Categories::RECETTES);







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$graph = utils::get('g');

if (Static_Cache::expired('graph_' . $graph))
{
	$stats = new Compta_Stats;
	$categories = new Compta_Categories;

	require_once ROOT . '/include/libs/svgplot/lib.svgpie.php';

	$pie = new \SVGPie(400, 250);

	if ($graph == 'recettes')
	{
		$data = $stats->repartitionRecettes();
		$categories = $categories->getList(Compta_Categories::RECETTES);

Modified src/www/admin/install.php from [c0631cdd45] to [999d5d56e5].

67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
);

test_requis(
    is_writable(__DIR__ . '/../../cache') && is_readable(__DIR__ . '/../../cache'),
    'Le répertoire /cache n\'est pas accessible en lecture/écriture.'
);

define('GARRADIN_INSTALL_PROCESS', true);

require_once __DIR__ . '/../../include/init.php';

if (!file_exists(GARRADIN_DB_FILE))
{
    // Renommage du fichier sqlite à la version 0.5.0
    $old_file = str_replace('.sqlite', '.db', GARRADIN_DB_FILE);

    if (file_exists($old_file))
    {
        rename($old_file, GARRADIN_DB_FILE);
        utils::redirect('/admin/upgrade.php');
    }
}

$tpl = Template::getInstance();

$tpl->assign('admin_url', WWW_URL . 'admin/');

if (file_exists(GARRADIN_DB_FILE))
{
    $tpl->assign('disabled', true);
}
else
{
    $tpl->assign('disabled', false);
    $error = false;
................................................................................
        else
        {
            try {
                $db = DB::getInstance(true);

                // Création de la base de données
                $db->exec('BEGIN;');
                $db->exec(file_get_contents(GARRADIN_DB_SCHEMA));
                $db->exec('END;');

                // Configuration de base
                $config = Config::getInstance();
                $config->set('nom_asso', utils::post('nom_asso'));
                $config->set('adresse_asso', utils::post('adresse_asso'));
                $config->set('email_asso', utils::post('email_asso'));
................................................................................

                $config->save();

                utils::redirect('/admin/login.php');
            }
            catch (UserException $e)
            {
                @unlink(GARRADIN_DB_FILE);
                $error = $e->getMessage();
            }
        }
    }

    $tpl->assign('error', $error);
}

$tpl->assign('passphrase', utils::suggestPassword());

$tpl->display('admin/install.tpl');

?>







|



|


|



|








|







 







|







 







|













67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
);

test_requis(
    is_writable(__DIR__ . '/../../cache') && is_readable(__DIR__ . '/../../cache'),
    'Le répertoire /cache n\'est pas accessible en lecture/écriture.'
);

const INSTALL_PROCESS = true;

require_once __DIR__ . '/../../include/init.php';

if (!file_exists(DB_FILE))
{
    // Renommage du fichier sqlite à la version 0.5.0
    $old_file = str_replace('.sqlite', '.db', DB_FILE);

    if (file_exists($old_file))
    {
        rename($old_file, DB_FILE);
        utils::redirect('/admin/upgrade.php');
    }
}

$tpl = Template::getInstance();

$tpl->assign('admin_url', WWW_URL . 'admin/');

if (file_exists(DB_FILE))
{
    $tpl->assign('disabled', true);
}
else
{
    $tpl->assign('disabled', false);
    $error = false;
................................................................................
        else
        {
            try {
                $db = DB::getInstance(true);

                // Création de la base de données
                $db->exec('BEGIN;');
                $db->exec(file_get_contents(DB_SCHEMA));
                $db->exec('END;');

                // Configuration de base
                $config = Config::getInstance();
                $config->set('nom_asso', utils::post('nom_asso'));
                $config->set('adresse_asso', utils::post('adresse_asso'));
                $config->set('email_asso', utils::post('email_asso'));
................................................................................

                $config->save();

                utils::redirect('/admin/login.php');
            }
            catch (UserException $e)
            {
                @unlink(DB_FILE);
                $error = $e->getMessage();
            }
        }
    }

    $tpl->assign('error', $error);
}

$tpl->assign('passphrase', utils::suggestPassword());

$tpl->display('admin/install.tpl');

?>

Modified src/www/admin/login.php from [2e1cd5e3ac] to [97047c6f65].

1
2
3
4

5





6
7
8
9
10
11
12
<?php
namespace Garradin;

define('GARRADIN_LOGIN_PROCESS', true);

require_once __DIR__ . '/_inc.php';






// Relance session_start et renvoie une image de 1px transparente
if (isset($_GET['keepSessionAlive']))
{
    $membres->keepSessionAlive();

    header('Cache-Control: no-cache, must-revalidate');



|
>

>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
namespace Garradin;

const LOGIN_PROCESS = true;

require_once __DIR__ . '/_inc.php';

if ($membres->isLogged())
{
    utils::redirect('/admin/');
}

// Relance session_start et renvoie une image de 1px transparente
if (isset($_GET['keepSessionAlive']))
{
    $membres->keepSessionAlive();

    header('Cache-Control: no-cache, must-revalidate');

Modified src/www/admin/logout.php from [e871d9cd95] to [50a6fd4fa1].

1
2
3
4
5
6
7
8
9
10
<?php
namespace Garradin;

define('GARRADIN_LOGIN_PROCESS', true);
require_once __DIR__ . '/_inc.php';

$membres->logout();
utils::redirect('/');

?>



|






1
2
3
4
5
6
7
8
9
10
<?php
namespace Garradin;

const LOGIN_PROCESS = true;
require_once __DIR__ . '/_inc.php';

$membres->logout();
utils::redirect('/');

?>

Modified src/www/admin/password.php from [a3f7db9d48] to [e453c05204].

1
2
3
4

5
6
7
8
9
10
11
<?php
namespace Garradin;

define('GARRADIN_LOGIN_PROCESS', true);

require_once __DIR__ . '/_inc.php';

$error = false;

if (trim(utils::get('c')))
{
    if ($membres->recoverPasswordConfirm(utils::get('c')))



|
>







1
2
3
4
5
6
7
8
9
10
11
12
<?php
namespace Garradin;

const LOGIN_PROCESS = true;

require_once __DIR__ . '/_inc.php';

$error = false;

if (trim(utils::get('c')))
{
    if ($membres->recoverPasswordConfirm(utils::get('c')))

Modified src/www/admin/upgrade.php from [bad6ec907f] to [ed9b9ebda9].

1
2
3
4
5
6
7
8
9
10
11
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
namespace Garradin;

define('GARRADIN_UPGRADE_PROCESS', true);

require_once __DIR__ . '/../../include/init.php';

$config = Config::getInstance();

$v = $config->getVersion();

................................................................................

if (version_compare($v, '0.4.0', '<'))
{
    $config->set('monnaie', '€');
    $config->set('pays', 'FR');
    $config->save();

    $db->exec(file_get_contents(GARRADIN_ROOT . '/include/data/0.4.0.sql'));

    // Mise en place compta
    $comptes = new Compta_Comptes;
    $comptes->importPlan();

    $comptes = new Compta_Categories;
    $comptes->importCategories();
}

if (version_compare($v, '0.4.3', '<'))
{
    $db->exec(file_get_contents(GARRADIN_ROOT . '/include/data/0.4.3.sql'));
}

if (version_compare($v, '0.4.5', '<'))
{
    // Mise à jour plan comptable
    $comptes = new Compta_Comptes;
    $comptes->importPlan();
................................................................................
{
    $categories = new Membres_Categories;
    $list = $categories->listComplete();

    $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

    // Mise à jour base de données
    $db->exec(file_get_contents(GARRADIN_ROOT . '/include/data/0.6.0.sql'));

    $id_cat_cotisation = $db->querySingle('SELECT id FROM compta_categories WHERE compte = 756 LIMIT 1;');

    // Conversion des cotisations de catégories en transactions
    foreach ($list as $cat)
    {
        $db->simpleInsert('cotisations', [
................................................................................
            WHERE date_cotisation IS NOT NULL AND date_cotisation != \'\' AND id_categorie = :id_categorie;',
            $args);

        // Mais on ne crée pas d'écriture comptable, car elles existent probablement déjà
    }

    // Déplacement des squelettes dans le répertoire public
    if (!file_exists(GARRADIN_ROOT . '/www/squelettes'))
    {
        mkdir(GARRADIN_ROOT . '/www/squelettes');
    }

    if (file_exists(GARRADIN_ROOT . '/squelettes'))
    {
        $dir = dir(GARRADIN_ROOT . '/squelettes');

        while ($file = $dir->read())
        {
            if ($file == '.' || $file == '..')
                continue;

            rename(GARRADIN_ROOT . '/squelettes/' . $file, GARRADIN_ROOT . '/www/squelettes/' . $file);
        }

        $dir->close();

        @rmdir(GARRADIN_ROOT . '/squelettes');
    }

    $db->exec('END; PRAGMA foreign_keys = ON;');
}

utils::clearCaches();




|







 







|











|







 







|







 







|

|


|

|






|




|







1
2
3
4
5
6
7
8
9
10
11
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
namespace Garradin;

const UPGRADE_PROCESS = true;

require_once __DIR__ . '/../../include/init.php';

$config = Config::getInstance();

$v = $config->getVersion();

................................................................................

if (version_compare($v, '0.4.0', '<'))
{
    $config->set('monnaie', '€');
    $config->set('pays', 'FR');
    $config->save();

    $db->exec(file_get_contents(ROOT . '/include/data/0.4.0.sql'));

    // Mise en place compta
    $comptes = new Compta_Comptes;
    $comptes->importPlan();

    $comptes = new Compta_Categories;
    $comptes->importCategories();
}

if (version_compare($v, '0.4.3', '<'))
{
    $db->exec(file_get_contents(ROOT . '/include/data/0.4.3.sql'));
}

if (version_compare($v, '0.4.5', '<'))
{
    // Mise à jour plan comptable
    $comptes = new Compta_Comptes;
    $comptes->importPlan();
................................................................................
{
    $categories = new Membres_Categories;
    $list = $categories->listComplete();

    $db->exec('PRAGMA foreign_keys = OFF; BEGIN;');

    // Mise à jour base de données
    $db->exec(file_get_contents(ROOT . '/include/data/0.6.0.sql'));

    $id_cat_cotisation = $db->querySingle('SELECT id FROM compta_categories WHERE compte = 756 LIMIT 1;');

    // Conversion des cotisations de catégories en transactions
    foreach ($list as $cat)
    {
        $db->simpleInsert('cotisations', [
................................................................................
            WHERE date_cotisation IS NOT NULL AND date_cotisation != \'\' AND id_categorie = :id_categorie;',
            $args);

        // Mais on ne crée pas d'écriture comptable, car elles existent probablement déjà
    }

    // Déplacement des squelettes dans le répertoire public
    if (!file_exists(ROOT . '/www/squelettes'))
    {
        mkdir(ROOT . '/www/squelettes');
    }

    if (file_exists(ROOT . '/squelettes'))
    {
        $dir = dir(ROOT . '/squelettes');

        while ($file = $dir->read())
        {
            if ($file == '.' || $file == '..')
                continue;

            rename(ROOT . '/squelettes/' . $file, ROOT . '/www/squelettes/' . $file);
        }

        $dir->close();

        @rmdir(ROOT . '/squelettes');
    }

    $db->exec('END; PRAGMA foreign_keys = ON;');
}

utils::clearCaches();