--- /dev/null
+BD/
+ebin/
\ No newline at end of file
Comet = function(page, version) {\r
this.page = page;\r
this.version = version;\r
- \r
+\r
// l'objet JSONHttpRequest représentant la connexion d'attente\r
this.attenteCourante = undefined;\r
- \r
+\r
// le multhreading du pauvre, merci javascript de m'offrire autant de primitives pour la gestion de la concurrence...\r
this.stop = false;\r
};\r
*/\r
Comet.prototype.stopAttenteCourante = function() {\r
this.stop = true;\r
- \r
+\r
if (this.attenteCourante) {\r
this.attenteCourante.abort();\r
}\r
};\r
\r
/**\r
- * Attend un événement lié à la page. Non-bloquant. \r
+ * Attend un événement lié à la page. Non-bloquant.\r
* @funSend une fonction renvoyant les données json à envoyer\r
* @funsReceive est un objet comprenant les fonctions à appeler en fonction du "reply"\r
* les fonctions acceptent un paramètre correspondant au données reçues.\r
*/\r
Comet.prototype.waitEvent = function(funSend, funsReceive) {\r
this.stopAttenteCourante();\r
- \r
+\r
this.stop = false;\r
- \r
+\r
var thisComet = this;\r
- \r
+\r
// on doit conserver l'ordre des valeurs de l'objet JSON (le serveur les veut dans l'ordre définit dans le protocole)\r
// TODO : ya pas mieux ?\r
var dataToSend = {\r
objectEach(poulpe, function(k, v) {\r
dataToSend[k] = v;\r
});\r
- \r
+\r
this.attenteCourante = jQuery.ajax({\r
type: "POST",\r
url: "request",\r
success:\r
function(data) {\r
funsReceive[data.reply](data);\r
- \r
+\r
// rappel de la fonction dans 100 ms\r
setTimeout(function(){ thisComet.waitEvent2(funSend, funsReceive); }, 100);\r
},\r
error:\r
function(XMLHttpRequest, textStatus, errorThrown) {\r
- ;; console.log("Connexion perdue dans Comet.prototype.waitEvent() : \n" + textStatus);\r
+ // console.log("Connexion perdue dans Comet.prototype.waitEvent() : \n" + textStatus);\r
setTimeout(function(){ thisComet.waitEvent2(funSend, funsReceive); }, 1000);\r
}\r
});\r
return;\r
}\r
this.waitEvent(funSend, funsReceive);\r
-};
\ No newline at end of file
+};\r
// Regroupe la partie communication JSON client -> serveur de euphorik.\r
// Voir : http://dev.euphorik.ch/wiki/euk/Protocole\r
\r
-/**
- * Les fonctions debutReq et finReq servent, par exemple, à afficher à l'utilisateur
+/**\r
+ * Les fonctions debutReq et finReq servent, par exemple, à afficher à l'utilisateur\r
* qu'une communication est en cours.\r
- * @param funError un fonction executée lors d'un réponse 'error' de la part du serveur, peut être redéfinit pour une requête.
- * @param funDebutReq fonction appelée au début d'une requête (facultatif)
+ * @param funError un fonction executée lors d'un réponse 'error' de la part du serveur, peut être redéfinit pour une requête.\r
+ * @param funDebutReq fonction appelée au début d'une requête (facultatif)\r
* @param funFinReq fonction appelée à la fin d'une requête (facultatif)\r
*/\r
euphorik.Communication = function(funError, funDebutReq, funFinReq) {\r
- this.funError = funError;
- this.funDebutReq = funDebutReq;
+ this.funError = funError;\r
+ this.funDebutReq = funDebutReq;\r
this.funFinReq = funFinReq;\r
-};
-
-/**
- * Charge un fichier depuis une url et retourne son contenu.
- */
-euphorik.Communication.prototype.load = function(url) {
- if (this.funDebutReq) {
- this.funDebutReq();
- }
- var contenu = "";
- $.ajax({async: false, url: url, success : function(page) { contenu += page; }});
- if (this.funFinReq) {
- this.funFinReq();
- }
- return contenu;
};\r
-
-/**
- * Effectue une requête JSON auprès du serveur.
- * @param action une chaine spécifiant l'action, par exemple "put_message"
- * @param json les données à envoyer associé à l'action, par exemple {"cookie" : "LKJDLAKSJBFLKASN", "nick" : "Paul", "content" : "Bonjour", "answer_to" : [] }
- * @param funOk la fonction exécuté après réception des données du serveur
- * @param funError la fonction exécuté si une erreur arrive (facultatif)
- * @param asynchrone true pour une communication asychrone (facultatif, truepar défaut)
- * @param paramsSupp un objet contenant des paramètres supplémentaire pour la fonction ajax de jQuery (facultatif)
+\r
+/**\r
+ * Charge un fichier depuis une url et retourne son contenu.\r
+ */\r
+euphorik.Communication.prototype.load = function(url) {\r
+ if (this.funDebutReq) {\r
+ this.funDebutReq();\r
+ }\r
+ var contenu = "";\r
+ $.ajax({async: false, url: url, success : function(page) { contenu += page; }});\r
+ if (this.funFinReq) {\r
+ this.funFinReq();\r
+ }\r
+ return contenu;\r
+};\r
+\r
+/**\r
+ * Effectue une requête JSON auprès du serveur.\r
+ * @param action une chaine spécifiant l'action, par exemple "put_message"\r
+ * @param json les données à envoyer associé à l'action, par exemple {"cookie" : "LKJDLAKSJBFLKASN", "nick" : "Paul", "content" : "Bonjour", "answer_to" : [] }\r
+ * @param funOk la fonction exécuté après réception des données du serveur\r
+ * @param funError la fonction exécuté si une erreur arrive (facultatif)\r
+ * @param asynchrone true pour une communication asychrone (facultatif, truepar défaut)\r
+ * @param paramsSupp un objet contenant des paramètres supplémentaire pour la fonction ajax de jQuery (facultatif)\r
*/\r
euphorik.Communication.prototype.requete = function(action, json, funOk, funError, asynchrone, paramsSupp) {\r
var thisCommunication = this;\r
var mess = this.getBase(action);\r
objectEach(json, function(nom, val) {\r
mess[nom] = val;\r
- });
-
- if (this.funDebutReq) {
- this.funDebutReq();
+ });\r
+\r
+ if (this.funDebutReq) {\r
+ this.funDebutReq();\r
}\r
- \r
+\r
paramsAjax = {\r
async: asynchrone,\r
type: "POST",\r
dataType: "json",\r
data: { action : JSON.stringify(mess) },\r
success:\r
- function(data) {
- if (thisCommunication.funFinReq) {
- thisCommunication.funFinReq();
+ function(data) {\r
+ if (thisCommunication.funFinReq) {\r
+ thisCommunication.funFinReq();\r
}\r
if (data.reply === "error") {\r
if (funError) {\r
} else if (funOk) {\r
funOk(data);\r
}\r
- },
- error:
- function(data) {
- if (thisCommunication.funFinReq) {
- thisCommunication.funFinReq();
- }
+ },\r
+ error:\r
+ function(data) {\r
+ if (thisCommunication.funFinReq) {\r
+ thisCommunication.funFinReq();\r
+ }\r
}\r
};\r
- \r
+\r
if (paramsSupp) {\r
objectEach(paramsSupp, function(nom, val) {\r
paramsAjax[nom] = val;\r
});\r
}\r
- \r
+\r
jQuery.ajax(paramsAjax);\r
};\r
\r
return {\r
"header" : { "action" : action, "version" : euphorik.conf.versionProtocole }\r
};\r
-};
\ No newline at end of file
+};\r
tempsAffichageMessageDialogue : 4000, // en ms\r
tempsKick : 15, // en minute\r
tempsBan : 60 * 24 * 3, // en minutes (3 jours)\r
- smiles : { \r
- "smile" : [/:\)/g, /:-\)/g], \r
+ smiles : {\r
+ "smile" : [/:\)/g, /:-\)/g],\r
"bigsmile" : [/:D/g, /:-D/g],\r
"clin" : [/;\)/g, /;-\)/g],\r
"cool" : [/8\)/g, /8-\)/g],\r
first = false;
});
window.location.hash = fragmentsStr;
-};
\ No newline at end of file
+};
keyToClose: 'c', // (string) (c = close) Letter to close the jQuery lightBox interface. Beyond this letter, the letter X and the SCAPE key is used to.\r
keyToPrev: 'p', // (string) (p = previous) Letter to show the previous image\r
keyToNext: 'n', // (string) (n = next) Letter to show the next image.\r
- // Don´t alter these variables in any way\r
+ // Don�t alter these variables in any way\r
imageArray: [],\r
activeImage: 0\r
},settings);\r
settings.imageArray.length = 0;\r
// Unset image active information\r
settings.activeImage = 0;\r
- // We have an image set? Or just an image? Let´s see it.\r
+ // We have an image set? Or just an image? Let�s see it.\r
if ( jQueryMatchedObj.length == 1 ) {\r
settings.imageArray.push(new Array(objClicked.getAttribute('href'),objClicked.getAttribute('title')));\r
} else {\r
- // Add an Array (as many as we have), with href and title atributes, inside the Array that storage the images references \r
+ // Add an Array (as many as we have), with href and title atributes, inside the Array that storage the images references\r
for ( var i = 0; i < jQueryMatchedObj.length; i++ ) {\r
settings.imageArray.push(new Array(jQueryMatchedObj[i].getAttribute('href'),jQueryMatchedObj[i].getAttribute('title')));\r
}\r
*/\r
function _set_interface() {\r
// Apply the HTML markup into body tag\r
- $('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + settings.imageLoading + '"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="' + settings.imageBtnClose + '"></a></div></div></div></div>'); \r
+ $('body').append('<div id="jquery-overlay"></div><div id="jquery-lightbox"><div id="lightbox-container-image-box"><div id="lightbox-container-image"><img id="lightbox-image"><div style="" id="lightbox-nav"><a href="#" id="lightbox-nav-btnPrev"></a><a href="#" id="lightbox-nav-btnNext"></a></div><div id="lightbox-loading"><a href="#" id="lightbox-loading-link"><img src="' + settings.imageLoading + '"></a></div></div></div><div id="lightbox-container-image-data-box"><div id="lightbox-container-image-data"><div id="lightbox-image-details"><span id="lightbox-image-details-caption"></span><span id="lightbox-image-details-currentNumber"></span></div><div id="lightbox-secNav"><a href="#" id="lightbox-secNav-btnClose"><img src="' + settings.imageBtnClose + '"></a></div></div></div></div>');\r
// Get page sizes\r
var arrPageSizes = ___getPageSize();\r
// Style overlay and show it\r
}).show();\r
// Assigning click events in elements to close overlay\r
$('#jquery-overlay,#jquery-lightbox').click(function() {\r
- _finish(); \r
+ _finish();\r
});\r
// Assign the _finish function to lightbox-loading-link and lightbox-secNav-btnClose objects\r
$('#lightbox-loading-link,#lightbox-secNav-btnClose').click(function() {\r
});\r
}\r
/**\r
- * Prepares image exibition; doing a image´s preloader to calculate it´s size\r
+ * Prepares image exibition; doing a image�s preloader to calculate it�s size\r
*\r
*/\r
function _set_image_to_view() { // show the loading\r
/**\r
* Perfomance an effect in the image container resizing it\r
*\r
- * @param integer intImageWidth The image´s width that will be showed\r
- * @param integer intImageHeight The image´s height that will be showed\r
+ * @param integer intImageWidth The image�s width that will be showed\r
+ * @param integer intImageHeight The image�s height that will be showed\r
*/\r
function _resize_container_image_box(intImageWidth,intImageHeight) {\r
// Get current width and height\r
var intCurrentWidth = $('#lightbox-container-image-box').width();\r
var intCurrentHeight = $('#lightbox-container-image-box').height();\r
// Get the width and height of the selected image plus the padding\r
- var intWidth = (intImageWidth + (settings.containerBorderSize * 2)); // Plus the image´s width and the left and right padding value\r
- var intHeight = (intImageHeight + (settings.containerBorderSize * 2)); // Plus the image´s height and the left and right padding value\r
+ var intWidth = (intImageWidth + (settings.containerBorderSize * 2)); // Plus the image�s width and the left and right padding value\r
+ var intHeight = (intImageHeight + (settings.containerBorderSize * 2)); // Plus the image�s height and the left and right padding value\r
// Diferences\r
var intDiffW = intCurrentWidth - intWidth;\r
var intDiffH = intCurrentHeight - intHeight;\r
if ( $.browser.msie ) {\r
___pause(250);\r
} else {\r
- ___pause(100); \r
+ ___pause(100);\r
}\r
- } \r
+ }\r
$('#lightbox-container-image-data-box').css({ width: intImageWidth });\r
$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ height: intImageHeight + (settings.containerBorderSize * 2) });\r
};\r
// If we have a image set, display 'Image X of X'\r
if ( settings.imageArray.length > 1 ) {\r
$('#lightbox-image-details-currentNumber').html(settings.txtImage + ' ' + ( settings.activeImage + 1 ) + ' ' + settings.txtOf + ' ' + settings.imageArray.length).show();\r
- } \r
+ }\r
}\r
/**\r
* Display the button navigations\r
function _set_navigation() {\r
$('#lightbox-nav').show();\r
\r
- // Instead to define this configuration in CSS file, we define here. And it´s need to IE. Just.\r
+ // Instead to define this configuration in CSS file, we define here. And it�s need to IE. Just.\r
$('#lightbox-nav-btnPrev,#lightbox-nav-btnNext').css({ 'background' : 'transparent url(' + settings.imageBlank + ') no-repeat' });\r
- \r
+\r
// Show the prev button, if not the first image in set\r
if ( settings.activeImage != 0 ) {\r
if ( settings.fixedNavigation ) {\r
});\r
}\r
}\r
- \r
+\r
// Show the next button, if not the last image in set\r
if ( settings.activeImage != ( settings.imageArray.length -1 ) ) {\r
if ( settings.fixedNavigation ) {\r
}\r
// Verify the key to show the previous image\r
if ( ( key == settings.keyToPrev ) || ( keycode == 37 ) ) {\r
- // If we´re not showing the first image, call the previous\r
+ // If we�re not showing the first image, call the previous\r
if ( settings.activeImage != 0 ) {\r
settings.activeImage = settings.activeImage - 1;\r
_set_image_to_view();\r
}\r
// Verify the key to show the next image\r
if ( ( key == settings.keyToNext ) || ( keycode == 39 ) ) {\r
- // If we´re not showing the last image, call the next\r
+ // If we�re not showing the last image, call the next\r
if ( settings.activeImage != ( settings.imageArray.length - 1 ) ) {\r
settings.activeImage = settings.activeImage + 1;\r
_set_image_to_view();\r
*/\r
function ___getPageSize() {\r
var xScroll, yScroll;\r
- if (window.innerHeight && window.scrollMaxY) { \r
+ if (window.innerHeight && window.scrollMaxY) {\r
xScroll = window.innerWidth + window.scrollMaxX;\r
yScroll = window.innerHeight + window.scrollMaxY;\r
} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac\r
var windowWidth, windowHeight;\r
if (self.innerHeight) { // all except Explorer\r
if(document.documentElement.clientWidth){\r
- windowWidth = document.documentElement.clientWidth; \r
+ windowWidth = document.documentElement.clientWidth;\r
} else {\r
windowWidth = self.innerWidth;\r
}\r
} else if (document.body) { // other Explorers\r
windowWidth = document.body.clientWidth;\r
windowHeight = document.body.clientHeight;\r
- } \r
+ }\r
// for small pages with total height less then height of the viewport\r
if(yScroll < windowHeight){\r
pageHeight = windowHeight;\r
- } else { \r
+ } else {\r
pageHeight = yScroll;\r
}\r
// for small pages with total width less then width of the viewport\r
- if(xScroll < windowWidth){ \r
- pageWidth = xScroll; \r
+ if(xScroll < windowWidth){\r
+ pageWidth = xScroll;\r
} else {\r
pageWidth = windowWidth;\r
}\r
xScroll = document.documentElement.scrollLeft;\r
} else if (document.body) {// all other Explorers\r
yScroll = document.body.scrollTop;\r
- xScroll = document.body.scrollLeft; \r
+ xScroll = document.body.scrollLeft;\r
}\r
arrayPageScroll = new Array(xScroll,yScroll);\r
return arrayPageScroll;\r
*\r
*/\r
function ___pause(ms) {\r
- var date = new Date(); \r
+ var date = new Date();\r
curDate = null;\r
do { var curDate = new Date(); }\r
while ( curDate - date < ms);\r
// Return the jQuery object for chaining. The unbind method is used to avoid click conflict when the plugin is called more than once\r
return this.unbind('click').click(_initialize);\r
};\r
-})(jQuery); // Call and execute the function immediately passing the jQuery object
\ No newline at end of file
+})(jQuery); // Call and execute the function immediately passing the jQuery object\r
$("#info .fermer").click(function() {\r
$("#info").slideUp(50);\r
});\r
- \r
+\r
$("body").append('<div id="flecheBulle"></div>').append('<div id="messageBulle"><p></p></div>');\r
- \r
+\r
this.formateur = formateur;\r
this.bulleActive = true;\r
};\r
* @param message le message (string)\r
* @param type voir 'messageType'. par défaut messageType.informatif\r
* @param les boutons sous la forme d'un objet ou les clefs sont les labels des boutons\r
- * et les valeurs les fonctions executées lorsqu'un bouton est activé.
- * Lorsqu'un bouton est activé le message se ferme. \r
- * @param formate faut-il formaté le message ? true par défaut
+ * et les valeurs les fonctions executées lorsqu'un bouton est activé.\r
+ * Lorsqu'un bouton est activé le message se ferme.\r
+ * @param formate faut-il formaté le message ? true par défaut\r
* @param temps le temps d'affichage du message en seconde, -1 pour une durée infinie\r
*/\r
euphorik.Util.prototype.messageDialogue = function(message, type, boutons, formate, temps) {\r
if (this.timeoutMessageDialogue) {\r
clearTimeout(this.timeoutMessageDialogue);\r
}\r
- \r
+\r
var fermer = function() { $("#info").slideUp(100); };\r
fermer();\r
\r
$("#info .message").html(!thisUtil.formateur || !formate ? message : thisUtil.formateur.traitementComplet(message));\r
- \r
+\r
switch(type) {\r
case euphorik.Util.messageType.informatif : $("#info #icone").attr("class", "information"); break;\r
case euphorik.Util.messageType.question : $("#info #icone").attr("class", "interrogation"); break;\r
case euphorik.Util.messageType.erreur : $("#info #icone").attr("class", "exclamation"); break;\r
}\r
- \r
+\r
$("#info .boutons").html("");\r
objectEach(boutons, function(nom, bouton) {\r
$("#info .boutons").append("<div>" + nom + "</div>").find("div:last").click(bouton).click(fermer);\r
});\r
- \r
- $("#info").slideDown(200);
+\r
+ $("#info").slideDown(200);\r
if (temps !== -1) {\r
- this.timeoutMessageDialogue = setTimeout(fermer, temps || euphorik.conf.tempsAffichageMessageDialogue);
+ this.timeoutMessageDialogue = setTimeout(fermer, temps || euphorik.conf.tempsAffichageMessageDialogue);\r
}\r
};\r
\r
var positionCible = cible.offset();\r
var positionBoite = {\r
left : positionX === euphorik.Util.positionTypeX.gauche ? positionCible.left - boite.width() :\r
- (positionX === euphorik.Util.positionTypeX.gaucheRecouvrement ? positionCible.left - boite.width() + cible.width() : \r
+ (positionX === euphorik.Util.positionTypeX.gaucheRecouvrement ? positionCible.left - boite.width() + cible.width() :\r
(positionX === euphorik.Util.positionTypeX.droitelsRecouvrement ? positionCible.left :\r
(positionX === euphorik.Util.positionTypeX.droite ? positionCible.left + cible.width() :\r
positionCible.left + cible.width() / 2 - boite.width() / 2 ))), // centre\r
top : positionY === euphorik.Util.positionTypeY.haut ? positionCible.top - boite.height() :\r
- (positionY === euphorik.Util.positionTypeY.hautRecouvrement ? positionCible.top - boite.height() + cible.height() : \r
+ (positionY === euphorik.Util.positionTypeY.hautRecouvrement ? positionCible.top - boite.height() + cible.height() :\r
(positionY === euphorik.Util.positionTypeY.basRecouvrement ? positionCible.top :\r
(positionY === euphorik.Util.positionTypeY.bas ? positionCible.top + cible.height() :\r
positionCible.top + cible.height() / 2 - boite.height() / 2 ))) // centre\r
};\r
- \r
+\r
// calcul les décalages en x et en y pour éviter que la boite ne sorte de la fenêtre, tient compte de la position des barres de défilement\r
- var marge = 10; \r
+ var marge = 10;\r
positionBoite.left = positionBoite.left < marge + window.pageXOffset ? marge + window.pageXOffset :\r
(boite.width() - $(window).width() + (positionBoite.left - window.pageXOffset) + marge > 0 ? $(window).width() - boite.width() - marge + window.pageXOffset : positionBoite.left);\r
positionBoite.top = positionBoite.top < marge + window.pageYOffset ? marge + window.pageYOffset :\r
(boite.height() - $(window).height() + (positionBoite.top - window.pageYOffset) + marge > 0 ? $(window).height() - boite.height() - marge + window.pageYOffset : positionBoite.top);\r
- \r
+\r
boite.css("top", positionBoite.top).css("left", positionBoite.left).show();\r
};\r
\r
euphorik.Util.positionBulleType = {haut : 0, droite : 1, bas : 2, gauche : 3};\r
-
-/**
- * Affiche ou cache la barre d'attente.
- */
-euphorik.Util.prototype.showWaitBar = function() {
- $("#waitbar").show();
-};
-euphorik.Util.prototype.hideWaitBar = function() {
- $("#waitbar").hide();
-};
+\r
+/**\r
+ * Affiche ou cache la barre d'attente.\r
+ */\r
+euphorik.Util.prototype.showWaitBar = function() {\r
+ $("#waitbar").show();\r
+};\r
+euphorik.Util.prototype.hideWaitBar = function() {\r
+ $("#waitbar").hide();\r
+};\r
\r
/**\r
* Affiche un info bulle lorsque le curseur survole l'élément donné.\r
*/\r
euphorik.Util.prototype.infoBulle = function(message, element, position) {\r
var thisUtil = this;\r
- var cacherBulle = function() { \r
+ var cacherBulle = function() {\r
$("#flecheBulle").hide();\r
$("#messageBulle").hide();\r
};\r
- \r
+\r
position = position || euphorik.Util.positionBulleType.haut;\r
\r
element.hover(\r
var m = $("#messageBulle");\r
var f = $("#flecheBulle");\r
f.removeClass().addClass(position === euphorik.Util.positionBulleType.haut ? "flecheBulleHaut" :\r
- (position === euphorik.Util.positionBulleType.droite ? "flecheBulleDroite" : \r
+ (position === euphorik.Util.positionBulleType.droite ? "flecheBulleDroite" :\r
(position === euphorik.Util.positionBulleType.bas ? "flecheBulleBas" : "flecheBulleGauche" )));\r
- \r
+\r
// remplie le paragraphe de la bulle avec le message\r
$("p", m).html(message);\r
- \r
+\r
// réinitialise la position, évite le cas ou la boite est collé à droite et remplie avec un texte la faisant dépassé\r
// dans ce cas la hauteur n'est pas calculé correctement\r
m.css("top", 0).css("left", 0);\r
- \r
+\r
var positionFleche = {\r
left : position === euphorik.Util.positionBulleType.haut || position === euphorik.Util.positionBulleType.bas ?\r
element.offset().left + element.outerWidth() / 2 - f.width() / 2 :\r
} else if (positionMessage.left < 0) {\r
positionMessage.left = 0;\r
}\r
- \r
+\r
m.css("top", positionMessage.top).css("left", positionMessage.left).show();\r
f.css("top", positionFleche.top).css("left", positionFleche.left).show();\r
},\r
var selectionStart = input.selectionStart;\r
var selectionEnd = input.selectionEnd;\r
input.value = input.value.substring(0, selectionStart) + replaceString + input.value.substring(selectionEnd);\r
- \r
+\r
if (selectionStart != selectionEnd) { // has there been a selection\r
this.setSelectionRange(input, selectionStart, selectionStart + replaceString.length);\r
} else { // set caret\r
if (pos === ch.length) {\r
return "";\r
}\r
- \r
+\r
var c = ch.charCodeAt(pos);\r
return String.fromCharCode(\r
c +\r
-# coding: utf-8\r
+# coding: utf-8
# Répertoire dans lequel se trouve les modules compilés (beam)
rep_ebin = ebin
# Répertoire dans lequel se trouve les fichier hrl (définition de record)
rep_include = include
+rep_include_yaws = /usr/lib/yaws/include
# Paramètres du compilateur
# il est possible de compiler en natif en executant :
# les différents tests on montrés que ca n'augmentait pas les performances
# car très lié à la base de données
# TODO : simplifier et éviter les répetitions
-ifdef NATIVE
- erlc_params = +native -I $(rep_include) -o $(rep_ebin) $<
+ifdef NATIVE
+ erlc_params = +native -I $(rep_include) -I $(rep_include_yaws) -o $(rep_ebin) $<
else
- erlc_params = -I $(rep_include) -o $(rep_ebin) $<
+ erlc_params = -I $(rep_include) -I $(rep_include_yaws) -o $(rep_ebin) $<
endif
# Compilation de toute l'application euphorik
-all: $(rep_ebin)/smtp.beam \\r
+all: $(rep_ebin)/smtp.beam \
$(rep_ebin)/euphorik_bd.beam \
$(rep_ebin)/euphorik_minichat_conversation.beam \
$(rep_ebin)/euphorik_requests.beam \
$(rep_ebin)/euphorik_bd_admin.beam \
$(rep_ebin)/euphorik_common.beam \
$(rep_ebin)/euphorik_test.beam
-\r
-# Module pour l'envoie d'email\r
-$(rep_ebin)/smtp.beam: $(rep_erl)/smtp.erl\r
- erlc $(erlc_params)\r
+
+# Module pour l'envoie d'email
+$(rep_ebin)/smtp.beam: $(rep_erl)/smtp.erl
+ erlc $(erlc_params)
# Module pour la gestion des données persistante la BD
$(rep_ebin)/euphorik_bd.beam: $(rep_erl)/euphorik_bd.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
-
+
# Module pour la mise à jour de la BD
$(rep_ebin)/euphorik_bd_admin.beam: $(rep_erl)/euphorik_bd_admin.erl $(rep_include)/euphorik_bd.hrl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
# Module permettant l'extraction des conversations du minichat
$(rep_ebin)/euphorik_minichat_conversation.beam: $(rep_erl)/euphorik_minichat_conversation.erl $(rep_include)/euphorik_bd.hrl
erlc $(erlc_params)
-
+
# Module traitant les requêtes AJAX du client javascript d'euphorik
$(rep_ebin)/euphorik_requests.beam: $(rep_erl)/euphorik_requests.erl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
-
+
# Module interpretant les messages XML du client
$(rep_ebin)/euphorik_protocole.beam: $(rep_erl)/euphorik_protocole.erl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
-
+
# Module pour la génération du captcha
#$(rep_ebin)/captcha.beam: $(rep_erl)/captcha.erl
# erlc $(erlc_params)
-
+
# Module effectuant periodiquement certaines tâches
$(rep_ebin)/euphorik_daemon.beam: $(rep_erl)/euphorik_daemon.erl $(rep_include)/euphorik_defines.hrl
erlc $(erlc_params)
-
+
# Module avec plein de bordel dedant
$(rep_ebin)/euphorik_common.beam: $(rep_erl)/euphorik_common.erl
erlc $(erlc_params)
-
+
# Module dédié au tests
$(rep_ebin)/euphorik_test.beam: $(rep_erl)/euphorik_test.erl $(rep_include)/euphorik_bd.hrl
erlc $(erlc_params)
%\r
% You should have received a copy of the GNU General Public License\r
% along with Euphorik. If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
% Ce module permet de gérer les données persistantes lié au site d'euphorik.ch.\r
% Il permet d'ajouter des message, de demande les messages sur une page donnée, etc..\r
% Ce module utilise une base mnesia.\r
\r
\r
-module(euphorik_bd).\r
--export([ \r
+-export([\r
% texte :\r
get_texte/1,\r
get_texte/2,\r
- \r
+\r
% users :\r
nouveau_user/2,\r
nouveau_user/4,\r
update_date_derniere_connexion/1,\r
update_ip/2,\r
update_pseudo_user/2,\r
- user_by_cookie/1, \r
- user_by_id/1, \r
+ user_by_cookie/1,\r
+ user_by_id/1,\r
user_by_login/1,\r
user_by_login_password/2,\r
user_by_mess/1,\r
css_from_user_cookie/1,\r
is_ek_master_from_cookie/1,\r
- \r
+\r
% messages :\r
nouveau_message/3,\r
nouveau_message_sys/1,\r
est_une_reponse_a_user/2,\r
a_repondu_a_message/2,\r
possede_message/2,\r
- \r
+\r
% ip :\r
list_ban/0,\r
ban/2,\r
deban/1,\r
est_banni/1,\r
can_register/1,\r
- \r
+\r
% trolls :\r
trolls/0,\r
trolls/1,\r
troll_by_id/1,\r
current_troll/0,\r
elire_troll/0,\r
- \r
+\r
% utiles :\r
- resultat_transaction/1,
+ resultat_transaction/1,\r
get_tuples/3 % must be in a transaction\r
]).\r
-import(qlc, [e/2, q/1, cursor/2]).\r
nouveau_user(Cookie, Profile) ->\r
F = fun() ->\r
Id = nouvel_id(user),\r
- User = #user{id = Id, cookie = Cookie, date_creation = now(), date_derniere_connexion = now(), profile = Profile},\r
+ User = #user{id = Id, cookie = Cookie, date_creation = erlang:timestamp(), date_derniere_connexion = erlang:timestamp(), profile = Profile},\r
mnesia:write(User),\r
User\r
end,\r
resultat_transaction(mnesia:transaction(F)).\r
- \r
- \r
+\r
+\r
% Ajoute un nouveau user et le renvoie\r
nouveau_user(Login, Password, Cookie, Profile) ->\r
F = fun() ->\r
Id = nouvel_id(user),\r
- User = #user{id = Id, cookie = Cookie, login = Login, password = Password, date_creation = now(), date_derniere_connexion = now(), profile = Profile#profile{pseudo = Login}},\r
+ User = #user{id = Id, cookie = Cookie, login = Login, password = Password, date_creation = erlang:timestamp(), date_derniere_connexion = erlang:timestamp(), profile = Profile#profile{pseudo = Login}},\r
mnesia:write(User),\r
User\r
end,\r
resultat_transaction(mnesia:transaction(F)).\r
- \r
+\r
\r
% Définit les données du profile d'une utilisateur.\r
set_profile(Cookie, Login, Password, Profile) ->\r
fun() ->\r
case mnesia:wread({user, User_id}) of\r
[User] ->\r
- mnesia:write(User#user{date_derniere_connexion = now()});\r
+ mnesia:write(User#user{date_derniere_connexion = erlang:timestamp()});\r
_ ->\r
mnesia:abort("update_date_derniere_connexion: User inconnu")\r
end\r
mnesia:abort("update_ip: User inconnu")\r
end\r
end\r
- ). \r
- \r
- \r
+ ).\r
+\r
+\r
% Met à jour le pseudo du user\r
update_pseudo_user(UserId, Pseudo) ->\r
mnesia:transaction(\r
- fun() -> \r
+ fun() ->\r
case mnesia:wread({user, UserId}) of\r
[#user{profile = Profile} = User] when Profile#profile.pseudo =/= Pseudo ->\r
mnesia:write(User#user{profile = Profile#profile { pseudo = Pseudo } });\r
end\r
end\r
).\r
- \r
+\r
\r
% Est-ce qu'un utilisateur existe en fonction de son cookie ?\r
% Renvoie {ok, User} ou erreur\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
user_by_id(ID) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
user_by_login(Login) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
end\r
end\r
)).\r
- \r
+\r
\r
% Renvoie une chaine représentant le cookie ou undefined si pas trouvé.\r
css_from_user_cookie(Cookie) ->\r
- case user_by_cookie(Cookie) of \r
+ case user_by_cookie(Cookie) of\r
{ok, #user{profile = Profile}} ->\r
Profile#profile.css;\r
_ ->\r
undefined\r
end.\r
- \r
- \r
+\r
+\r
is_ek_master_from_cookie(Cookie) ->\r
case user_by_cookie(Cookie) of\r
{ok, #user{ek_master = true}} -> true;\r
_ -> false\r
end.\r
- \r
+\r
\r
user_by_login_password(Login, Password) ->\r
resultat_transaction(mnesia:transaction(\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie {ok, User} où User est un #user possédant le message donné.\r
user_by_mess(Id) ->\r
resultat_transaction(mnesia:transaction(\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Ajoute un message. Repond_A est une liste d'id auquel le message répond\r
% retourne soit l'id du message soit {erreur, <raison>}.\r
nouveau_message(Mess, Auteur_id, Repond_A_ids) ->\r
% regarde si les id 'Repond_A' existent\r
- F = fun() -> \r
+ F = fun() ->\r
Repond_a = lists:foldr(\r
fun(Repond_a_id, Acc) ->\r
- case mnesia:read({minichat, Repond_a_id}) of
+ case mnesia:read({minichat, Repond_a_id}) of\r
[M] -> [M | Acc];\r
- _ -> Acc % le message n'est pas trouvé
+ _ -> Acc % le message n'est pas trouvé\r
end\r
- end,
+ end,\r
[],\r
Repond_A_ids\r
),\r
Racine_id = case Repond_a of\r
[] -> undefined;\r
- [M | _] -> \r
+ [M | _] ->\r
Une_racine = M#minichat.racine_id,\r
% vérification que tout les messages de Repond_a possède la même racine (même conversation)\r
case lists:all(fun(R) -> R#minichat.racine_id =:= Une_racine end, Repond_a) of\r
_ ->\r
{erreur, "Les messages ne font pas partie de la même conversation"}\r
end\r
- end,
- if length(Repond_a) =/= length(Repond_A_ids) ->
- {erreur, "Un ou plusieurs messages introuvable"};
+ end,\r
+ if length(Repond_a) =/= length(Repond_A_ids) ->\r
+ {erreur, "Un ou plusieurs messages introuvable"};\r
true ->\r
case Racine_id of\r
{erreur, E} -> {erreur, E};\r
case mnesia:wread({user, Auteur_id}) of\r
[#user{profile = Profile} = Auteur] ->\r
% comparaison entre la date du dernier poste et maintenant (gestion du flood)\r
- Now = now(),\r
+ Now = erlang:timestamp(),\r
Delta = euphorik_common:delta_date_ms(Auteur#user.date_derniere_connexion, Now),\r
Nouvel_indice_flood = Auteur#user.indice_flood + if Delta =< ?DUREE_SPAM -> 2; true -> -1 end,\r
Auteur_maj = Auteur#user{\r
nouveau_message_sys("\"" ++ Profile#profile.pseudo ++ if Auteur#user.login =/= [] -> " (" ++ Auteur#user.login ++ ")"; true -> "" end ++ "\" est bloqué pour " ++ integer_to_list(trunc(?DUREE_BLOCAGE_SPAM / 1000)) ++ " secondes pour cause de flood.");\r
Auteur#user.indice_flood =:= ?INDICE_SPAM_MAX, Delta =< ?DUREE_BLOCAGE_SPAM ->\r
{erreur, "Bloqué pour cause de flood"};\r
- true -> \r
+ true ->\r
mnesia:write(Auteur_maj),\r
Id = nouvel_id(minichat),\r
inserer_reponses(Id, Repond_A_ids),\r
_ ->\r
{erreur, "L'auteur du message est introuvable"}\r
end\r
- end
+ end\r
end\r
end,\r
resultat_transaction(mnesia:transaction(F)).\r
- \r
+\r
% Définit Id_repondant comme étant la réponse à Ids. Ids est une liste d'id.\r
inserer_reponses(Id_repondant, [Id_mess | Reste]) ->\r
mnesia:write(#reponse_minichat{repondant = Id_repondant, cible = Id_mess}),\r
inserer_reponses(Id_repondant, Reste);\r
inserer_reponses(_, []) ->\r
ok.\r
- \r
- \r
+\r
+\r
% Permet de créer un message système.\r
% Renvoie l'id du message système\r
nouveau_message_sys(Mess) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
Id = nouvel_id(minichat),\r
- mnesia:write(#minichat{id = Id, auteur_id = 0, date = now(), pseudo = Profile#profile.pseudo, contenu = Mess, racine_id = Id}),\r
+ mnesia:write(#minichat{id = Id, auteur_id = 0, date = erlang:timestamp(), pseudo = Profile#profile.pseudo, contenu = Mess, racine_id = Id}),\r
Id\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie N messages se trouvant sur la première page\r
-messages(N) -> \r
+messages(N) ->\r
messages(N, 1).\r
\r
\r
-% Renvoie N messages se trouvant sur la page P
+% Renvoie N messages se trouvant sur la page P\r
% TODO FIXME : fonction en O(N * P) !\r
messages(N, P) ->\r
- F = fun() ->
- % % #minichat{contenu = contenu_message(E)}
+ F = fun() ->\r
+ % % #minichat{contenu = contenu_message(E)}\r
get_tuples(minichat, mnesia:table_info(minichat, size) - N * P + 1, N)\r
end,\r
- resultat_transaction(mnesia:transaction(F)).
-
-
-get_tuples(Table, First_id, N) ->
- lists:foldr(
- fun(Id, Acc) ->
- case mnesia:read({Table, Id}) of
- [T] -> [T | Acc];
- _ -> Acc
- end
- end,
- [],
- lists:seq(First_id, First_id + N - 1)
- ).
- \r
+ resultat_transaction(mnesia:transaction(F)).\r
+\r
+\r
+get_tuples(Table, First_id, N) ->\r
+ lists:foldr(\r
+ fun(Id, Acc) ->\r
+ case mnesia:read({Table, Id}) of\r
+ [T] -> [T | Acc];\r
+ _ -> Acc\r
+ end\r
+ end,\r
+ [],\r
+ lists:seq(First_id, First_id + N - 1)\r
+ ).\r
+\r
\r
% Renvoie les messages manquants pour la page P en sachant qu'il y a N message\r
% par page et que le dernier message que l'on possède est Id\r
messages(Id, N, P) ->\r
lists:filter(fun (M) -> M#minichat.id > Id end, messages(N, P)).\r
- \r
- \r
+\r
+\r
% Renvoie {ok, #minichat} (voir #minichat de euphorik_bd.hrl) à partir de son id.\r
message_by_id(Id) ->\r
resultat_transaction(mnesia:transaction(\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie le contenu d'un message donnée en fonction du troll associé, à utiliser à l'intérieur d'une transaction.\r
% TODO : Cette fonction pourrait être remplacée par un "outer-join", est-ce possible avec qlc ?\r
contenu_message(E) ->\r
[] -> E#minichat.contenu;\r
[T] -> E#minichat.contenu ++ T#troll.content\r
end.\r
- \r
+\r
\r
% Renvoie une liste de message (voir #minichat de euphorik_bd.hrl) à partir d'une liste d'id (Ids).\r
% TODO : optimisations ? serait-ce du O(n) ?\r
),[{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end\r
)).\r
- \r
+\r
\r
% Est-ce qu'un message existe ? Renvoie un boolean.\r
% TODO : ya pas plus simple ?\r
resultat_transaction(mnesia:transaction(fun() ->\r
length(e(q([E#minichat.id || E <- mnesia:table(minichat), E#minichat.id =:= Id]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])) =:= 1\r
end)).\r
- \r
- \r
+\r
+\r
% Renvoie les reponses (utilisé normalement uniquement pendant le debug).\r
reponses() ->\r
F = fun() ->\r
e(q([E || E <- mnesia:table(reponse_minichat)]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end,\r
resultat_transaction(mnesia:transaction(F)).\r
- \r
- \r
+\r
+\r
% Renvoie les messages auquel M_id répond.\r
parents(M_id) ->\r
resultat_transaction(mnesia:transaction(\r
M#minichat.id =:= R#reponse_minichat.cible]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie les message qui repondent à M_id\r
enfants(M_id) ->\r
resultat_transaction(mnesia:transaction(\r
M#minichat.id =:= R#reponse_minichat.repondant]), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie les id des parents d'un message M (les messages auquels répond M)\r
% ordrés du plus petit au plus grand..\r
% On évite d'utiliser qlc pour des raisons de performance\r
fun(#reponse_minichat{cible = Cible}) -> Cible end,\r
Parents\r
));\r
- _ -> [] \r
+ _ -> []\r
end\r
end)).\r
- \r
- \r
+\r
+\r
% Renvoie les id des enfants d'un message M (les messages qui répondent à M)\r
% ordrés du plus petit au plus grand.\r
% @spec enfants_id(integer()) -> [integer()]\r
fun(#reponse_minichat{repondant = Repondant}) -> Repondant end,\r
Enfants\r
));\r
- _ -> [] \r
+ _ -> []\r
end\r
end)).\r
- \r
+\r
\r
% Est-ce que le message Id_mess est une réponse d'une message de Id_user ?\r
% On evite d'utiliser qlc (ce qui était fait avant) pour des raisons de performance.\r
end\r
)).\r
\r
- \r
+\r
% Est-ce que Id_user à répondu au message Id_mess\r
% On evite d'utiliser qlc (ce qui était fait avant) pour des raisons de performance.\r
a_repondu_a_message(Id_user, Id_mess) ->\r
end\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Est-ce que Id_user possède Id_mess ?\r
possede_message(Id_user, Id_mess) ->\r
case mnesia:transaction(\r
{atomic, [Id_user | []]} -> true;\r
_ -> false\r
end.\r
- \r
- \r
+\r
+\r
% renvoie la liste des ip bannies\r
% liste de {ip, temps_restant(en minutes), Users} ou Users est une liste de {pseudo, login}\r
% TODO : déterminer la complexité de cette fonction. (Il n'y a pas d'index sur #user.last_ip)\r
list_ban() ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
- Now = now(),\r
+ Now = erlang:timestamp(),\r
e(qlc:keysort(1, q([\r
{\r
IP#ip_table.ip,\r
fun() ->\r
case mnesia:wread({ip_table, IP}) of\r
[IP_tuple] ->\r
- mnesia:write(IP_tuple#ip_table{ban = now(), ban_duration = Duration});\r
+ mnesia:write(IP_tuple#ip_table{ban = erlang:timestamp(), ban_duration = Duration});\r
_ ->\r
- mnesia:write(#ip_table{ip = IP, ban = now(), ban_duration = Duration})\r
+ mnesia:write(#ip_table{ip = IP, ban = erlang:timestamp(), ban_duration = Duration})\r
end\r
end\r
).\r
- \r
+\r
\r
% Débanni une ip\r
deban(IP) ->\r
ban(IP, 0).\r
\r
- \r
+\r
% Renvoie soit {true, Temps} où Temps est le temps en minutes pendant lequel le user est encore banni\r
% ou false.\r
est_banni(User_id) ->\r
]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
[{Ban, Ban_duration}] ->\r
Echeance = date_plus_minutes(Ban, Ban_duration),\r
- Now = now(),\r
+ Now = erlang:timestamp(),\r
if Echeance < Now -> % l'échéance est passée\r
false;\r
true ->\r
end\r
end\r
)).\r
- \r
- \r
-% Ban est une date tel que retourner par now().\r
+\r
+\r
+% Ban est une date tel que retourner par erlang:timestamp().\r
% Ban_duration est un temps en minutes.\r
% retourne une date.\r
date_plus_minutes(Ban, Ban_duration) ->\r
Duration_sec = Ban_duration * 60,\r
{MegaSec, Sec, MicroSec} = Ban,\r
{MegaSec + if Sec + Duration_sec >= 1000000 -> 1; true -> 0 end,(Sec + Duration_sec) rem 1000000, MicroSec}.\r
- \r
\r
-% Si deux enregistrements consequtifs de la même IP sont fait en moins d'une seconde alors \r
+\r
+% Si deux enregistrements consequtifs de la même IP sont fait en moins d'une seconde alors\r
% ip_table.nb_try_register est incrémenté de 1 sinon il est décrémenté de 1 (jusqu'a 0).\r
% Si ip_table.nb_try_register vaut 5 alors l'ip ne peux plus s'enregistrer pour une heure.\r
can_register(IP) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
case e(q([I || I <- mnesia:table(ip_table), I#ip_table.ip =:= IP]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
- [] -> \r
- mnesia:write(#ip_table{ip = IP, date_last_try_register = now()}),\r
+ [] ->\r
+ mnesia:write(#ip_table{ip = IP, date_last_try_register = erlang:timestamp()}),\r
true;\r
[T] ->\r
- Delta = euphorik_common:delta_date_ms(T#ip_table.date_last_try_register, now()),\r
+ Delta = euphorik_common:delta_date_ms(T#ip_table.date_last_try_register, erlang:timestamp()),\r
if T#ip_table.nb_try_register =:= ?NB_MAX_FLOOD_REGISTER, Delta < ?TEMPS_BAN_FLOOD_REGISTER ->\r
false;\r
true ->\r
mnesia:write(T#ip_table{\r
ip = IP,\r
- date_last_try_register = now(),\r
+ date_last_try_register = erlang:timestamp(),\r
nb_try_register = T#ip_table.nb_try_register + if Delta < ?TEMPS_FLOOD_REGISTER -> 1; T#ip_table.nb_try_register > 0 -> -1; true -> 0 end\r
}),\r
true\r
end\r
end\r
)).\r
- \r
+\r
\r
% Renvoie tous les trolls\r
trolls() ->\r
e(qlc:keysort(#troll.id, q([T || T <- mnesia:table(troll)])), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Renvoie les trolls manquants posté après Last_id.\r
trolls(Last_id) ->\r
resultat_transaction(mnesia:transaction(\r
e(qlc:keysort(#troll.id, q([T || T <- mnesia:table(troll), T#troll.id > Last_id, T#troll.date_post =:= undefined])), [{tmpdir, ?KEY_SORT_TEMP_DIR}])\r
end\r
)).\r
- \r
- \r
+\r
+\r
% Crée un nouveau troll.\r
% Renvoie l'id du nouveau troll\r
% ou max_troll_reached_per_user si le nombre de troll posté par l'utilisateur max a été atteind\r
max_troll_reached;\r
true ->\r
Id = nouvel_id(troll),\r
- mnesia:write(#troll{id = Id, id_user = User_id, date_create = now(), content = Content}),\r
+ mnesia:write(#troll{id = Id, id_user = User_id, date_create = erlang:timestamp(), content = Content}),\r
Id\r
end;\r
_ ->\r
end\r
end\r
).\r
- \r
- \r
+\r
+\r
del_troll(Troll_id) ->\r
mnesia:transaction(\r
fun() ->\r
end\r
end\r
).\r
- \r
- \r
+\r
+\r
troll_by_id(Troll_id) ->\r
resultat_transaction(mnesia:transaction(\r
fun() ->\r
end\r
end\r
)).\r
- \r
+\r
\r
% Renvoie le troll actuel qui se trouve sur la page principale.\r
% Renvois aucun si pas de troll courant.\r
% Un message est posté par 'Sys' et le troll elu est lié à ce message\r
% met à jour sa date de post.\r
% renvoie plus_de_trolls si il n'y a aucun troll en attente.\r
-elire_troll() -> \r
- {A1,A2,A3} = now(),\r
+elire_troll() ->\r
+ {A1,A2,A3} = erlang:timestamp(),\r
random:seed(A1, A2, A3),\r
mnesia:transaction(\r
fun() ->\r
Trolls ->\r
Troll = lists:nth(random:uniform(length(Trolls)), Trolls),\r
Id_message = nouveau_message_sys("Troll de la semaine : "),\r
- Troll2 = Troll#troll{date_post = now(), id_minichat = Id_message},\r
+ Troll2 = Troll#troll{date_post = erlang:timestamp(), id_minichat = Id_message},\r
mnesia:write(Troll2)\r
end\r
end\r
).\r
- \r
- \r
+\r
+\r
% Renvoie le résultat d'une transaction (en décomposant le tuple fournit)\r
resultat_transaction({_, T}) ->\r
T.\r
% Renvoie un nouvel id pour une table donnée\r
nouvel_id(Table) ->\r
mnesia:dirty_update_counter(counter, Table, 1).\r
-
\ No newline at end of file
%
% You should have received a copy of the GNU General Public License
% along with Euphorik. If not, see <http://www.gnu.org/licenses/>.
-%
+%
% Module mettant à disposition tout un tas de fonction pour l'administration de la base de données euphorik comme :
% - Création de la BD
% - Mise à jour de la BD
connect/1,
reset/0,
update/0,
-
+
backup/1,
restore/1,
change_node_name/4,
-
+
toggle_ek_master/1,
print_users/0,
print_users/1,
mnesia:read({proprietes, version})
end
)).
-
-% Instructions pour créer une nouvelle base :
+
+% Instructions pour créer une nouvelle base :
% $erl -sname yaws -mnesia dir '"/projets/euphorik/BD"'
% voir doc/installation.txt
% >l(euphorik_bd).
mnesia:start(),
create_tables(),
reset().
-
+
create_tables() ->
mnesia:create_table(counter, [
{attributes, record_info(fields, counter)},
{disc_copies, [node()]}
]),
creer_indexes().
-
-
+
+
% mis à part car lors de la reprise de données avec load_textfile les indexes ne sont pas recréés
creer_indexes() ->
% commence par supprimer les anciens indexes
end,
mnesia:table_info(T, index)
)
- end,
+ end,
?TABLES
),
mnesia:add_table_index(minichat, auteur_id),
mnesia:add_table_index(reponse_minichat, cible),
mnesia:add_table_index(user, cookie),
mnesia:add_table_index(user, login),
- mnesia:add_table_index(troll, date_post),\r
+ mnesia:add_table_index(troll, date_post),
mnesia:add_table_index(troll, id_minichat).
-
-
+
+
% Connexion à la base de données de yaws sur overnux
connect() ->
connect(yaws@flynux).
% crée l'utilisateur root
mnesia:transaction(fun() ->
mnesia:write(#proprietes{nom = version, valeur = ?VERSION_BD}),
- User = #user{id = 0, profile = #profile{pseudo = "Sys"}, login = "Sys", date_creation = now(), date_derniere_connexion = now(), ek_master = true},
+ User = #user{id = 0, profile = #profile{pseudo = "Sys"}, login = "Sys", date_creation = erlang:timestamp(), date_derniere_connexion = erlang:timestamp(), ek_master = true},
mnesia:write(User),
User
end),
peupler_texte().
-
-
+
+
peupler_texte() ->
mnesia:transaction(fun() ->
mnesia:write(#texte{ id = 10, fr = "Login déjà existant"}),
_ ->
erreur
end.
-
+
% Mise à jour de la BD.
% attention : il est nécessaire de se trouver dans une transaction.
end;
{error, Raison} -> {error, lists:flatten(io_lib:format("Erreur de création du backup de la version ~w : ~w", [Version, Raison]))}
end.
-
-
+
+
% Applique une modification de la BD pour passer d'une version à la suivante.
% crée un backup avant l'application du patch
% dans BD/backups nommé "backup<num>" où <num> et le numéro de la version.
% 1 -> 2
-patch(1) ->\r
- % Prend un chemin vers la feuille de style de type "css/1/euphorik.css"\r
- % et renvoie "styles/1/euphorik.css"\r
+patch(1) ->
+ % Prend un chemin vers la feuille de style de type "css/1/euphorik.css"
+ % et renvoie "styles/1/euphorik.css"
Transforme_css = fun("css" ++ Reste) ->
- "styles" ++ Reste;\r
- (F) -> F\r
- end,\r
- Traiter_message = fun(M, Racine) ->\r
- F = fun(F, M2) -> % seul moyen à ma connaissance pour faire de la récursion dans une lambda fonction, voir : http://www.nabble.com/Auto-generated-functions-td15279499.html\r
- % met à jour la racine de chaque message qui répond à M\r
- lists:foreach(\r
- fun(M3) ->\r
- mnesia:write(M2#minichat{racine_id = Racine}),\r
- F(F, M3)\r
- end,\r
- euphorik_bd:enfants(M#minichat.id)\r
- )\r
- end,\r
- F(F, M, Racine)\r
+ "styles" ++ Reste;
+ (F) -> F
+ end,
+ Traiter_message = fun(M, Racine) ->
+ F = fun(F, M2) -> % seul moyen à ma connaissance pour faire de la récursion dans une lambda fonction, voir : http://www.nabble.com/Auto-generated-functions-td15279499.html
+ % met à jour la racine de chaque message qui répond à M
+ lists:foreach(
+ fun(M3) ->
+ mnesia:write(M2#minichat{racine_id = Racine}),
+ F(F, M3)
+ end,
+ euphorik_bd:enfants(M#minichat.id)
+ )
+ end,
+ F(F, M, Racine)
end,
mnesia:create_table(texte, [
{attributes, record_info(fields, texte)},
{disc_copies, [node()]}
]),
peupler_texte(),
- % traitement des users
+ % traitement des users
mnesia:transform_table(
user,
fun({user, Id, Cookie, Pseudo, Login, Password, Email, Date_creation, Date_derniere_connexion, Css, Nick_format, View_times, View_tooltips, Indice_flood, _Page_principale, Conversations, Ek_master, Last_ip}) ->
) of
{aborted, Raison} -> {erreur, Raison};
{atomic, _} -> ok
- end;\r
-% 2 -> 3\r
-patch(2) ->\r
- mnesia:transform_table(\r
- troll,\r
- fun({troll, Id_troll, Id_user, Date_create, Date_post, Content}) ->\r
- % recherche le message associé s'il existe\r
- Id_minichat = case e(q([M || M <- mnesia:table(minichat), element(7, M) =:= Id_troll]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of\r
- [M] -> element(2, M);\r
- _ -> undefined\r
- end,\r
- {troll, Id_troll, Id_user, Id_minichat, Date_create, Date_post, Content}\r
- end,\r
- record_info(fields, troll)\r
- ),\r
- %mnesia:del_table_index(minichat, troll_id),\r
- mnesia:transform_table(\r
- minichat,\r
- fun({minichat, Id, Auteur_id, Date, Pseudo, Contenu, _Troll_id, Racine_id}) ->\r
- {minichat, Id, Auteur_id, Date, Pseudo, Contenu, Racine_id, normal}\r
- end,\r
- record_info(fields, minichat)\r
+ end;
+% 2 -> 3
+patch(2) ->
+ mnesia:transform_table(
+ troll,
+ fun({troll, Id_troll, Id_user, Date_create, Date_post, Content}) ->
+ % recherche le message associé s'il existe
+ Id_minichat = case e(q([M || M <- mnesia:table(minichat), element(7, M) =:= Id_troll]), [{tmpdir, ?KEY_SORT_TEMP_DIR}]) of
+ [M] -> element(2, M);
+ _ -> undefined
+ end,
+ {troll, Id_troll, Id_user, Id_minichat, Date_create, Date_post, Content}
+ end,
+ record_info(fields, troll)
+ ),
+ %mnesia:del_table_index(minichat, troll_id),
+ mnesia:transform_table(
+ minichat,
+ fun({minichat, Id, Auteur_id, Date, Pseudo, Contenu, _Troll_id, Racine_id}) ->
+ {minichat, Id, Auteur_id, Date, Pseudo, Contenu, Racine_id, normal}
+ end,
+ record_info(fields, minichat)
),
mnesia:transaction(fun() ->
% comble les trous entre les id non-contigues
lists:foreach(fun(Id) ->
case mnesia:read({minichat, Id}) of
- [] ->
+ [] ->
{ok, #user{profile = Profile}} = euphorik_bd:user_by_id(0),
mnesia:write(#minichat{id = Id, auteur_id = 0, date = undefined, pseudo = Profile#profile.pseudo, contenu = "Comblement...", racine_id = Id, status = deleted});
_ -> rien
),
% la table troll utilise maintenant son index et pas celui de la table minichat (correction d'un vieux bug)
mnesia:write(#counter{key = troll, value = mnesia:table_info(minichat, size)})
- end),\r
- creer_indexes(). % uniquement pour l'indice sur id_minichat de la table troll\r
+ end),
+ creer_indexes(). % uniquement pour l'indice sur id_minichat de la table troll
% Renvoie le dossier dans lequel les backups sont effectué, ce dossier doit être en écriture.
% Renvoie le fichier (avec le chemin) correspondant à la version Version, par exemple : "/var/euphorik/BD/backups/backup1"
-fichier_backup(Version) when is_integer(Version) ->
+fichier_backup(Version) when is_integer(Version) ->
dossier_backups() ++ "backup" ++ integer_to_list(Version).
-\r
+
% crée un backup dont le nom est fournit dans le repertoire backups qui se trouve dans le repertoire de la BD.
backup(Fichier) ->
mnesia:backup(dossier_backups() ++ Fichier).
-
-
+
+
% Restaure un backup de la BD.
restore(Fichier) when is_list(Fichier) ->
mnesia:restore(dossier_backups() ++ Fichier, []);
% (les données insérées durant les versions plus récentes sont perdues).
restore(Version) when is_integer(Version) ->
mnesia:restore(fichier_backup(Version), []). % [{default_op, recreate_tables}]).
-
+
% Change le nom du noeud d'un backup.
% provient d'ici : http://www.erlang.org/doc/apps/mnesia/Mnesia_chap7.html#6.9
% Obsolète
%~ backup_text(File) ->
%~ mnesia:dump_to_textfile(File).
-%~ restore_text(File) ->
+%~ restore_text(File) ->
%~ mnesia:stop(),
%~ mnesia:delete_schema([node()]),
%~ mnesia:start(),
end
end
)).
-
+
% Affiche N user trié par leur date de dernière connexion.
% Opt est une liste d'option d'affichage :
euphorik_bd:resultat_transaction(mnesia:transaction(fun() ->
C = cursor(
qlc:keysort(
- #user.date_derniere_connexion,
+ #user.date_derniere_connexion,
if AfficheQueLesEkMaster ->
q([E || E <- mnesia:table(user), E#user.ek_master =:= true]);
true ->
),
qlc:delete_cursor(C)
end)).
-
-
+
+
% Affiche tous les users.
print_users(Opt) ->
print_users(all_remaining, Opt).
% Affiche tous les users.
print_users() ->
print_users(all_remaining, []).
-
+
print_user(User) when is_record(User, user) ->
#user{id = Id, profile = #profile{pseudo = Pseudo}, login = Login, ek_master = Ek_master, date_derniere_connexion = Date, last_ip = IP} = User,
{{Annee, Mois, Jour}, {Heure, Min, _}} = calendar:now_to_local_time(Date),
io:format(
% id pseudo (login) IP Jour Mois Année Heure Minute
"~4w : ~10.10..s(~10.10..s) ~s ~2w.~2.2.0w.~w - ~2wh~2.2.0w~n",
- [
+ [
Id,
if Ek_master -> "*"; true -> "" end ++ Pseudo,
Login,
{erreur, "Login pas trouvé : " ++ Login}
end;
% Affichage d'un user en fonction de son id
-print_user(Id) when is_integer(Id) ->
- case euphorik_bd:user_by_id(Id) of
+print_user(Id) when is_integer(Id) ->
+ case euphorik_bd:user_by_id(Id) of
{ok, User} ->
print_user(User);
_ ->
{erreur, "Id pas trouvé : " ++ integer_to_list(Id)}
end.
-
\ No newline at end of file
%
% You should have received a copy of the GNU General Public License
% along with Euphorik. If not, see <http://www.gnu.org/licenses/>.
-%
+%
% Module avec plein de bordel utile à l'intérieur.
% @author G.Burri
Pos when Pos > 0 -> T + 1;
_ -> T
end.
-
-% Retourne la difference entre deux timestamp (erlang:now()) en miliseconde
+
+% Retourne la difference entre deux timestamp (erlang:timestamp()) en miliseconde
delta_date_ms(D1, D2) ->
1000000000 * abs(element(1, D1) - element(1, D2)) + 1000 * abs(element(2, D1) - element(2, D2)) + trunc(abs(element(3, D1) - element(3, D2)) / 1000).
% Retourne la différence entre deux timestamp (erlang:now) en minutes
delta_date_minute(D1, D2) ->
trunc(delta_date_ms(D1, D2) / 1000 / 60).
-
+
serialize_ip(undefined) ->
"<unknown IP>";
serialize_ip(IP) ->
lists:flatten(io_lib:format("~w.~w.~w.~w", tuple_to_list(IP))).
-
-
+
+
unserialize_ip(IP) ->
case io_lib:fread("~d.~d.~d.~d", IP) of
{ok, [A, B, C, D], []} -> {A, B, C, D};
%\r
% You should have received a copy of the GNU General Public License\r
% along with Euphorik. If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
% Ce module gére les différents messages envoyés par le client (javascript) via AJAX.\r
% Les messages donnés ainsi que les réponses sont au format JSON.\r
% @author G.Burri\r
\r
\r
% Une utilisateur s'enregistre avec un tuple {Login, Password}.\r
-register([{login, Login}, {password, Password}, {profile, Profile_json}], IP) ->\r
+register([{"login", Login}, {"password", Password}, {"profile", Profile_json}], IP) ->\r
Can_register = euphorik_bd:can_register(IP),\r
if Can_register ->\r
case euphorik_bd:user_by_login(Login) of\r
erreur_register_flood()\r
end;\r
% Enregistrement sans {Login, Password}\r
-register([{profile, Profile_json}], IP) -> \r
+register([{"profile", Profile_json}], IP) ->\r
Can_register = euphorik_bd:can_register(IP),\r
if Can_register ->\r
Profile = profile_from_json(Profile_json),\r
true ->\r
erreur_register_flood()\r
end.\r
- \r
+\r
erreur_register_flood() ->\r
erreur(20).\r
- \r
+\r
\r
% Un utilisateur se logge (avec un couple {login, mot de passe})\r
-login([{login, Login}, {password, Password}], IP) ->\r
+login([{"login", Login}, {"password", Password}], IP) ->\r
case euphorik_bd:user_by_login_password(Login, Password) of\r
{ok, User} ->\r
loginUser(User, IP);\r
- _ -> \r
+ _ ->\r
timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
erreur(30)\r
end;\r
% Un utilisateur se logge (avec un cookie)\r
-login([{cookie, Cookie}], IP) ->\r
+login([{"cookie", Cookie}], IP) ->\r
case euphorik_bd:user_by_cookie(Cookie) of\r
{ok, User} ->\r
loginUser(User, IP);\r
timer:sleep(?TEMPS_ATTENTE_ERREUR_LOGIN),\r
erreur(40)\r
end.\r
- \r
- \r
+\r
+\r
% L'utilisateur donné se logge avec l'ip donnée.\r
loginUser(User, IP) ->\r
euphorik_bd:update_ip(User#user.id, IP),\r
euphorik_bd:update_date_derniere_connexion(User#user.id),\r
json_reponse_login_ok(User).\r
- \r
- \r
+\r
+\r
% Renvoie un string() représentant un cookie en base 36. Il y a 10^32 possibillités.\r
generer_cookie() ->\r
- {A1, A2, A3} = now(),\r
+ {A1, A2, A3} = erlang:timestamp(),\r
random:seed(A1, A2, A3),\r
erlang:integer_to_list(random:uniform(trunc(math:pow(10, 32))), 36).\r
\r
% Modification du profile.\r
profile(\r
[\r
- {cookie, Cookie},\r
- {login, Login},\r
- {password, Password},\r
- {profile, Profile_json}\r
+ {"cookie", Cookie},\r
+ {"login", Login},\r
+ {"password", Password},\r
+ {"profile", Profile_json}\r
]\r
) ->\r
case profile_from_json(Profile_json) of\r
profile_from_json(\r
{struct,\r
[\r
- {nick, Pseudo},\r
- {email, Email},\r
- {css, Css},\r
- {chat_order, Chat_order_str},\r
- {nick_format, Nick_format_str},\r
- {view_times, View_times},\r
- {view_tooltips, View_tooltips},\r
- {conversations, {array, Conversations_json}},\r
- {ostentatious_master, Ostentatious_master_str}\r
+ {"nick", Pseudo},\r
+ {"email", Email},\r
+ {"css", Css},\r
+ {"chat_order", Chat_order_str},\r
+ {"nick_format", Nick_format_str},\r
+ {"view_times", View_times},\r
+ {"view_tooltips", View_tooltips},\r
+ {"conversations", {array, Conversations_json}},\r
+ {"ostentatious_master", Ostentatious_master_str}\r
]\r
}\r
) ->\r
% décomposition de la strucure JSON\r
Conversations = lists:foldr(\r
- fun({struct, [{root, Racine}, {minimized, Reduit}]}, A) ->\r
+ fun({struct, [{"root", Racine}, {"minimized", Reduit}]}, A) ->\r
% virage des messages qui n'existent pas\r
Message_exite = euphorik_bd:message_existe(Racine),\r
if Message_exite ->\r
Chat_order_valide = lists:any(fun(E) -> E =:= Chat_order end, [reverse, chrono]),\r
if not Chat_order_valide ->\r
{erreur, Chat_order_str ++ " n'est pas une valeur acceptée pour 'chat_order'"};\r
- true -> \r
+ true ->\r
Nick_format = list_to_atom(Nick_format_str),\r
Nick_format_valide = lists:any(fun(E) -> E =:= Nick_format end, [nick, login, nick_login]),\r
if not Nick_format_valide ->\r
{erreur, Nick_format_str ++ " n'est pas une valeur acceptée pour 'nick_format'"};\r
- true -> \r
+ true ->\r
Ostentatious_master = list_to_atom(Ostentatious_master_str),\r
Ostentatious_master_valide = lists:any(fun(E) -> E =:= Ostentatious_master end, [invisible, light, heavy]),\r
if not Ostentatious_master_valide ->\r
ostentatious_master = Ostentatious_master\r
}\r
end\r
- end \r
+ end\r
end.\r
\r
\r
% Attend un événement pour la page "Chat"\r
% last_message id et cookie sont facultatifs\r
-wait_event([{page, "chat"} | Data]) ->\r
+wait_event([{"page", "chat"} | Data]) ->\r
% traitement des inputs\r
- Cookie = case lists:keysearch(cookie, 1, Data) of {value, {_, C}} -> C; _ -> inconnu end,\r
- Last_message_id = case lists:keysearch(last_message_id, 1, Data) of {value, {_, Id}} -> Id; _ -> 0 end,\r
- {value, {_, Message_count}} = lists:keysearch(message_count, 1, Data),\r
- Main_page = case lists:keysearch(main_page, 1, Data) of {value, {_, P}} -> P; _ -> 1 end,\r
- Troll_id = case lists:keysearch(troll_id, 1, Data) of {value, {_, T}} -> T; _ -> 0 end,\r
- {value, {_, {array, Conversations_json}}} = lists:keysearch(conversations, 1, Data),\r
+ Cookie = case lists:keysearch("cookie", 1, Data) of {value, {_, C}} -> C; _ -> inconnu end,\r
+ Last_message_id = case lists:keysearch("last_message_id", 1, Data) of {value, {_, Id}} -> Id; _ -> 0 end,\r
+ {value, {_, Message_count}} = lists:keysearch("message_count", 1, Data),\r
+ Main_page = case lists:keysearch("main_page", 1, Data) of {value, {_, P}} -> P; _ -> 1 end,\r
+ Troll_id = case lists:keysearch("troll_id", 1, Data) of {value, {_, T}} -> T; _ -> 0 end,\r
+ {value, {_, {array, Conversations_json}}} = lists:keysearch("conversations", 1, Data),\r
+\r
Racines_conversations = lists:map(\r
- fun({struct, [{root, Racine}, {page, Page} | Reste]}) ->\r
- Last_mess_conv = case Reste of [{last_message_id, L}] -> L; _ -> 0 end,\r
+ fun({struct, [{"root", Racine}, {"page", Page} | Reste]}) ->\r
+ Last_mess_conv = case Reste of [{"last_message_id", L}] -> L; _ -> 0 end,\r
{Racine, Page, Last_mess_conv}\r
end,\r
Conversations_json\r
{ok, U} -> U;\r
_ -> inconnu\r
end,\r
+\r
case {mnesia:subscribe({table, minichat, detailed}), mnesia:subscribe({table, troll, detailed})} of\r
{{error, E}, _} -> E;\r
{_, {error, E}} -> E;\r
R\r
end;\r
% Attend un événement pour la page "Admin"\r
-wait_event([{page, "admin"}, {last_troll, Last_troll}]) ->\r
+wait_event([{"page", "admin"}, {"last_troll", Last_troll}]) ->\r
case wait_event_page_admin(Last_troll) of\r
banned_ips_refresh ->\r
- {struct, \r
+ {struct,\r
[\r
- {reply, "banned_ips_refresh"}\r
+ {"reply", "banned_ips_refresh"}\r
]\r
};\r
{mod, Troll} ->\r
{struct,\r
[\r
- {reply, "troll_modified"},\r
- {troll_id, Troll#troll.id},\r
- {content, Troll#troll.content}\r
+ {"reply", "troll_modified"},\r
+ {"troll_id", Troll#troll.id},\r
+ {"content", Troll#troll.content}\r
]\r
};\r
{add, Trolls} ->\r
{struct,\r
[\r
- {reply, "troll_added"},\r
- {trolls, {array, \r
+ {"reply", "troll_added"},\r
+ {"trolls", {array,\r
lists:map(\r
- fun(T) -> \r
+ fun(T) ->\r
{ok, #user{profile = Profile} = User} = euphorik_bd:user_by_id(T#troll.id_user),\r
{struct,\r
[\r
- {troll_id, T#troll.id},\r
- {content, T#troll.content},\r
- {author, Profile#profile.pseudo},\r
- {author_id, User#user.id}\r
+ {"troll_id", T#troll.id},\r
+ {"content", T#troll.content},\r
+ {"author", Profile#profile.pseudo},\r
+ {"author_id", User#user.id}\r
]\r
}\r
end,\r
)\r
}}\r
]\r
- }; \r
+ };\r
{del, Troll_id} ->\r
{struct,\r
[\r
- {reply, "troll_deleted"},\r
- {troll_id, Troll_id}\r
+ {"reply", "troll_deleted"},\r
+ {"troll_id", Troll_id}\r
]\r
- }; \r
+ };\r
_ ->\r
erreur(60)\r
end;\r
case euphorik_bd:current_troll() of\r
Current when is_record(Current, troll), Current#troll.id =/= Troll_id ->\r
{struct, [\r
- {reply, "new_troll"},\r
- {troll_id, Current#troll.id},\r
- {message_id, Current#troll.id_minichat},\r
- {content, Current#troll.content}\r
+ {"reply", "new_troll"},\r
+ {"troll_id", Current#troll.id},\r
+ {"message_id", Current#troll.id_minichat},\r
+ {"content", Current#troll.content}\r
]};\r
_ ->\r
% est-ce qu'il y a des nouveaux messages ?\r
case euphorik_minichat_conversation:conversations(Racines_conversations, Message_count, Last_message_id, Main_page) of\r
- vide -> \r
+ vide ->\r
wait_event_bd_page_chat(),\r
wait_event_page_chat(User, Racines_conversations, Message_count, Last_message_id, Main_page, Troll_id);\r
Conversations ->\r
% accrochez-vous ca va siouxer ;)\r
{struct, [\r
- {reply, "new_messages"},\r
- {conversations, {array,\r
+ {"reply", "new_messages"},\r
+ {"conversations", {array,\r
lists:map(\r
fun({Racine, {Conv, Plus}}) ->\r
{struct, [\r
- {last_page, not Plus},\r
- {first, % le premier message de la conversation\r
+ {"last_page", not Plus},\r
+ {"first", % le premier message de la conversation\r
if Racine =:= undefined orelse Conv =:= [] ->\r
null;\r
true ->\r
]}\r
end\r
end.\r
- \r
\r
-aggregation_racines_conversations(L1, L2) -> \r
+\r
+aggregation_racines_conversations(L1, L2) ->\r
aggregation_racines_conversations(L1, L2, []).\r
aggregation_racines_conversations([], [], L) -> lists:reverse(L);\r
aggregation_racines_conversations([E1|R1], [E2|R2], L) ->\r
aggregation_racines_conversations(R1, R2, [{E1, E2} | L]).\r
- \r
+\r
\r
\r
% Attend un événement lié à la page 'chat'.\r
wait_event_bd_page_chat()\r
% 60 minutes de timeout (on ne sais jamais)\r
% Après 60 minutes de connexion, le client doit donc reétablir une connexion\r
- after 1000 * 60 * 60 -> \r
+ after 1000 * 60 * 60 ->\r
timeout\r
end.\r
\r
mnesia:unsubscribe({table, ip_table, detailed}),\r
R\r
end.\r
- \r
+\r
wait_event_page_admin() ->\r
% s'il n'y a pas de trolls que l'utilisateur n'a pas connaissance alors on attend un événement\r
receive\r
wait_event_page_admin()\r
% 60 minutes de timeout (on ne sais jamais)\r
% Après 60 minutes de connexion, le client doit donc reétablir une connexion\r
- after 1000 * 60 * 60 -> \r
+ after 1000 * 60 * 60 ->\r
timeout\r
end.\r
- \r
- \r
+\r
+\r
% Un utilisateur envoie un message\r
% Answer_to est une liste d'id (int)\r
put_message(\r
[\r
- {cookie, Cookie},\r
- {nick, Nick},\r
- {content, Content},\r
- {answer_to, {array, Answer_to}}\r
+ {"cookie", Cookie},\r
+ {"nick", Nick},\r
+ {"content", Content},\r
+ {"answer_to", {array, Answer_to}}\r
]\r
) ->\r
case euphorik_bd:user_by_cookie(Cookie) of\r
% bannissement d'un utilisateur (son ip est bannie)\r
ban(\r
[\r
- {cookie, Cookie},\r
- {duration, Duration},\r
- {user_id, User_id},\r
- {reason, Reason}\r
+ {"cookie", Cookie},\r
+ {"duration", Duration},\r
+ {"user_id", User_id},\r
+ {"reason", Reason}\r
]) ->\r
% controle que l'utilisateur est un admin\r
case euphorik_bd:user_by_cookie(Cookie) of\r
_ ->\r
erreur(150)\r
end.\r
- \r
+\r
\r
% slapage d'un user (avertissement)\r
slap(\r
[\r
- {cookie, Cookie},\r
- {user_id, User_id},\r
- {reason, Reason}\r
+ {"cookie", Cookie},\r
+ {"user_id", User_id},\r
+ {"reason", Reason}\r
]) ->\r
% controle que l'utilisateur est un admin\r
case euphorik_bd:user_by_cookie(Cookie) of\r
{ok, User1 = #user{ek_master = true, profile = Profile1}} ->\r
case euphorik_bd:user_by_id(User_id) of\r
{ok, User1} ->\r
- euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap~s.", \r
+ euphorik_bd:nouveau_message_sys(lists:flatten(io_lib:format("~s s'auto slap~s.",\r
[\r
Profile1#profile.pseudo,\r
if Reason =/= [] -> " - Raison: " ++ Reason; true -> "" end\r
_ ->\r
erreur(170)\r
end.\r
- \r
- \r
+\r
+\r
put_troll(\r
[\r
- {cookie, Cookie},\r
- {content, Content}\r
+ {"cookie", Cookie},\r
+ {"content", Content}\r
]\r
) ->\r
% controle que l'utilisateur est un admin\r
_ ->\r
erreur(200)\r
end.\r
- \r
- \r
+\r
+\r
mod_troll(\r
[\r
- {cookie, Cookie},\r
- {troll_id, Troll_id},\r
- {content, Content}\r
+ {"cookie", Cookie},\r
+ {"troll_id", Troll_id},\r
+ {"content", Content}\r
]\r
) ->\r
% controle que l'utilisateur est un admin\r
erreur(220)\r
end.\r
\r
- \r
+\r
del_troll(\r
[\r
- {cookie, Cookie},\r
- {troll_id, Troll_id}\r
+ {"cookie", Cookie},\r
+ {"troll_id", Troll_id}\r
]\r
-) -> \r
+) ->\r
% controle que l'utilisateur est un admin\r
case euphorik_bd:user_by_cookie(Cookie) of\r
{ok, User = #user{ek_master = true}} ->\r
_ ->\r
erreur(220)\r
end.\r
- \r
- \r
+\r
+\r
unban_ip(\r
[\r
- {cookie, Cookie},\r
- {ip, IP}\r
+ {"cookie", Cookie},\r
+ {"ip", IP}\r
]\r
) ->\r
case euphorik_bd:user_by_cookie(Cookie) of\r
_ ->\r
erreur(230)\r
end.\r
- \r
- \r
+\r
+\r
list_banned_ips(\r
[\r
- {cookie, Cookie}\r
+ {"cookie", Cookie}\r
]\r
) ->\r
case euphorik_bd:user_by_cookie(Cookie) of\r
{\r
struct,\r
[\r
- {reply, "list_banned_ips"},\r
- {list, {array, lists:map(\r
+ {"reply", "list_banned_ips"},\r
+ {"list", {array, lists:map(\r
fun({IP, T, Users}) ->\r
{struct,\r
[\r
- {ip, euphorik_common:serialize_ip(IP)},\r
- {remaining_time, format_minutes(T)},\r
- {users, {array, lists:map(\r
+ {"ip", euphorik_common:serialize_ip(IP)},\r
+ {"remaining_time", format_minutes(T)},\r
+ {"users", {array, lists:map(\r
fun({Pseudo, Login}) ->\r
{struct,\r
[\r
- {nick, Pseudo},\r
- {login, Login}\r
+ {"nick", Pseudo},\r
+ {"login", Login}\r
]\r
}\r
end,\r
% Construit une erreur\r
erreur(Num, Args) ->\r
erreur_json(Num, lists:flatten(io_lib:format(euphorik_bd:get_texte(Num), Args))).\r
- \r
- \r
+\r
+\r
erreur(Num) ->\r
erreur_json(Num, euphorik_bd:get_texte(Num)).\r
- \r
- \r
+\r
+\r
erreur_json(Num, Mess) ->\r
{\r
struct, [\r
- {reply, "error"},\r
- {no, Num},\r
- {error_message, Mess}\r
+ {"reply", "error"},\r
+ {"no", Num},\r
+ {"error_message", Mess}\r
]\r
}.\r
- \r
- \r
+\r
+\r
% Formatage de minutes.\r
% par exemple : "1min", "45min", "1h23min", "1jour 2h34min"\r
format_minutes(Min) ->\r
true ->\r
" " ++ integer_to_list(Minutes) ++ " minute" ++ if Minutes > 1 -> "s"; true -> "" end\r
end.\r
- \r
- \r
+\r
+\r
% Formatage d'une heure\r
% local_time() -> string\r
format_date(Date) ->\r
Hier ->\r
"Hier ";\r
Annee =:= AnneeNow ->\r
- io_lib:format("~2.10.0B/~2.10.0B ", [Jour, Mois]); \r
+ io_lib:format("~2.10.0B/~2.10.0B ", [Jour, Mois]);\r
true ->\r
io_lib:format("~2.10.0B/~2.10.0B/~B ", [Jour, Mois, Annee])\r
end ++\r
\r
\r
json_reponse_ok() ->\r
- {struct, [{reply, "ok"}]}.\r
- \r
- \r
+ {struct, [{"reply", "ok"}]}.\r
+\r
+\r
json_reponse_login_ok(#user{profile = Profile} = User) ->\r
{\r
struct, [\r
- {reply, "login"},\r
- {status, if (User#user.password =/= []) and (User#user.login =/= []) -> "auth_registered"; true -> "auth_not_registered" end},\r
- {cookie, User#user.cookie},\r
- {id, User#user.id},\r
- {login, User#user.login},\r
- {ek_master, User#user.ek_master},\r
- {profile, {struct,\r
+ {"reply", "login"},\r
+ {"status", if (User#user.password =/= []) and (User#user.login =/= []) -> "auth_registered"; true -> "auth_not_registered" end},\r
+ {"cookie", User#user.cookie},\r
+ {"id", User#user.id},\r
+ {"login", User#user.login},\r
+ {"ek_master", User#user.ek_master},\r
+ {"profile", {struct,\r
[\r
- {nick, Profile#profile.pseudo},\r
- {email, Profile#profile.email},\r
- {css, Profile#profile.css},\r
- {chat_order, atom_to_list(Profile#profile.chat_order)},\r
- {nick_format, atom_to_list(Profile#profile.nick_format)},\r
- {view_times, Profile#profile.view_times},\r
- {view_tooltips, Profile#profile.view_tooltips},\r
- {conversations, {array, lists:map(\r
+ {"nick", Profile#profile.pseudo},\r
+ {"email", Profile#profile.email},\r
+ {"css", Profile#profile.css},\r
+ {"chat_order", atom_to_list(Profile#profile.chat_order)},\r
+ {"nick_format", atom_to_list(Profile#profile.nick_format)},\r
+ {"view_times", Profile#profile.view_times},\r
+ {"view_tooltips", Profile#profile.view_tooltips},\r
+ {"conversations", {array, lists:map(\r
fun({Racine, Reduit}) ->\r
- {struct, [{root, Racine}, {minimized, Reduit}]}\r
+ {struct, [{"root", Racine}, {"minimized", Reduit}]}\r
end,\r
Profile#profile.conversations\r
)}},\r
- {ostentatious_master, atom_to_list(Profile#profile.ostentatious_master)}\r
+ {"ostentatious_master", atom_to_list(Profile#profile.ostentatious_master)}\r
]\r
}}\r
]\r
}.\r
- \r
+\r
% Renvoie le message formaté en JSON.\r
% Mess est de type #minichat\r
% Repond_a est une liste d'id des messages auquel répond Mess\r
Est_une_reponse_a_user = User =/= inconnu andalso euphorik_bd:est_une_reponse_a_user(User#user.id, Mess#minichat.id),\r
{ok, #user{profile = Profile_mess} = User_mess } = euphorik_bd:user_by_id(Mess#minichat.auteur_id),\r
{struct, [\r
- {id, Mess#minichat.id},\r
- {user_id, User_mess#user.id},\r
- {date, case Mess#minichat.date of undefined -> "?"; _ -> format_date(Mess#minichat.date) end},\r
- {system, Mess#minichat.auteur_id =:= 0},\r
- {owner, Est_proprietaire},\r
- {answered, A_repondu_a_message},\r
- {is_a_reply, Est_une_reponse_a_user},\r
- {nick, Mess#minichat.pseudo},\r
- {login, User_mess#user.login},\r
- {content, Mess#minichat.contenu},\r
- {root, Mess#minichat.racine_id},\r
- {answer_to, {array, lists:map(\r
- fun(Id_mess) -> \r
+ {"id", Mess#minichat.id},\r
+ {"user_id", User_mess#user.id},\r
+ {"date", case Mess#minichat.date of undefined -> "?"; _ -> format_date(Mess#minichat.date) end},\r
+ {"system", Mess#minichat.auteur_id =:= 0},\r
+ {"owner", Est_proprietaire},\r
+ {"answered", A_repondu_a_message},\r
+ {"is_a_reply", Est_une_reponse_a_user},\r
+ {"nick", Mess#minichat.pseudo},\r
+ {"login", User_mess#user.login},\r
+ {"content", Mess#minichat.contenu},\r
+ {"root", Mess#minichat.racine_id},\r
+ {"answer_to", {array, lists:map(\r
+ fun(Id_mess) ->\r
{ok, M} = euphorik_bd:message_by_id(Id_mess),\r
{ok, User_reponse} = euphorik_bd:user_by_mess(M#minichat.id),\r
- {struct, [{id, M#minichat.id}, {nick, M#minichat.pseudo}, {login, User_reponse#user.login}]}\r
+ {struct, [{"id", M#minichat.id}, {"nick", M#minichat.pseudo}, {"login", User_reponse#user.login}]}\r
end,\r
Repond_a\r
)}},\r
- {ek_master, User_mess#user.ek_master},\r
- {ostentatious_master, atom_to_list(Profile_mess#profile.ostentatious_master)}\r
+ {"ek_master", User_mess#user.ek_master},\r
+ {"ostentatious_master", atom_to_list(Profile_mess#profile.ostentatious_master)}\r
]}.\r
%\r
% You should have received a copy of the GNU General Public License\r
% along with Euphorik. If not, see <http://www.gnu.org/licenses/>.\r
-% \r
+%\r
% Ce module est fait pour répondre à des requêtes JSON via 'AJAX'.\r
% Il est définit comme 'appmods' pour l'url "request" dans Yaws.\r
% Par exemple http://www.euphorik.ch/request abouti sur la fonction out/1 de ce module.\r
\r
-module(euphorik_requests).\r
-export([out/1]).\r
--include_lib("yaws/include/yaws_api.hrl").\r
+-include_lib("yaws_api.hrl").\r
-include("../include/euphorik_defines.hrl").\r
\r
\r
% Point d'entrée pour les requêtes AJAX sur http://www.euphorik.ch/request.\r
-out(A) -> \r
+out(A) ->\r
IP = case inet:peername(A#arg.clisock) of\r
{ok, {Adresse, _Port}} -> Adresse;\r
_ -> inconnue\r
% Décode le message JSON.\r
traiter_message(Contenu, IP) ->\r
% extrait l'entête obligatoire des messages JSON\r
- {ok, {struct, [{header, {struct, [{action, Action}, {version, Version_client}]}} | Reste]}} = json:decode_string(Contenu),\r
- json:encode(\r
+ {ok, {struct, [{"header", {struct, [{"action", Action}, {"version", Version_client}]}} | Reste]}} = json2:decode_string(Contenu),\r
+\r
+ json2:encode(\r
if Version_client =:= ?VERSION_PROTOCOLE ->\r
traiter_action(Action, Reste, IP);\r
true ->\r
)))\r
end\r
).\r
- \r
+\r
\r
% Authentification d'un client.\r
traiter_action("authentification", JSON, IP) ->\r
% Un ekMaster débannie une ip.\r
traiter_action("unban", JSON, _) ->\r
euphorik_protocole:unban_ip(JSON).\r
-
\ No newline at end of file
bench_get_messages_avec_2_conversations/0
]).
-include("../include/euphorik_bd.hrl").
-\r
-% les intervalles en seconde min en max entre deux postes de message d'un utilisateur\r
-% le temps d'attente est choisi au hasard entre ces deux valeurs\r
--define(INTERVALLE_MIN, 2).\r
+
+% les intervalles en seconde min en max entre deux postes de message d'un utilisateur
+% le temps d'attente est choisi au hasard entre ces deux valeurs
+-define(INTERVALLE_MIN, 2).
-define(INTERVALLE_MAX, 5).
fun(Id) ->
timer:sleep(100),
spawn(
- fun() ->
- {A1, A2, A3} = now(),
+ fun() ->
+ {A1, A2, A3} = erlang:timestamp(),
random:seed(A1, A2, A3),
loop(Id, M)
end
end,
Ids
).
-
+
stop(Pids) ->
lists:foreach(fun(Pid) -> exit(Pid, kill) end, Pids).
-
+
% des trucs qui trainent
bench_get_messages() ->
T = [
moyenne_temps(Module, Fun, Args, N, Total, Temps_acc) ->
{Temps, _} = timer:tc(Module, Fun, Args),
moyenne_temps(Module, Fun, Args, N - 1, Total, Temps_acc + Temps).
-
-
+
+
% Crée N user avec des noms aléatoires et renvoie la liste des id.
creer_users(N) ->
creer_users(N, []).
message_rand() ->
lists:flatten(message_rand(random:uniform(10), [])).
message_rand(0, Mots) -> Mots;
-message_rand(N, Mots) ->
+message_rand(N, Mots) ->
message_rand(N - 1, [mot_rand(random:uniform(2) + 5), $ | Mots]).
mot_rand(0, Mot) -> Mot;
mot_rand(L, Mot) ->
mot_rand(L - 1, [random:uniform($z - $a + 1) + $a - 1 | Mot]).
-
+
% Tire au hasard de 0 à 3 messages sur les 10 derniers postés, renvoie une liste de int()
-% répartition :
+% répartition :
% 0 : 0.1
% 1 : 0.95
% 2 : 0.04
loop(User_id, 0) ->
io:format("~p a fini~n", [User_id]);
-loop(User_id, M) ->
+loop(User_id, M) ->
% attend un temp aléatoire compris entre INTERVALLE_MIN sec et INTERVALLE_MAX sec
timer:sleep(1000 * (random:uniform(?INTERVALLE_MAX - ?INTERVALLE_MIN + 1) + ?INTERVALLE_MIN - 1)),
% poste un message aléatoire par une personne aléatoire répondant à des messages aléatoires
{Message, Repond_a} = {message_rand(), messages_id_rand()},
- % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),
+ % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]),
case euphorik_bd:nouveau_message(Message, User_id, Repond_a) of
- {erreur, E} ->
+ {erreur, E} ->
io:format("~p : erreur : ~p~n", [User_id, E]),
loop(User_id, M);
_ ->
loop(User_id, M - 1)
end.
-
-
-% Permet de tester la vitesse d'écriture en fonction de la
+
+
+% Permet de tester la vitesse d'écriture en fonction de la
% taille de la BD
% voir : http://erlang.org/pipermail/erlang-questions/2008-October/038697.html
bench_write_minichat(Filename) ->
end,
Times
),
- file:close(File).
+ file:close(File).
bench_write_minichat(100000, Temps) -> Temps;
bench_write_minichat(N, Temps) ->
{T, _} = timer:tc(mnesia, transaction, [fun() ->
mnesia:write(#minichat{
id = Id,
auteur_id = random:uniform(10000),
- date = now(),
+ date = erlang:timestamp(),
pseudo = "Test",
contenu = "Blabla blabla bla.",
racine_id = random:uniform(10000)
})
end]),
bench_write_minichat(N + 1, if N rem 500 =:= 0 -> [{N, T} | Temps]; true -> Temps end).
-
-
-
\ No newline at end of file
+
+
key,
value
}).
-
-
+
+
% Mémorse toutes les propriétés, entre autre la version des données
-record(proprietes,
{
{
id, % integer
auteur_id, % -> #user.id
- date, % erlang:now()
+ date, % erlang:timestamp()
pseudo, % chaine de caractère
contenu, % chaine de caractère
racine_id = undefined, % la racine, par défaut correspond à l'id du message
status = normal % can be equal to normal, censored or deleted
}).
-
-
+
+
% type bag
% 'repondant' repond à 'cible'
-record(reponse_minichat,
{
repondant, % -> #minichat.id
cible % -> #minichat.id
- }).
+ }).
-record(profile, % attention : pas une table !
ostentatious_master = light, % peut valoir invisible, light ou heavy. seulement pour ek_master
chat_order = reverse, % peut valoir chrono ou reverse
conversations = [] % [{integer(), bool}], la liste des messages correspondant au conversation {racine, reduite?}
- }).\r
- \r
-
+ }).
+
+
-record(user,
{
id,
login = [], % string()
password = [], % string() (md5)
profile = #profile{},
- date_creation, % erlang:now()
- date_derniere_connexion, % erlang:now(), est mis à jour lors de n'importe quelle activitée (envoie de message par exemple)
+ date_creation, % erlang:timestamp()
+ date_derniere_connexion, % erlang:timestamp(), est mis à jour lors de n'importe quelle activitée (envoie de message par exemple)
indice_flood = 0, % integer() est incrémenté lorsque l'utilisateur envoie trop rapidement des messages.
ek_master = false,
last_ip = undefined % integer(), undefined si inconnu
date_last_try_register,
date_last_try_login % pour l'instant pas utilisé
}).
-
-
+
+
-record(troll,
{
id,
- id_user,\r
+ id_user,
id_minichat = undefined, % l'id du message associé
- date_create, % erlang:now()
- date_post = undefined, % date à laquelle le troll est affiché sur la page principale. undefined initialement puis erlang:now() quand affiché
+ date_create, % erlang:timestamp()
+ date_post = undefined, % date à laquelle le troll est affiché sur la page principale. undefined initialement puis erlang:timestamp() quand affiché
content % chaine de caractère
}).
-
\ No newline at end of file
<!-- encoding: utf-8 -->\r
\r
<h1>euphorik.ch</h1>\r
-<p>Version : <a href="http://dev.euphorik.ch/repositories/browse/euk/tags/1.1.5" class="version">1.1.5</a></p>\r
+<p>Version : <a href="http://dev.euphorik.ch/repositories/browse/euk/tags/1.1.6" class="version">1.1.6</a></p>\r
<p>Auteur : <a href="{EMAIL_LIEN}">GBurri</a></p>\r
\r
<h2>FAQ</h2>\r
# Classe permettant la vérification du code JS pas jslint.
# Passe en revu chaque fichier js de manière récursive à partir d'un dossier de départ.s
-class VerifJS
-
+class VerifJS
+
def initialize(dossier)
@dossier = dossier
end
-
+
def verifier
verifierRecur(@dossier)
end
-
+
def verifierRecur(dossier)
Dir.foreach(dossier){|fichier|
cheminComplet = "#{dossier}/#{fichier}"
end
elsif fichier[-3, 3] == '.js'
puts "== Vérification de #{cheminComplet} =="
- # TODO : mettre un if pour la version windows si dessous
+ # TODO : mettre un if pour la version windows si dessous
#system("java org.mozilla.javascript.tools.shell.Main jslint.js #{cheminComplet}")
system("rhino ./tools/jslint.js #{cheminComplet}")
# puts $?.exitstatus
end
# Classe de gestion de la version
-class Version
+class Version
# @param dossier la racine du site (par exemple "/var/www/euphorik")
def initialize(dossier)
@dossier = dossier
@fichiers = ['/pages/about.html']
@balise = /(<a.+?href=".*?\/tags\/).*?(".+?class.*?=.*?"version".*?>).*?(<\/a>)/
end
-
+
# met à jour la version dans les fichiers @fichiers
- def maj
+ def maj
@fichiers.each{|fichier|
fichier = @dossier + fichier
lines = IO.readlines(fichier)
lines.each{|l|
io.write(l.sub(@balise){|m| $1 + @version + $2 + @version + $3})
}
- }
+ }
}
end
end
# obsolète !
@@rep_remote = '/var/www/euphorik'
@@host = 'euphorik.ch'
-
+
def initialize(racine)
Dir.chdir(racine)
- end
-
+ end
+
# L'emplacement ou sont copié les fichiers
# A définir avant la mise en prod
def uri=(uri)
@uri = plop[0]
@rep = plop[1]
end
-
+
# Effectue la mise en production.
def miseEnProd
copierFichiers()
maj('yaws')
end
-
+
# Effectue la mise en préproduction.
def miseEnPreProd
copierFichiers()
lancerYaws()
maj('yaws_dev')
end
-
+
def copierFichiers
compiler_partie_serveuse()
creer_repertoire_bd()
copie_modules_serveurs()
set_droits_fichiers()
end
-
+
def lancerYaws
creer_rep("tools")
system("rsync tools/yaws.conf #{@uri}:#{@rep}/tools")
system("rsync tools/start_yaws.sh #{@uri}:#{@rep}/tools")
system("ssh #{@uri} \"cd #{@rep}/tools; screen -d -m -S yaws_dev ./start_yaws.sh\"")
end
-
+
def exec(commande)
system("ssh #{@uri} \"cd #{@rep} && #{commande}\"")
end
rescue
end
end
-
+
def compiler_partie_serveuse
log "compilation des modules serveur"
Dir.chdir('modules')
end
Dir.chdir('..')
end
-
- def creer_repertoire_bd
- log "création du répertoire de la base de données"
+
+ def creer_repertoire_bd
+ log "création du répertoire de la base de données"
# création du repertoire BD
creer_rep('BD')
creer_rep('BD/backups')
exec("chmod -R g+w BD")
end
-
+
# css, images, html, etc..
def copier_partie_statique
- log "copie de la partie statique"
+ log "copie de la partie statique"
uri = "#{@uri}:#{@rep}"
system("awk '$0 !~ /prod=\"delete\"/' index.yaws | ssh #{@uri} \" cat > #{@rep}/index.yaws\"")
system("rsync favicon.ico #{uri}")
system("rsync --delete -r pages #{uri}")
system("rsync --delete -r --exclude 'autres' img #{uri}")
end
-
+
# minification et package des fichiers js dans euphorik.js
def pack_js
- log "minification, assemblage et copie du javascript"
+ log "minification, assemblage et copie du javascript"
rep_js = 'js'
creer_rep(rep_js)
# jquery.js et euphorik.js doivent se trouve en premier
fichiers = ['js/libs/jquery.js', 'js/euphorik.js'].concat(get_fichiers_js(rep_js))
- commande_cat = "cat "
+ commande_cat = "cat "
fichiers.each{|f|
commande_cat += f + " "
}
#copie des js concaténés avec minification
- system("#{commande_cat} | tools/jsmin.rb | ssh #{@uri} \"cd #{@rep} && cat > #{rep_js}/euphorik.js\"")
+ # tools/jsmin.rb |
+ system("#{commande_cat} | ssh #{@uri} \"cd #{@rep} && cat > #{rep_js}/euphorik.js\"")
end
-
+
#renvoie une liste des fichiers js
def get_fichiers_js(rep)
fichiers = []
fichiers << fichier
end
end
- }
+ }
return fichiers
end
-
- def copie_modules_serveurs
- log "copie des modules du serveur"
+
+ def copie_modules_serveurs
+ log "copie des modules du serveur"
# copie des modules erlang
creer_rep('modules')
system("rsync -r --exclude 'euphorik_test.beam' modules/ebin #{@uri}:#{@rep}/modules")
system("rsync -r modules/include #{@uri}:#{@rep}/modules")
end
-
+
def set_droits_fichiers
- log "attribution des droits sur les fichiers"
+ log "attribution des droits sur les fichiers"
# attribution des droits
exec("chmod -R g+rx .")
end
-
+
# noeud : le nom du noeud sur lequel le script de mise en prod est exécuté
# Execute le script 'mise_en_prod.erl' sur le serveur afin de :
# - Recharger les modules
# - Mettre à jour la base de données
def maj(noeud)
- log "rechargement des modules serveur et mise à jour de la base de données"
+ log "rechargement des modules serveur et mise à jour de la base de données"
# execution du script de mise à jour
system("cat tools/mise_en_prod.erl | ssh #{@uri} \"cat > /tmp/mise_en_prod.erl\"")
system("ssh #{@uri} \"chmod u+x /tmp/mise_en_prod.erl; /tmp/mise_en_prod.erl #{noeud}; rm /tmp/mise_en_prod.erl\"")
end
-
+
def log(message)
puts "----- #{message} -----"
end
# Traite la ligne de commande lorsque tools.rb est utilisé comme tel
class Commande
- def initialize
+ def initialize
Dir.chdir("..")
@miseEnProd = MiseEnProd.new(".")
@verifJS = VerifJS.new("js")
@version = Version.new(".")
end
-
+
def traiter
if ARGV.size == 0
afficherUsage
return
end
-
+
case ARGV[0]
when 'prod'
@version.maj()
@version.maj()
end
end
-
+
def afficherUsage
puts "Usage : tools.rb (prod | pre | js | version)\n" +
" prod : Mise en production\n" +