Browse code

Initial commit

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