Browse code

Commit initial

Chrisix authored on 08/05/2017 14:42:33
Showing 186 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,14 @@
1
+LICENCE PUBLIQUE COMME LA WTFPL MAIS EN PLUS POLI
2
+                     Version 1, mai 2017
3
+
4
+Copyright (C) 2017 Chrisix
5
+
6
+La copie et la distribution de copies exactes de cette licence sont
7
+autorisées, et toute modification est permise à condition de changer
8
+le nom de la licence. 
9
+
10
+        CONDITIONS DE COPIE, DISTRIBUTON ET MODIFICATION
11
+     DE LA LICENCE PUBLIQUE COMME LA WTFPL MAIS EN PLUS POLI
12
+
13
+ 0. Faites ce que vous voulez, je n'en ai cure.
14
+ 
0 15
\ No newline at end of file
1 16
new file mode 100644
... ...
@@ -0,0 +1,5 @@
1
+# olcc - OnLineCoinCoin
2
+
3
+OnlineCoincoin est un client multi-tribune conçu pour tourner dans un navigateur, avec le moins possible de code serveur.
4
+Quand j'aurai un peu de temps, je ferai un README un peu plus fourni.
5
+En attendant, ceux qui savent sauront.
0 6
new file mode 100644
... ...
@@ -0,0 +1,17 @@
1
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
3
+<head>
4
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5
+  <title>Poster un fichier</title>
6
+</head>
7
+
8
+<body>
9
+    <form action="attach.php" id="attach-form" method="post" enctype="multipart/form-data">
10
+      <label for="attach_file">Poster le fichier&nbsp;:</label>
11
+      <input id="attach_file" name="attach_file" type="file" />
12
+      <input type="submit" name="submit" value="Envoyer" />
13
+      <button onclick="parent.closePanel('attach')">Annuler</button>
14
+    </form>
15
+</body>
16
+
17
+</html>
0 18
new file mode 100644
... ...
@@ -0,0 +1,53 @@
1
+<?php
2
+  $userfile = $_FILES['attach_file']['name'];
3
+  $tmpfile = $_FILES['attach_file']['tmp_name'];
4
+  $error = $_FILES['attach_file']['error'];
5
+  
6
+  $dest_dir = "attach";
7
+  if( !is_dir( $dest_dir ) ) {
8
+    mkdir( $dest_dir );
9
+  }
10
+  $dest = basename( $userfile );
11
+  $ext = substr($dest, strrpos($dest, ".")+1);
12
+  if ($ext == "php" || $ext == "html") {
13
+     $dest = $dest. ".txt";
14
+  }
15
+  $new_file_name = date("YmdHis") . "_" . $dest;
16
+  $new_file = $dest_dir . "/" . $new_file_name;
17
+  if( file_exists( $new_file ) ) { unlink( $new_file ); }
18
+  move_uploaded_file($tmpfile, $new_file );
19
+
20
+  $sname = $_SERVER['SERVER_NAME'];
21
+  $uri = $_SERVER['REQUEST_URI'];
22
+  $folder = substr($uri, 0, strrpos($uri, "/"));
23
+
24
+  $fileurl = "http://$sname$folder/$dest_dir/".urlencode($new_file_name);
25
+
26
+?>
27
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
28
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
29
+<head>
30
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
31
+  <title>Attach file</title>
32
+</head>
33
+<body>
34
+<?php
35
+  if( $error ) {
36
+?>
37
+    <img style="float:right" src="img/cancel.png" alt="[Fermer]" title="Fermer" onclick="parent.closePanel('attach')" />
38
+    <h3>Échec du téléchargement</h3>
39
+    <p><tt>Erreur&nbsp;: <?php echo( $error ); ?></tt></p>
40
+<?php
41
+  } else {
42
+?>
43
+    <script type="text/javascript"><!--
44
+      parent.postFile("<?php echo($dest); ?>", "<?php echo($fileurl); ?>");
45
+    // -->
46
+    </script>
47
+<?php
48
+  }
49
+?>
50
+</body>
51
+
52
+</html>
53
+
0 54
new file mode 100644
... ...
@@ -0,0 +1,6 @@
1
+<html>
2
+  <head>
3
+    <title>Rien</title>
4
+  </head>
5
+  <body> </body>
6
+</html>
0 7
\ No newline at end of file
1 8
new file mode 100644
... ...
@@ -0,0 +1,96 @@
1
+<?php /* vim: set ts=4 sw=4 noet ai : */
2
+
3
+        error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED);
4
+
5
+	/* If $bDebug is true, append a line in the log file
6
+	to debug If-Modified-Since/Last-Modified handling. Do not
7
+	use in production environment. */
8
+
9
+	$bDebug   = false ;
10
+	$sVersion = '0.3.8' ;
11
+	$aHeaders = array( 'Accept: text/xml', 'Cache-Control: no-cache, must-revalidate' );
12
+
13
+
14
+        /* if (strpos($_REQUEST['url'], "bombefourchette")) die('[:kiki]'); */
15
+
16
+	/* Previous received "Last-Modified" HTTP response header
17
+	 * returned by the server is sent back in a "If-Modified-Since"
18
+	 * HTTP request header. */
19
+
20
+	if( isset( $_REQUEST['lastModified'] ) )
21
+	{
22
+		$aHeaders[] = 'If-Modified-Since: ' . $_REQUEST['lastModified'] ;
23
+	}
24
+
25
+	$rCurl = curl_init(
26
+		str_replace(
27
+			array( '{question}', '{amp}' ),
28
+			array(          '?',     '&' ),
29
+			$_REQUEST['url']
30
+		)
31
+	);
32
+	if( $rCurl === false ) 
33
+	{
34
+		die( 'Error: Unable to initialize cURL' );
35
+	}
36
+	
37
+	curl_setopt( $rCurl, CURLOPT_RETURNTRANSFER, true );
38
+	curl_setopt( $rCurl, CURLOPT_HEADER,         true );
39
+	curl_setopt( $rCurl, CURLOPT_HTTPHEADER,     $aHeaders );
40
+	curl_setopt( $rCurl, CURLOPT_USERAGENT,      "onlineCoinCoin/" . $sVersion );
41
+	curl_setopt( $rCurl, CURLOPT_CONNECTTIMEOUT, 5 );
42
+	curl_setopt( $rCurl, CURLOPT_TIMEOUT,        8 );
43
+
44
+	if( isset( $_REQUEST['cookie'] ) )
45
+	{
46
+		curl_setopt($rCurl, CURLOPT_COOKIE, $_REQUEST['cookie']);
47
+	}
48
+
49
+	$sMessage = curl_exec( $rCurl );
50
+	if ($sMessage === false)
51
+	{
52
+		die( 'Error: ' . curl_error( $rCurl ) );
53
+	}
54
+
55
+	header( 'HTTP/1.0 ' . curl_getinfo( $rCurl, CURLINFO_HTTP_CODE ) );
56
+	header( 'Content-type: text/xml');
57
+
58
+	$sLastModified = null ;
59
+	$iHeaderLen = curl_getinfo( $rCurl, CURLINFO_HEADER_SIZE);
60
+	$aHeaders   = explode( "\r\n", substr( $sMessage, 0, $iHeaderLen ) );
61
+	foreach( $aHeaders as $sHeader )
62
+	{
63
+		list( $sName, $sValue ) = explode( ":", $sHeader, 2 );
64
+		if( isset($sName) && isset($sValue) )
65
+		{
66
+			if( strtolower(trim($sName)) == 'last-modified' )
67
+			{
68
+				$sLastModified = trim( $sValue );
69
+			}
70
+			header( 'X-Olcc-' . trim($sName) . ':' . trim($sValue) );
71
+		}
72
+	}
73
+
74
+	$sBody = substr( $sMessage, $iHeaderLen );
75
+	$iPos  = strpos( $sBody, '<' );
76
+	if(( ! empty( $sBody) )&&( $iPos === false ))
77
+	{
78
+		echo 'Error: ' . $sBody ;
79
+	}
80
+	else
81
+	{
82
+		echo preg_replace( '/<!DOCTYPE[^>]*>/', '', substr( $sBody, $iPos ), 1 );
83
+	}
84
+
85
+	if( $bDebug )
86
+	{
87
+		error_log( 
88
+			  'OLCC - '
89
+			. $_REQUEST['url']
90
+			. ' : '
91
+			. 'If-Modified-Since: '	. ( isset( $_REQUEST['lastModified'] ) ? $_REQUEST['lastModified'] : "NULL" ) . ' ; '
92
+			. 'Last-Modified: '     . ( isset( $sLastModified )            ? $sLastModified            : "NULL" ) . ' ; '
93
+			. 'Status: '            . curl_getinfo( $rCurl, CURLINFO_HTTP_CODE )
94
+		);
95
+	}
96
+?>
0 97
new file mode 100644
... ...
@@ -0,0 +1,583 @@
1
+/************************************************************
2
+ * OnlineCoinCoin, by Chrisix (chrisix@gmail.com)
3
+ * Définition de la classe Board, gérant une tribune
4
+ ************************************************************/
5
+
6
+function Board(name, perso) {
7
+  // Données statiques
8
+  this.name = name;
9
+  this.perso = perso;
10
+  this.getUrl = '';
11
+  this.postUrl = '';
12
+  this.postData = 'message=%m';
13
+  this.slip = SLIP_TAGS_ENCODED;
14
+  
15
+  // Données configurables
16
+  this.color = '#dac0de';
17
+  this.alias = '';
18
+  this.delay = DEFAULT_TIMEOUT;
19
+  this.login = '';
20
+  this.ua = '';
21
+  this.cookie = '';
22
+  this.lastModified = null;
23
+  this.initstate = STATE_IDLE;
24
+  // this.plonk = '';
25
+  
26
+  // Données dynamiques
27
+  this.lastId = 0;
28
+  this.state = STATE_LOADED;
29
+  this.timer = null;
30
+  this.nbPosts = 0;
31
+  
32
+  this.views = new Array();
33
+}
34
+
35
+// Board est un observable
36
+Board.prototype.addView = function (view) {
37
+    if (!this.views.contains(view)) {
38
+        this.views.push(view);
39
+    }
40
+}
41
+Board.prototype.removeView = function (view) {
42
+    this.views.remove(view);
43
+}
44
+Board.prototype.notify = function () {
45
+    var args = arguments;
46
+    for(var i=this.views.length; i--;) {
47
+        this.views[i].notified.apply(this.views[i], args);
48
+    }
49
+}
50
+
51
+// Mise à jour de la css de la board (couleur de fond)
52
+function BoardUpdateCSS(board) {
53
+    var bclass = "background: "+board.color+";";
54
+    var css = addCSSClass("tab-"+board.name, bclass);
55
+    css.style.background = board.color;
56
+    if (is_ie) {
57
+        var bcolor = board.color;
58
+    }
59
+    else {
60
+        var bcolor = "transparent";
61
+    }
62
+    bclass += "border-color:"+bcolor+";";
63
+    css = addCSSClass("pinni-"+board.name, bclass);
64
+    css.style.background = board.color;
65
+    css.style.borderColor = board.color;
66
+}
67
+Board.prototype.updateCSS = function () { BoardUpdateCSS(this); };
68
+
69
+// Change l'état de la tribune, affiche l'éventuel indicateur correspondant
70
+function BoardSetState(board, state) {
71
+    board.state = state;
72
+    board.notify(NOTIF_STATE, state);
73
+}
74
+Board.prototype.setState = function (state) { BoardSetState(this, state); };
75
+
76
+// Chargement de la config
77
+function BoardLoadConfig(board) {
78
+    var settings = getCookie(board.name);
79
+    if (settings) {
80
+        var pairs = settings.split("\n");
81
+        for (var i=pairs.length; i--;) {
82
+            var opt_val = pairs[i];
83
+            var eqpos = opt_val.indexOf('=');
84
+            var opt = opt_val.substr(0, eqpos);
85
+            var val = opt_val.substr(eqpos+1, opt_val.length);
86
+            switch(opt) {
87
+              case "getUrl":
88
+                board.getUrl = val;
89
+                break;
90
+              case "postUrl":
91
+                board.postUrl = val;
92
+                break;
93
+              case "postData":
94
+                board.postData = val;
95
+                break;
96
+              case "slip":
97
+                board.slip = val;
98
+                break;
99
+              case "color":
100
+                board.color = val;
101
+                break;
102
+              case "login":
103
+                board.login = val;
104
+                break;
105
+              case "ua":
106
+                board.ua = val;
107
+                break;
108
+              case "cookie":
109
+                board.cookie = val;
110
+                break;
111
+              case "alias":
112
+                board.alias = val;
113
+                break;
114
+              case "delay":
115
+                board.delay = eval(val)*1000;
116
+                break;
117
+              case "initstate":
118
+                board.initstate = val;
119
+                break;
120
+            }
121
+        }
122
+    }
123
+}
124
+Board.prototype.loadConfig = function () { BoardLoadConfig(this); };
125
+
126
+// Sauvegarde des données configurables
127
+function BoardSaveConfig(board) {
128
+    var tab = new Array();
129
+    tab.push("login="+board.login);
130
+    tab.push("ua="+board.ua);
131
+    tab.push("color="+board.color);
132
+    tab.push("cookie="+board.cookie);
133
+    tab.push("alias="+board.alias);
134
+    tab.push("delay="+(board.delay/1000));
135
+    tab.push("initstate="+board.state);
136
+    if (board.perso) {
137
+        tab.push("getUrl="+board.getUrl);
138
+        tab.push("postUrl="+board.postUrl);
139
+        tab.push("postData="+board.postData);
140
+        tab.push("slip="+board.slip);
141
+    }
142
+    setCookie(board.name, tab.join("\n"), 10000);
143
+}
144
+Board.prototype.saveConfig = function () { BoardSaveConfig(this); };
145
+
146
+// Démarre une tribune (lancement du timer d'auto-refresh)
147
+function BoardStart(board) {
148
+    if (board.state == STATE_LOADED) {
149
+        return;
150
+    }
151
+    board.setState(STATE_IDLE);
152
+    if (!board.timer) {
153
+        board.refresh();
154
+    }
155
+}
156
+Board.prototype.start = function () { BoardStart(this); };
157
+
158
+// Arrête une tribune (annule l'auto-refresh)
159
+function BoardStop(board) {
160
+    if (board.state == STATE_LOADED) {
161
+        return;
162
+    }
163
+    if (board.timer) {
164
+        window.clearTimeout(board.timer);
165
+        board.timer = null;
166
+    }
167
+    board.setState(STATE_STOP);
168
+}
169
+Board.prototype.stop = function () { BoardStop(this); };
170
+
171
+// Refresh immédiat de la tribune
172
+function BoardRefresh(board) {
173
+    if (board.state == STATE_LOADED) {
174
+        return;
175
+    }
176
+    if (board.timer) {
177
+        window.clearTimeout(board.timer);
178
+        board.timer = null;
179
+    }
180
+    board.getBackend();
181
+}
182
+Board.prototype.refresh = function () { BoardRefresh(this); };
183
+
184
+function BoardProcessBackend(board, xhr) {
185
+    try {
186
+        var status = xhr.status;
187
+    }
188
+    catch(err) {
189
+        board.setState(STATE_HTTP_ERROR);
190
+        board.timer = window.setTimeout(function () { BoardRefresh(board); }, board.delay);
191
+        return;
192
+    }
193
+    if (status == 200) {
194
+        board.setState(STATE_PARSE);
195
+        // alert(xhr.getAllResponseHeaders());
196
+        var cookie = xhr.getResponseHeader("X-Olcc-Set-Cookie");
197
+        // alert(cookie);
198
+        if (cookie && !board.cookie) board.cookie = cookie;
199
+        board.lastModified = xhr.getResponseHeader("X-Olcc-Last-Modified");
200
+        var res = xhr.responseText;
201
+        if (res.substr(0,6) == 'Error:') {
202
+            board.setState(STATE_HTTP_ERROR);
203
+        }
204
+        else {
205
+            var slip = loadXML(res);
206
+            if (no_xpath) {
207
+                var postNodes = slip.getElementsByTagName("post");
208
+                var i = postNodes.length;
209
+            }
210
+            else {
211
+                var postNodes = evalXPath(slip, '//post[@id > ' + board.lastId + ']');
212
+                var i = getLength(postNodes); // snapshotLength
213
+            }
214
+            var toScroll = false;
215
+            var hasNews = false;
216
+            if (i > 0) {
217
+                // Test si le dernier post du pinni est visible, pour savoir si on
218
+                // aura besoin de scroller après avoir inséré les nouveaux posts
219
+                var allposts = GlobalPinni.getElementsByTagName("div");
220
+                if (allposts.length > 0) {
221
+                    var yLastPost = allposts[allposts.length-1].offsetTop;
222
+                    var toScroll = (yLastPost < (GlobalPinni.scrollTop + window.innerHeight - 40));
223
+                }
224
+                else {
225
+                    toScroll = true;
226
+                }
227
+                // alert("tribune "+board.name+": "+i+" posts dans le backend");
228
+            }
229
+            while (--i >= 0) {
230
+                var postNode = getItem(postNodes, i);
231
+                var currentId = parseInt(postNode.getAttribute('id'));
232
+                if (currentId > board.lastId) {
233
+                    var timestamp = postNode.getAttribute('time');
234
+                    var hour = timestamp.substring(8);
235
+                    var clock = hour.substr(0,2) + ':' + hour.substr(2,2) + ':' + hour.substr(4,2); 
236
+                    var login = getNodeText(postNode.getElementsByTagName('login')[0]);
237
+                    var info = getNodeText(postNode.getElementsByTagName('info')[0]);
238
+                    var msgNode = postNode.getElementsByTagName('message')[0];
239
+                    if (board.slip == SLIP_TAGS_ENCODED) {
240
+                        message = getNodeText(msgNode);
241
+                    }
242
+                    else {
243
+                        message = serializeNodes(msgNode, "message");
244
+                    }
245
+                    var post = document.createElement('div');
246
+                    // Construction de l'id interne du post au format MMDDhhmmssii@board
247
+                    var postid = timestamp.substr(4, timestamp.length)+'99@'+board.name;
248
+                    post.setAttribute("id", postid);
249
+                    addClass(post, "pinni-"+board.name);
250
+                    addClass(post, "newpost")
251
+                    insertToPinni(post, postid, board, clock, login, info, message, currentId);
252
+                    board.nbPosts++;
253
+                    board.lastId = currentId;
254
+                    board.notify(NOTIF_NEW_POST, postid, post);
255
+                    hasNews = true;
256
+                }
257
+            }
258
+            if (toScroll) {
259
+                toPinniBottom();
260
+            }
261
+            if (!GlobalWindowFocus && hasNews && settings.value('sound_enabled')) {
262
+                // alert(GlobalIsPlaying);
263
+                sound_play("sound/"+settings.value('sound_new'));
264
+            }
265
+            board.setState(STATE_IDLE);
266
+        }
267
+    }
268
+    else if (status == 304) { /* Not Modified */
269
+      board.setState(STATE_IDLE);
270
+    }
271
+    else {
272
+      board.setState(STATE_HTTP_ERROR);
273
+    }
274
+    board.timer = window.setTimeout(function () { BoardRefresh(board); }, board.delay);
275
+}
276
+Board.prototype.process = function (xhr) { BoardProcessBackend(this, xhr); };
277
+
278
+function BoardGetBackend(board) {
279
+    board.setState(STATE_HTTP);
280
+    var xhr = new XMLHttpRequest();
281
+    // Le paramètre random est là pour IE6 qui ne tient pas compte des directives de cache
282
+    var get_url = 'backend.php?r='+Math.random();
283
+    if (board.cookie) get_url += '&cookie='+escape(board.cookie);
284
+    if (board.lastModified) get_url += '&lastModified=' + escape(board.lastModified);
285
+    get_url += '&url='+to_url(board.getUrl.replace("%i", board.lastId || ""));
286
+    xhr.open('GET', get_url, true);
287
+    xhr.onreadystatechange = function() {
288
+        switch (xhr.readyState) {
289
+          case 4:
290
+            BoardProcessBackend(board, xhr);
291
+            break;
292
+          default:
293
+            // inprogress(xhr);
294
+            break;
295
+        }
296
+      }
297
+    try {
298
+        xhr.send(null);
299
+    }
300
+    catch(err) {
301
+        board.setState(STATE_HTTP_ERROR);
302
+        board.timer = window.setTimeout(function () { BoardRefresh(board); }, board.delay);
303
+    }
304
+}
305
+Board.prototype.getBackend = function () { BoardGetBackend(this); };
306
+
307
+function BoardPost(board, msg) {
308
+    board.setState(STATE_HTTP);
309
+    var message = msg.replace(/\+/g, "#{plus}#");
310
+    message = message.replace(/\&/g, "#{amp}#");
311
+    message = message.replace(/\;/g, "#{dcomma}#");
312
+    message = message.replace(/\%/g, "#{percent}#");
313
+    var postdata = board.postData.replace("%m", message);
314
+    var xhr = new XMLHttpRequest();
315
+    xhr.open('POST', 'post.php', true);
316
+    xhr.onreadystatechange = function() {
317
+        switch (xhr.readyState) {
318
+          case 4:
319
+            BoardPostResult(board, xhr);
320
+            break;
321
+          default:
322
+            // inprogress(xhr);
323
+            break;
324
+        }
325
+      }
326
+    xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
327
+    var data = 'ua=' + to_url(board.ua || settings.value('default_ua'))
328
+             + '&cookie=' + escape(board.cookie)
329
+             + '&posturl=' + escape(board.postUrl)
330
+             + '&postdata=' + to_url(postdata);
331
+    xhr.send(data);
332
+}
333
+Board.prototype.post = function (msg) {
334
+    BoardPost(this, msg);
335
+};
336
+
337
+function BoardPostResult(board, xhr) {
338
+    try {
339
+        //alert("Post status="+xhr.status);
340
+        //alert(xhr.responseText);
341
+        if (xhr.status == 200) {
342
+            var res = eval(xhr.responseText);
343
+            // alert(""+res);
344
+            if (res['SetCookie'] && !(board.cookie)) {
345
+               // board.tmpcookie = true;
346
+               board.cookie = res['SetCookie'];
347
+            }
348
+            if (res['XPostId']) {
349
+                GlobalXPosts.push(res['XPostId']+'@'+board.name);
350
+            }
351
+        }
352
+    }
353
+    catch(err) {
354
+        board.setState(STATE_HTTP_ERROR);
355
+    }
356
+    board.refresh();
357
+}
358
+Board.prototype.postResult = function (xhr) { BoardPostResult(this, xhr); };
359
+
360
+/****************************************************
361
+ * L'onglet matérialisant une tribune active
362
+ ****************************************************/
363
+
364
+function BoardTab(board) {
365
+    this.board = board;
366
+    this.visible = false;
367
+}
368
+
369
+function BoardTabAddTab (boardTab) {
370
+    var board = boardTab.board;
371
+    if (boardTab.tab()) {
372
+        return;
373
+    }
374
+    // Ajout de l'onglet
375
+    board.loadConfig();
376
+    board.updateCSS();
377
+    var tab = document.createElement("div");
378
+    tab.setAttribute("id", "tab-"+board.name);
379
+    tab.className = "tab tab-"+board.name;
380
+    addEvent(tab, "click", function (e) { clickBoard(board.name, e); }, false);
381
+    var icon = document.createElement("img");
382
+    icon.src = "img/stop.png";
383
+    tab.appendChild(icon);
384
+    var name = document.createElement("span");
385
+    name.className = "tab-name";
386
+    name.innerHTML = board.name;
387
+    tab.appendChild(name);
388
+    var text = document.createElement("span");
389
+    text.setAttribute("id", "tab-notif-"+board.name);
390
+    addClass(text, "tab-notif");
391
+    tab.appendChild(text);
392
+    document.getElementById("tabs-boards").appendChild(tab);
393
+    boardTab.visible = true;
394
+    board.addView(boardTab);
395
+    board.addView(window);
396
+    // Mise à jour de l'état
397
+    board.setState(STATE_STOP);
398
+    // Ajout de la tribune dans la liste du palmipède
399
+    var palmilist = document.getElementById('palmi-list');
400
+    var opt = document.createElement('option');
401
+    opt.setAttribute("value", board.name);
402
+    opt.innerHTML = board.name;
403
+    palmilist.appendChild(opt);
404
+}
405
+BoardTab.prototype.addTab = function () { BoardTabAddTab(this); };
406
+
407
+BoardTab.prototype.tab = function () {
408
+    return document.getElementById("tab-"+this.board.name);
409
+}
410
+BoardTab.prototype.icon = function () {
411
+    return document.getElementById("tab-"+this.board.name).getElementsByTagName("img")[0];
412
+}
413
+BoardTab.prototype.text = function () {
414
+    return document.getElementById("tab-notif-"+this.board.name); //.getElementsByTagName("span")[0];
415
+}
416
+
417
+function BoardTabNotified(boardTab, notif, arg) {
418
+    switch (notif) {
419
+      case NOTIF_STATE:
420
+        switch (arg) {
421
+          case STATE_LOADED:
422
+            break;
423
+          case STATE_STOP:
424
+            boardTab.icon().src = "img/stop.png";
425
+            break;
426
+          case STATE_IDLE:
427
+            // _log.debug("mais pouet quoi");
428
+            boardTab.icon().src = "img/blank.gif";
429
+            break;
430
+          case STATE_HTTP:
431
+            boardTab.icon().src = "img/refresh.png";
432
+            break;
433
+          case STATE_PARSE:
434
+            boardTab.icon().src = "img/parse.png";
435
+            break;
436
+          case STATE_POST:
437
+            boardTab.icon().src = "img/sendpost.png";
438
+            break;
439
+          case STATE_HTTP_ERROR:
440
+            boardTab.icon().src = "img/error.png";
441
+            break;
442
+          case STATE_PARSE_ERROR:
443
+            // AFR ajout icone erreur parsing
444
+            break;
445
+          case STATE_POST_ERROR:
446
+            // AFR ajout icone post fail
447
+            break;
448
+        }
449
+        break;
450
+      case NOTIF_NEW_POST:
451
+        var notifzone = boardTab.text();
452
+        var char1 = notifzone.innerHTML.substr(0,1);
453
+        if (char1 != "#" && char1 != "@" && char1 != "&") {
454
+            if (!boardTab.visible) {
455
+                var notifzone = boardTab.text();
456
+                notifzone.innerHTML = "*";
457
+                notifzone.setAttribute("title", "Il y a des nouveaux posts");
458
+            }
459
+        }
460
+        break;
461
+      case NOTIF_ANSWER:
462
+        if (!boardTab.visible) {
463
+            var notifzone = boardTab.text();
464
+            notifzone.innerHTML = "#";
465
+            notifzone.setAttribute("title", "Nouvelle réponse à "+getCtxtClock(arg));
466
+        }
467
+        break;
468
+      case NOTIF_BIGORNO_ALL:
469
+        if (!boardTab.visible) {
470
+            var notifzone = boardTab.text();
471
+            notifzone.innerHTML = "&lt;";
472
+            notifzone.setAttribute("title", "On appelle en "+getCtxtClock(arg));
473
+        }
474
+        break;
475
+      case NOTIF_BIGORNO:
476
+        if (!boardTab.visible) {
477
+            var notifzone = boardTab.text();
478
+            notifzone.innerHTML = "@&lt;";
479
+            notifzone.setAttribute("title", "On appelle en "+getCtxtClock(arg));
480
+        }
481
+        break;
482
+    }
483
+}
484
+BoardTab.prototype.notified = function (notif, arg) { BoardTabNotified(this, notif, arg); };
485
+
486
+function BoardTabDisplay(boardTab) {
487
+    var css = getStyleClass("pinni-"+boardTab.board.name);
488
+    if (css) {
489
+        css.style.display = 'block';
490
+        removeClass(boardTab.tab(), "tab-hidden");
491
+    }
492
+    boardTab.visible = true;
493
+    boardTab.text().innerHTML = '';
494
+}
495
+BoardTab.prototype.display = function () { BoardTabDisplay(this); };
496
+
497
+function BoardTabHide(boardTab) {
498
+    var css = getStyleClass("pinni-"+boardTab.board.name);
499
+    if (css) {
500
+        css.style.display = 'none';
501
+        addClass(boardTab.tab(), "tab-hidden");
502
+    }
503
+    boardTab.visible = false;
504
+}
505
+BoardTab.prototype.hide = function () { BoardTabHide(this); };
506
+
507
+function BoardTabToggle(boardTab) {
508
+    boardTab.visible ? boardTab.hide() : boardTab.display();
509
+}
510
+BoardTab.prototype.toggle = function () { BoardTabToggle(this); };
511
+
512
+function BoardTabRemoveTab(boardTab) {
513
+    if (boardTab.tab()) {
514
+        // on retire le tab des vues de la board
515
+        boardTab.board.removeView(boardTab);
516
+        boardTab.board.removeView(window);
517
+        document.getElementById("tabs-boards").removeChild(boardTab.tab());
518
+        if (is_ie || no_xpath) {
519
+            var posts = IE_selectNodes(["pinni-"+boardTab.board.name]);
520
+        }
521
+        else {
522
+            var posts = evalexp("//div[contains(@class,'pinni-"+boardTab.board.name+"')]");
523
+        }
524
+        for (var i=getLength(posts); i--;) {
525
+            GlobalPinni.removeChild(getItem(posts, i));
526
+        }
527
+        // On retire la tribune de la liste du palmipède
528
+        var palmilist = document.getElementById('palmi-list');
529
+        if (palmilist.childNodes) {
530
+            for (i=palmilist.childNodes.length; i--;) {
531
+                var child = palmilist.childNodes[i];
532
+                if (child.value == boardTab.board.name) {
533
+                    palmilist.removeChild(child);
534
+                    break;
535
+                }
536
+            }
537
+        }
538
+        // mise à jour de l'état
539
+        boardTab.board.setState(STATE_LOADED);
540
+        boardTab.board.lastPost = "0";
541
+    }
542
+}
543
+BoardTab.prototype.removeTab = function () { return BoardTabRemoveTab(this); };
544
+
545
+
546
+// Affichage du panneau de config
547
+function BoardConfigPanel(board) {
548
+    var panel = document.createElement("div");
549
+    panel.setAttribute('id', "config-panel-"+board.name);
550
+    panel.className = 'config-panel'; // setAttribute('class', "config-panel");
551
+    var head = document.createElement('div');
552
+    head.className = 'panel-header'; // setAttribute('class', "panel-header");
553
+    head.innerHTML = 'Paramètres pour la tribune '+board.name;
554
+    head.innerHTML += ' <img src="img/closeok.png" title="Enregistrer les changements et fermer" onclick="saveBoardConfig('+"'"+board.name+"'"+')" />';
555
+    head.innerHTML += ' <img src="img/cancel.png" title="Annuler les changements et fermer" onclick="cancelBoardConfig('+"'"+board.name+"'"+')" />';
556
+    panel.appendChild(head);
557
+    var subpanelw = document.createElement('table');
558
+    subpanelw.style.width = "100%";
559
+    var subpanel = document.createElement('tbody');
560
+    subpanelw.appendChild(subpanel);
561
+    subpanel.className = 'subpanel'; // setAttribute('class', "subpanel");
562
+    subpanel.appendChild(TextBox('config-color', "Couleur", board.color, 10));
563
+    subpanel.appendChild(TextBox('config-alias', "Alias", board.alias, -1));
564
+    subpanel.appendChild(TextBox('config-delay', "Fréquence", board.delay/1000, 3));
565
+    subpanel.appendChild(TextBox('config-login', "Login", board.login, -1));
566
+    subpanel.appendChild(TextBox('config-ua', "User-agent", board.ua, -1));
567
+    subpanel.appendChild(TextBox('config-cookie', "Cookie", board.cookie, -1));
568
+    if (board.perso) {
569
+        subpanel.appendChild(TextBox('config-getUrl', "URL du backend", board.getUrl, -1));
570
+        subpanel.appendChild(TextBox('config-postUrl', "URL de post", board.postUrl, -1));
571
+        subpanel.appendChild(TextBox('config-postData', "Données de post", board.postData, -1));
572
+        subpanel.appendChild(SelectBox('config-slip', "Type de slip", [SLIP_TAGS_RAW, SLIP_TAGS_ENCODED], board.slip, 10));
573
+    }
574
+    else {
575
+        subpanel.appendChild(InfoBox("URL du backend", '<a href="'+board.getUrl+'">'+board.getUrl+'</a>'));
576
+        subpanel.appendChild(InfoBox("URL de post", board.postUrl));
577
+        subpanel.appendChild(InfoBox("Données de post", board.postData));
578
+        subpanel.appendChild(InfoBox("Type de slip", board.slip));
579
+    }
580
+    panel.appendChild(subpanelw);
581
+    return panel;
582
+}
583
+Board.prototype.configPanel = function() { return BoardConfigPanel(this); };
0 584
new file mode 100644
... ...
@@ -0,0 +1,139 @@
1
+/************************************************************
2
+ * OnlineCoinCoin, by Chrisix (chrisix@gmail.com)
3
+ * Définition des tribunes préconfigurées
4
+ ************************************************************/
5
+
6
+var dlfp = new Board('dlfp', false);
7
+dlfp.getUrl = 'http://linuxfr.org/board/index.xml';
8
+dlfp.postUrl = 'http://linuxfr.org/board';
9
+dlfp.postData = "board[message]=%m";
10
+dlfp.alias = "linuxfr,beyrouth,passite,dapassite";
11
+dlfp.cookie = 'linuxfr.org_session=';
12
+GlobalBoards['dlfp'] = dlfp;
13
+
14
+var batavie = new Board('batavie', false);
15
+batavie.getUrl = 'http://batavie.leguyader.eu/remote.xml';
16
+batavie.postUrl = 'http://batavie.leguyader.eu/index.php/add';
17
+batavie.color = '#ffccaa';
18
+batavie.alias = "llg";
19
+batavie.slip = SLIP_TAGS_RAW;
20
+GlobalBoards['batavie'] = batavie;
21
+
22
+var euro = new Board('euromussels', false);
23
+euro.getUrl = 'http://faab.euromussels.eu/data/backend.xml';
24
+euro.postUrl = 'http://faab.euromussels.eu/add.php';
25
+euro.color = '#d0d0ff';
26
+euro.alias = "euro,euroxers,eurofaab";
27
+euro.slip = SLIP_TAGS_RAW;
28
+GlobalBoards['euromussels'] = euro;
29
+
30
+// var oldeuro = new Board('oldeuro', false);
31
+// oldeuro.getUrl = 'http://euromussels.eu/?q=tribune.xml';
32
+// oldeuro.postUrl = 'http://euromussels.eu/?q=tribune/post';
33
+// oldeuro.color = '#e02fa0';
34
+// GlobalBoards['oldeuro'] = oldeuro;
35
+
36
+var see = new Board('see', false);
37
+see.getUrl = 'http://tout.essaye.sauf.ca/tribune.xml';
38
+see.postUrl = 'http://tout.essaye.sauf.ca/tribune/post';
39
+see.color = '#ffd0d0';
40
+see.slip = SLIP_TAGS_RAW;
41
+see.alias = "schee,seeschloss";
42
+GlobalBoards['see'] = see;
43
+
44
+var moules = new Board('moules', false);
45
+moules.getUrl = 'http://moules.org/board/backend/xml';
46
+moules.postUrl = 'http://moules.org/board/add.php';
47
+moules.color = '#ffe3c9';
48
+moules.slip = SLIP_TAGS_RAW;
49
+GlobalBoards['moules'] = moules;
50
+
51
+var bouchot = new Board('bouchot', false);
52
+bouchot.getUrl = 'http://bouchot.org/tribune/remote?last=%i';
53
+bouchot.postUrl = 'http://bouchot.org/tribune/post_coincoin';
54
+bouchot.postData = "missive=%m";
55
+bouchot.color = '#e9e9e9';
56
+GlobalBoards['bouchot'] = bouchot;
57
+
58
+var finss = new Board('finss', false);
59
+finss.getUrl = 'http://finss.fr/drupal/node/95/xml';
60
+finss.postUrl = 'http://finss.fr/drupal/node/95/post';
61
+finss.color = '#d0ffd0';
62
+finss.slip = SLIP_TAGS_RAW;
63
+GlobalBoards['finss'] = finss;
64
+
65
+var shoop = new Board('shoop', false);
66
+shoop.getUrl = 'http://sveetch.net/tribune/remote/xml/'; // ?last=%i inopérant pour le moment
67
+shoop.postUrl = 'http://sveetch.net/tribune/post/xml/';
68
+shoop.postData = "content=%m";
69
+shoop.alias = "sveetch,dax";
70
+shoop.color = '#EDEDDB';
71
+shoop.slip = SLIP_TAGS_RAW;
72
+GlobalBoards['shoop'] = shoop;
73
+
74
+var devnewton = new Board('devnewton', false);
75
+devnewton.getUrl = 'http://b3.bci.im/legacy/xml';
76
+devnewton.postUrl = 'http://b3.bci.im/legacy/post';
77
+devnewton.color = '#F5D6CC';
78
+GlobalBoards['devnewton'] = devnewton;
79
+
80
+var tif = new Board('tifauv', false);
81
+tif.getUrl = 'http://tribune.tifauv.homeip.net/tribune/remote?last=%i';
82
+tif.postUrl = 'http://tribune.tifauv.homeip.net/tribune/post_coincoin';
83
+tif.postData = "missive=%m";
84
+tif.alias = "tif";
85
+tif.color = '#a9f9b9';
86
+GlobalBoards['tifauv'] = tif;
87
+
88
+var olo = new Board('olo', false);
89
+olo.getUrl = 'http://board.olivierl.org/remote.xml';
90
+olo.postUrl = 'http://board.olivierl.org/add.php';
91
+olo.color = '#80dafc';
92
+olo.alias = "olivierl,breizh";
93
+olo.slip = SLIP_TAGS_RAW;
94
+GlobalBoards['olo'] = olo;
95
+
96
+var ygllo = new Board('ygllo', false);
97
+ygllo.getUrl = 'http://ygllo.com/?q=tribune.xml';
98
+ygllo.postUrl = 'http://ygllo.com/?q=tribune/post';
99
+ygllo.color = '#eee887';
100
+ygllo.alias = "yg,llo,fdg";
101
+GlobalBoards['ygllo'] = ygllo;
102
+
103
+var kad = new Board('kadreg', false);
104
+kad.getUrl = 'http://kadreg.org/board/backend.php';
105
+kad.postUrl = 'http://kadreg.org/board/add.php';
106
+kad.color = '#dae6e6';
107
+kad.alias = "kad,rincevent";
108
+kad.slip = SLIP_TAGS_RAW;
109
+GlobalBoards['kadreg'] = kad;
110
+
111
+var dae = new Board('darkside', false);
112
+dae.getUrl = 'http://quadaemon.free.fr/remote.xml';
113
+dae.postUrl = 'http://quadaemon.free.fr/add.php';
114
+dae.color = '#daedae';
115
+dae.alias = "dae,daemon";
116
+dae.slip = SLIP_TAGS_RAW; // Protection temporaire
117
+GlobalBoards['darkside'] = dae;
118
+
119
+var axel = new Board('hadoken', false);
120
+axel.getUrl = 'http://hadoken.free.fr/board/remote.php';
121
+axel.postUrl = 'http://hadoken.free.fr/board/post.php';
122
+axel.color = '#77AADD';
123
+axel.alias = "axel,waf";
124
+GlobalBoards['hadoken'] = axel;
125
+
126
+var lo = new Board('comptoir', false);
127
+lo.getUrl = 'http://lordoric.free.fr/daBoard/remote.xml';
128
+lo.postUrl = 'http://lordoric.free.fr/daBoard/add.php';
129
+lo.color = '#dedede';
130
+lo.alias = "lo,lordoric";
131
+lo.slip = SLIP_TAGS_RAW; // Protection temporaire
132
+GlobalBoards['comptoir'] = lo;
133
+
134
+var gabu = new Board('gabuzomeu', false);
135
+gabu.getUrl = 'http://gabuzomeu.fr/tribune.xml';
136
+gabu.postUrl = 'http://gabuzomeu.fr/tribune/post';
137
+gabu.color = '#aaffbb';
138
+gabu.slip = SLIP_TAGS_RAW;
139
+GlobalBoards['gabuzomeu'] = gabu;
0 140
new file mode 100644
... ...
@@ -0,0 +1,589 @@
1
+/************************************************************
2
+ * OnlineCoinCoin, by Chrisix (chrisix@gmail.com)
3
+ * Fonctions de gestion des options de configuration utilisateur
4
+ ************************************************************/
5
+
6
+var TYPE_INT = "int";
7
+var TYPE_STR = "string";
8
+var TYPE_BOOL = "bool";
9
+var TYPE_CHOICE = "choice";
10
+var TYPE_MULTI_CHOICE = "multichoice";
11
+var TYPE_SOUND = "sound";
12
+
13
+/*
14
+function Option(descr, value, type) {
15
+    this.descr = descr;
16
+    this.value = value;
17
+    this.type = type;
18
+} */
19
+
20
+var settings = {
21
+    options: {
22
+        'active_boards': {
23
+            descr: "Tribunes actives",
24
+            type: TYPE_MULTI_CHOICE
25
+        },
26
+        'pinni_size': {
27
+            descr: "Nombre max de posts",
28
+            type: TYPE_INT
29
+        },
30
+        'pinni_keep': {
31
+            descr: "Ne jamais effacer mes posts et leurs réponses",
32
+            type: TYPE_BOOL
33
+        },
34
+        'default_ua': {
35
+            descr: "User-agent",
36
+            type: TYPE_STR
37
+        },
38
+        'totoz_server': {
39
+            descr: "Serveur de totoz",
40
+            type: TYPE_STR
41
+        },
42
+        'totoz_mode': {
43
+            descr: "Affichage des totoz",
44
+            type: TYPE_CHOICE
45
+        },
46
+        'default_login': {
47
+            descr: "Login par défaut",
48
+            type: TYPE_STR
49
+        },
50
+        'window_title': {
51
+            descr: "Titre de la fenêtre",
52
+            type: TYPE_STR
53
+        },
54
+        'favicon': {
55
+            descr: "Icone de la fenêtre",
56
+            type: TYPE_STR
57
+        },
58
+        'boss_mode': {
59
+            descr: "Boss-mode",
60
+            type: TYPE_CHOICE
61
+        },
62
+        'style': {
63
+            descr: "Style",
64
+            type: TYPE_CHOICE
65
+        },
66
+        'plonk': {
67
+            descr: "Plonk-list",
68
+            type: TYPE_STR
69
+        },
70
+        'balltrap': {
71
+            descr: "Balltrap",
72
+            type: TYPE_BOOL
73
+        },
74
+        'max_ducks': {
75
+            descr: "Nombre max de canards",
76
+            type: TYPE_INT
77
+        },
78
+        'balltrap_mode': {
79
+            descr: "Mode de chasse",
80
+            type: TYPE_CHOICE
81
+        },
82
+        'balltrap_silent': {
83
+            descr: "Chasse silencieuse",
84
+            type: TYPE_BOOL
85
+        },
86
+        'sound_enabled': {
87
+            descr: "Sons activés",
88
+            type: TYPE_BOOL
89
+        },
90
+        'sound_volume': {
91
+            descr: "Volume (1-100)",
92
+            type: TYPE_INT
93
+        },
94
+        'sound_new': {
95
+            descr: "Arrivée de nouveaux posts",
96
+            type: TYPE_SOUND
97
+        },
98
+        'sound_reply': {
99
+            descr: "Réponse à un de mes posts",
100
+            type: TYPE_SOUND
101
+        },
102
+        'sound_bigorno': {
103
+            descr: "Bigornophone",
104
+            type: TYPE_SOUND
105
+        },
106
+        'sound_zoo': {
107
+            descr: "Zoodvinssen activé",
108
+            type: TYPE_BOOL
109
+        }
110
+    },
111
+    setDefault: function () {
112
+        for (var opt in this.options) {
113
+            this.options[opt].value = eval('DEFAULT_'+opt.toUpperCase());
114
+        }
115
+    },
116
+    set: function(name, val) {
117
+        this.options[name].value = val;
118
+    },
119
+    value: function (name) {
120
+        return this.options[name].value;
121
+    },
122
+    save: function () {
123
+        var tab = new Array();
124
+        // alert("save");
125
+        for (var opt in this.options) {
126
+            var val = this.value(opt);
127
+            if (this.options[opt].type == TYPE_MULTI_CHOICE) {
128
+                val = val.join("|");
129
+            }
130
+            tab.push(opt+"="+val);
131
+        }
132
+        setCookie("settings", tab.join("\n"), 10000);
133
+    },
134
+    load: function () {
135
+        var settings = getCookie("settings");
136
+        // alert("load: "+settings);
137
+        if (settings) {
138
+            var pairs = settings.split("\n");
139
+            // alert("pairs.length="+pairs.length+" ; pairs="+pairs);
140
+            for (var i=pairs.length; i--;) {
141
+                var opt_val = pairs[i];
142
+                if (!opt_val) continue;
143
+                var eqpos = opt_val.indexOf('=');
144
+                var name = opt_val.substr(0, eqpos);
145
+                var opt = this.options[name];
146
+                var val = opt_val.substr(eqpos+1, opt_val.length);
147
+                if (name == 'default_ua') { // MAJ du numéro de version dans l'UA
148
+                    val = val.replace(/((?:ol|online)(?:cc|c²|coincoin))\/[0-9]+\.[0-9]+\.[0-9]+/i, '$1/'+VERSION);
149
+                }
150
+                // alert("name="+name+" ; val="+val);
151
+                switch (opt.type) {
152
+                  case TYPE_INT:
153
+                  case TYPE_BOOL:
154
+                    val = eval(val);
155
+                    break;
156
+                  case TYPE_MULTI_CHOICE:
157
+                    val = (val) ? val.split("|") : [];
158
+                    break;
159
+                }
160
+                opt.value = val;
161
+            }
162
+        }
163
+    }
164
+}
165
+
166
+var GlobalBufStyle = '';
167
+
168
+// Bascule affichage/fermeture du panneau de config
169
+function toggleConfig() {
170
+    if (document.getElementById("config").style.display != 'none') {
171
+        closeConfig();
172
+    }
173
+    else {
174
+        dispConfig();
175
+    }
176
+}
177
+
178
+// affichage du panneau de config
179
+function dispConfig() {
180
+    var configPanel = document.getElementById("config");
181
+    createConfigPanel(configPanel);
182
+    configPanel.style.display = 'block';
183
+}
184
+
185
+// fermeture du panneau de config
186
+function closeConfig() {
187
+    var configPanel = document.getElementById("config");
188
+    configPanel.style.display = 'none';
189
+    // removage des vues
190
+    for (var name in GlobalBoards) {
191
+        var board = GlobalBoards[name];
192
+        if (board.state != STATE_LOADED) {
193
+            board.removeView(document.getElementById('config-'+board.name));
194
+        }
195
+    }
196
+}
197
+
198
+function saveConfig() {
199
+    for (var opt in settings.options) {
200
+        var cur_opt = settings.options[opt];
201
+        var opt_elem = document.getElementById('config-'+opt);
202
+        switch (cur_opt.type) {
203
+          case TYPE_INT:
204
+            cur_opt.value = eval(opt_elem.value);
205
+            break;
206
+          case TYPE_BOOL:
207
+            cur_opt.value = opt_elem.checked;
208
+            break;
209
+          case TYPE_CHOICE:
210
+            var tmpval = opt_elem.options[opt_elem.selectedIndex].value;
211
+            if (tmpval) {  // Pour IE6 qui ne sait pas trouver les valeurs des combobox
212
+              cur_opt.value = tmpval; 
213
+            }
214
+            break;
215
+          case TYPE_STR:
216
+          case TYPE_SOUND:
217
+            cur_opt.value = opt_elem.value;
218
+            if (opt == 'window_title') {
219
+                document.title = cur_opt.value;
220
+            }
221
+            else if (opt == 'favicon') {
222
+                favicon.change(cur_opt.value);
223
+            }
224
+            break;
225
+          case TYPE_MULTI_CHOICE:
226
+            if (opt == 'active_boards') {
227
+                var res = new Array();
228
+                for (var name in GlobalBoards) {
229
+                    if (GlobalBoards[name].state != STATE_LOADED) {
230
+                        res.push(name);
231
+                    }
232
+                }
233
+                cur_opt.value = res;
234
+            }
235
+            break;
236
+        }
237
+    }
238
+    settings.save();
239
+    if (GlobalBufStyle != settings.value('style')) {
240
+        applyGlobalCSS();
241
+        GlobalBufStyle = settings.value('style');
242
+    }
243
+    closeConfig();
244
+}
245
+
246
+
247
+// Ajoute une ligne dans le tableau de configuration des tribunes actives
248
+function addConfigLine(board, subpanel) {
249
+    tr = document.createElement('tr');
250
+    tr.setAttribute('id', 'config-'+board.name);
251
+    tr.className = 'subpanel'; // setAttribute('class', "subpanel");
252
+    // Cellule nom de la tribune
253
+    td = document.createElement('td');
254
+    td.className = 'panel-board tab-'+board.name; // setAttribute('class', 'panel-board');
255
+    td.innerHTML = board.name;
256
+    // td.style.background = board.color;
257
+    tr.appendChild(td);
258
+    // Cellule bouton start
259
+    td = document.createElement('td');
260
+    icon = (board.state == STATE_STOP) ? "start.png" : "greystart.png";
261
+    td.innerHTML = '<img id="but-start-'+board.name+'" src="img/'+icon+'" alt="[Démarrer]" title="Démarrer" onclick="BoardStart(GlobalBoards['+"'"+board.name+"'"+'])" />';
262
+    tr.appendChild(td);
263
+    // Cellule bouton stop
264
+    td = document.createElement('td');
265
+    icon = (board.state == STATE_STOP) ? "greystop.png" : "stop.png";
266
+    td.innerHTML = '<img id="but-stop-'+board.name+'" src="img/'+icon+'" alt="[Arrêter]" title="Arrêter" onclick="BoardStop(GlobalBoards['+"'"+board.name+"'"+'])" />';
267
+    tr.appendChild(td);
268
+    // Cellule bouton config
269
+    td = document.createElement('td');
270
+    td.innerHTML = '<img id="but-config-'+board.name+'" src="img/bconfig.png" alt="[Paramètres]" title="Paramètres" onclick="configBoard('+"'"+board.name+"'"+')" />';
271
+    tr.appendChild(td);
272
+    // Cellule bouton remove
273
+    td = document.createElement('td');
274
+    td.innerHTML = '<img id="but-remove-'+board.name+'" src="img/remove.png" alt="[Supprimer]" title="Supprimer" onclick="configRemove('+"'"+board.name+"'"+')" />';
275
+    tr.appendChild(td);
276
+    // Cellule nombre de posts
277
+    td = document.createElement('td');
278
+    td.setAttribute('id', "nbposts-"+board.name);
279
+    td.className = 'cinfo';
280
+    td.innerHTML = board.nbPosts + " posts";
281
+    tr.appendChild(td);
282
+    // Cellule état
283
+    td = document.createElement('td');
284
+    td.setAttribute('id', "cstate-"+board.name);
285
+    td.className = 'cstate';
286
+    td.innerHTML = "["+board.state+"]";
287
+    tr.appendChild(td);
288
+    // Ajout de la ligne
289
+    subpanel.appendChild(tr);
290
+    tr.notified = function (notif, state) {
291
+        var name = this.getAttribute('id').substr(7);
292
+        var board = GlobalBoards[name];
293
+        switch (notif) {
294
+          case NOTIF_STATE:
295
+            document.getElementById("cstate-"+name).innerHTML = "["+board.state+"]";
296
+            switch (state) {
297
+              case STATE_LOADED:
298
+                // self destruction
299
+                break;
300
+              case STATE_STOP:
301
+                document.getElementById("but-start-"+name).src = "img/start.png";
302
+                document.getElementById("but-stop-"+name).src = "img/greystop.png";
303
+                break;
304
+              default:
305
+                document.getElementById("but-start-"+name).src = "img/greystart.png";
306
+                document.getElementById("but-stop-"+name).src = "img/stop.png";
307
+                break;
308
+            }
309
+            break;
310
+          case NOTIF_NEW_POST:
311
+            document.getElementById("nbposts-"+name).innerHTML = board.nbPosts + " posts";
312
+            break;
313
+        }
314
+    };
315
+    board.addView(tr);
316
+}
317
+
318
+var config_sections = [
319
+    { name: "Général", descr: "Paramètres généraux", img: "application32.png" },
320
+    { name: "Tribunes", descr: "Configuration des tribunes", img: "comments32.png" },
321
+    { name: "Sons", descr: "Notifications sonores", img: "sound32.png" },
322
+    { name: "Load/Store", descr: "chargement/déchargement des paramètres", img: "ls32.png" }
323
+];
324
+
325
+// Creation du panneau de config
326
+// Onglets du panneau de config
327
+function createConfigTabs(panel) {
328
+    var head1 = document.createElement('div');
329
+    head1.className = 'panel-header'; // setAttribute('class', "panel-header");
330
+    head1.innerHTML = 'OnlineCoinCoin '+VERSION+' - Configuration';
331
+    head1.innerHTML += ' <img src="img/closeok.png" alt="[Ok]" title="Enregistrer les changements et fermer" onclick="saveConfig()" />';
332
+    head1.innerHTML += ' <img src="img/cancel.png" alt="[Annuler]" title="Annuler les changements et fermer" onclick="closeConfig()" />';
333
+    panel.appendChild(head1);
334
+    var tabbar = document.createElement('div');
335
+    tabbar.className = "panel-tabs";
336
+    panel.appendChild(tabbar);
337
+    for (var i=0; i<config_sections.length; i++) {
338
+        var subpanel = document.createElement('div');
339
+        subpanel.className = "subpanel";
340
+        subpanel.setAttribute('id', "config-tab-"+i);
341
+        panel.appendChild(subpanel);
342
+        var tab = document.createElement('div');
343
+        tab.className = "panel-tab";
344
+        tab.setAttribute('id', "config-tab-but-"+i);
345
+        tab.innerHTML = '<img src="img/'+config_sections[i].img+'" alt="['+config_sections[i].name+']" title="'+config_sections[i].descr+'" /><br />'+config_sections[i].name;
346
+        /* var coin = function() {alert(i);setConfigTab(i)}; */
347
+        addEvent(tab, "click", coin(i), false);
348
+        tabbar.appendChild(tab);
349
+    }
350
+}
351
+function coin(t) {
352
+  return function(){setConfigTab(t)};
353
+}
354
+function setConfigTab(t) {
355
+    for (var i=0; i<config_sections.length; i++) {
356
+        if (i==t) {
357
+            document.getElementById('config-tab-'+i).style.display = 'block';
358
+            addClass(document.getElementById('config-tab-but-'+i), 'tab-active');
359
+        }
360
+        else {
361
+            document.getElementById('config-tab-'+i).style.display = 'none';
362
+            removeClass(document.getElementById('config-tab-but-'+i), 'tab-active');
363
+        }
364
+    }
365
+}
366
+
367
+function addOptionLine(opt, subpanel) {
368
+    var cur_opt = settings.options[opt];
369
+    var size = -1;
370
+    switch (cur_opt.type) {
371
+      case TYPE_INT:
372
+        size = 3;
373
+      case TYPE_STR:
374
+        subpanel.appendChild(TextBox('config-'+opt, cur_opt.descr, cur_opt.value, size));
375
+        break;
376
+      case TYPE_BOOL:
377
+        subpanel.appendChild(CheckBox('config-'+opt, cur_opt.descr, cur_opt.value));
378
+        break;
379
+      case TYPE_CHOICE:
380
+        var tab = null;
381
+        switch (opt) {
382
+          case 'totoz_mode':
383
+            tab = [TOTOZ_POPUP, TOTOZ_INLINE];
384
+            break;
385
+          case 'boss_mode':
386
+            tab = [BOSSMODE_RANDOM, BOSSMODE_PTRAMO, BOSSMODE_KERVIEL, BOSSMODE_PBPG, BOSSMODE_DECIDEUR]
387
+            break;
388
+          case 'style':
389
+            tab = ['default', 'lefttabs', 'sfw', 'golcc', 'oldolcc'];
390
+            break;
391
+          case 'balltrap_mode':
392
+            tab = [BALLTRAP_ONCLICK, BALLTRAP_AUTO, BALLTRAP_KILL];
393
+            break;
394
+        }
395
+        if (tab) {
396
+            subpanel.appendChild(SelectBox('config-'+opt, cur_opt.descr, tab, cur_opt.value, size));
397
+        }
398
+        break;
399
+      case TYPE_SOUND:
400
+        subpanel.appendChild(SoundBox('config-'+opt, cur_opt.descr, cur_opt.value, size));
401
+        break;
402
+    }
403
+}
404
+
405
+function createConfigPanel(cpanel) {
406
+    cpanel.innerHTML = '';
407
+    GlobalBufStyle = settings.value('style');
408
+    createConfigTabs(cpanel);
409
+    setConfigTab(0);
410
+    
411
+    // Section config générale
412
+    var panel = document.getElementById('config-tab-0');
413
+    var subpanelwrapper = document.createElement('table');
414
+    subpanelwrapper.style.width = "100%";
415
+    var subpanel = document.createElement('tbody');
416
+    subpanelwrapper.appendChild(subpanel);
417
+    subpanel.setAttribute('id', "configZone");
418
+    subpanel.setAttribute('class', "subpanel");
419
+    var opt = null;
420
+    for (opt in settings.options) {
421
+        if (opt.substr(0,5) != 'sound') {
422
+            addOptionLine(opt, subpanel);
423
+        }
424
+    }