Accueil > Forum > > > > code source java incompréhensible
code source java incompréhensible
mercredi 31 décembre 2008 à 15:05:40 |
code source java incompréhensible

samtanga
|
je suis étudiant en licence pro. Mon mémoire porte sur l'implémentation en java de l'algorithme RSA uin menbre m'a passé un code source correcte mais sans commentaire. si quelqu'un pourrait me commenter ce programme ligne par ligne. exemple que signifie BigInteger("1") ? comment le texte est il codé ? j'ai vérifier ce n'est pas en ASCII voici le code il s'exécute sur une page html import java.awt.*; import java.applet.*; import java.awt.event.*; import java.math.BigInteger; import java.util.Random; public class RSA extends java.applet.Applet implements ActionListener { Label pqLabel; Label pLabel; Label qLabel; Label generate_pq_sizeLabel; Label nLabel; Label nSpacer; Label eLabel; Label eSpacer; Label generate_e_sizeLabel; Label dLabel; Label dSpacer; Label useSpacer; Label convertButtonSpacer; Label cryptButtonSpacer; Label decryptButtonSpacer; Label decryptLabel; Button generate_pqButton; Button calculate_nButton; Button generate_eButton; Button calculate_dButton; Button convert_to_numberButton; Button convert_to_textButton; Button encryptButton; Button decryptButton; TextArea pTextArea; TextArea qTextArea; TextField generate_pq_sizeField; TextArea nTextArea; TextArea eTextArea; TextField generate_e_sizeField; TextArea dTextArea; TextArea plainTextArea; TextArea mTextArea; TextArea cTextArea; TextArea decryptTextArea; int prime_certainty = 20; public void init() { setLayout(new FlowLayout(1)); pqLabel = new Label("ENTRER DEUX NOMBRES PREMIERS P ET Q "); add(pqLabel); Panel pPanel = new Panel(); pLabel = new Label("P"); pPanel.add(pLabel); pTextArea = new TextArea("", 2, 50, 1); pPanel.add(pTextArea); add(pPanel); Panel qPanel = new Panel(); qLabel = new Label("Q"); qPanel.add(qLabel); qTextArea = new TextArea("", 2, 50, 1); qPanel.add(qTextArea); add(qPanel); Panel generate_pqPanel = new Panel(); generate_pqButton = new Button("VALEURS PAR DEFAUT"); generate_pqPanel.add(generate_pqButton); generate_pq_sizeLabel = new Label("ENTER AVERAGE BIT SIZE"); generate_pqPanel.add(generate_pq_sizeLabel); generate_pq_sizeField = new TextField("",5); generate_pqPanel.add(generate_pq_sizeField); add(generate_pqPanel); Panel nTextPanel = new Panel(); nLabel = new Label("N"); nTextPanel.add(nLabel); nTextArea = new TextArea("", 2, 50, 1); nTextPanel.add(nTextArea); add(nTextPanel); Panel nPanel = new Panel(); calculate_nButton = new Button("CALCULER N"); nPanel.add(calculate_nButton); nSpacer = new Label(" "); nPanel.add(nSpacer); add(nPanel); Panel eTextPanel = new Panel(); eLabel = new Label("CLE PUBLIQUE"); eTextPanel.add(eLabel); eTextArea = new TextArea("", 2, 50, 1); eTextPanel.add(eTextArea); add (eTextPanel); Panel ePanel = new Panel(); generate_eButton = new Button("GENERER LA CLE PUBLIQUE"); ePanel.add(generate_eButton); generate_e_sizeLabel = new Label("BIT LENGTH OF PUBLIC KEY"); ePanel.add(generate_e_sizeLabel); generate_e_sizeField = new TextField("", 5); ePanel.add(generate_e_sizeField); eSpacer = new Label(" "); ePanel.add(eSpacer); add(ePanel); Panel dTextPanel = new Panel(); dLabel = new Label("CLE PRIVEE"); dTextPanel.add(dLabel); dTextArea = new TextArea("", 2, 50, 1); dTextPanel.add(dTextArea); add(dTextPanel); Panel dPanel = new Panel(); calculate_dButton = new Button("GENERER LA CLE PRIVEE"); dPanel.add(calculate_dButton); dSpacer = new Label(" "); dPanel.add(dSpacer); add(dPanel); useSpacer = new Label(" ENTRER LE MESSAGE A CRYPTER "); add(useSpacer); plainTextArea = new TextArea("", 4, 54, 1); add(plainTextArea); Panel convertButtonPanel = new Panel(); convert_to_numberButton = new Button("REPRESENTATION NUMERIQUE"); convertButtonPanel.add(convert_to_numberButton); convertButtonSpacer = new Label(" "); convertButtonPanel.add(convertButtonSpacer); convert_to_textButton = new Button("TEXT REPRESENTATION"); convertButtonPanel.add(convert_to_textButton); add(convertButtonPanel); Panel cryptButtonPanel = new Panel(); encryptButton = new Button("CRYPTER") ; cryptButtonPanel.add(encryptButton); add(cryptButtonPanel); decryptButton = new Button("DECRYPTER") ; cryptButtonPanel.add(decryptButton); add(cryptButtonPanel); mTextArea = new TextArea("", 4, 54, 1); add(mTextArea); cTextArea = new TextArea("", 4, 54, 1); add(cTextArea); generate_pqButton.addActionListener(this); calculate_nButton.addActionListener(this); generate_eButton.addActionListener(this); calculate_dButton.addActionListener(this); convert_to_numberButton.addActionListener(this); convert_to_textButton.addActionListener(this); encryptButton.addActionListener(this); decryptButton.addActionListener(this); } public void actionPerformed(ActionEvent event) { if (event.getSource() == generate_pqButton) { int pq_size = new Integer(generate_pq_sizeField.getText()).intValue(); if (pq_size >= 4) { qTextArea.setText(new BigInteger(pq_size + 1, prime_certainty, new Random()).toString()); pTextArea.setText(new BigInteger(pq_size - 1, prime_certainty, new Random()).toString()); } else { pTextArea.setText("Enter larger p and q size."); } } else if (event.getSource() == calculate_nButton) { nTextArea.setText(calculate_n(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText())) .toString()); } else if (event.getSource() == generate_eButton) { eTextArea.setText(generate_e(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText()), new Integer(generate_e_sizeField.getText()).intValue()) .toString()); } else if (event.getSource() == calculate_dButton) { dTextArea.setText( calculate_d(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText()), new BigInteger(eTextArea.getText())) .toString()); } else if (event.getSource() == convert_to_numberButton) { mTextArea.setText(new BigInteger(plainTextArea.getText().getBytes()).toString()); } else if (event.getSource() == convert_to_textButton) { plainTextArea.setText(new String(new BigInteger(mTextArea.getText()).toByteArray())); } else if (event.getSource() == encryptButton) { cTextArea.setText(encrypt(new BigInteger(mTextArea.getText()), new BigInteger(eTextArea.getText()), new BigInteger(nTextArea.getText())).toString()); } else if (event.getSource() == decryptButton) { mTextArea.setText(decrypt(new BigInteger(cTextArea.getText()), new BigInteger(dTextArea.getText()), new BigInteger(nTextArea.getText())) .toString()); } } BigInteger generate_e(BigInteger p, BigInteger q, int bitsize) { BigInteger e, phi; e = new BigInteger("0"); phi = q.subtract(new BigInteger("1")); phi = phi.multiply(p.subtract(new BigInteger("1"))); int i = 0; do { e = (new BigInteger(bitsize, 0, new Random())).setBit(0); i = i + 1; } while( i<100 && (e.gcd(phi).compareTo(new BigInteger("1")) != 0)); return e; } BigInteger calculate_d(BigInteger p, BigInteger q, BigInteger e) { BigInteger d, phi; phi = q.subtract(new BigInteger("1")); phi = phi.multiply(p.subtract(new BigInteger("1"))); d = e.modInverse(phi); return d; } BigInteger calculate_n(BigInteger p, BigInteger q) { return p.multiply(q); } BigInteger encrypt(BigInteger m, BigInteger e, BigInteger n) { BigInteger c, bitmask; c = new BigInteger("0"); int i = 0; bitmask = (new BigInteger("2")).pow(n.bitLength()-1).subtract(new BigInteger("1")); while (m.compareTo(bitmask) == 1) { c = m.and(bitmask).modPow(e,n).shiftLeft(i*n.bitLength()).or(c); m = m.shiftRight(n.bitLength()-1); i = i+1; } c = m.modPow(e,n).shiftLeft(i*n.bitLength()).or(c); return c; } BigInteger decrypt(BigInteger c, BigInteger d, BigInteger n) { BigInteger m, bitmask; m = new BigInteger("0"); int i = 0; bitmask = (new BigInteger("2")).pow(n.bitLength()).subtract(new BigInteger("1")); while (c.compareTo(bitmask) == 1) { m = c.and(bitmask).modPow(d,n).shiftLeft(i*(n.bitLength()-1)).or(m); c = c.shiftRight(n.bitLength()); i = i+1; } m = c.modPow(d,n).shiftLeft(i*(n.bitLength()-1)).or(m); return m; } } ......................
|
|
samedi 3 janvier 2009 à 00:37:07 |
Re : code source java incompréhensible

POIVRONVERTBLEU
|
J'ai fait de mon mieux je connait pas bien les applets en java. Un reformatage du code aide beaucoup, pour ça j'ai utilisé eclipse. L'utilisation d'éclipse ou de netBeans permet d'afficher la documentation des classes java en temps réel. La structure de la classe me pique les yeux! pourquoi une classe unique il faudrait séparer les méthodes de la classe RSA , de la gestion de l'affichage.
import java.awt.*; import java.applet.*; import java.awt.event.*; import java.math.BigInteger; import java.util.Random;
public class RSA extends java.applet.Applet implements ActionListener { /* * Tous ces éléments sont destiné à l'interface graphique J'aurai * certainement pas procédé comme ça */ Label pqLabel; Label pLabel; Label qLabel; Label generate_pq_sizeLabel; Label nLabel; Label nSpacer; Label eLabel; Label eSpacer; Label generate_e_sizeLabel; Label dLabel; Label dSpacer; Label useSpacer; Label convertButtonSpacer; Label cryptButtonSpacer; Label decryptButtonSpacer; Label decryptLabel; Button generate_pqButton; Button calculate_nButton; Button generate_eButton; Button calculate_dButton; Button convert_to_numberButton; Button convert_to_textButton; Button encryptButton; Button decryptButton; TextArea pTextArea; TextArea qTextArea; TextField generate_pq_sizeField; TextArea nTextArea; TextArea eTextArea; TextField generate_e_sizeField; TextArea dTextArea; TextArea plainTextArea; TextArea mTextArea; TextArea cTextArea; TextArea decryptTextArea; int prime_certainty = 20;// il est d'usage de déclarer les champs statiques en majuscules
/* * équivalent au main dans les applets, on met en forme l'interface * graphique on attache des actions au éléments cliquables. (non-Javadoc) * * @see java.applet.Applet#init() */ public void init() {
setLayout(new FlowLayout(1)); // this.setSize(640, 480);//j'ai ajouté ça pour tester pqLabel = new Label("ENTRER DEUX NOMBRES PREMIERS P ET Q "); add(pqLabel); Panel pPanel = new Panel(); pLabel = new Label("P"); pPanel.add(pLabel); pTextArea = new TextArea("", 2, 50, 1); pPanel.add(pTextArea); add(pPanel); Panel qPanel = new Panel(); qLabel = new Label("Q"); qPanel.add(qLabel); qTextArea = new TextArea("", 2, 50, 1); qPanel.add(qTextArea); add(qPanel); Panel generate_pqPanel = new Panel(); generate_pqButton = new Button("VALEURS PAR DEFAUT"); generate_pqPanel.add(generate_pqButton); generate_pq_sizeLabel = new Label("ENTER AVERAGE BIT SIZE"); generate_pqPanel.add(generate_pq_sizeLabel); generate_pq_sizeField = new TextField("", 5); generate_pqPanel.add(generate_pq_sizeField); add(generate_pqPanel); Panel nTextPanel = new Panel(); nLabel = new Label("N"); nTextPanel.add(nLabel); nTextArea = new TextArea("", 2, 50, 1); nTextPanel.add(nTextArea); add(nTextPanel); Panel nPanel = new Panel(); calculate_nButton = new Button("CALCULER N"); nPanel.add(calculate_nButton); nSpacer = new Label(" "); nPanel.add(nSpacer); add(nPanel); Panel eTextPanel = new Panel(); eLabel = new Label("CLE PUBLIQUE"); eTextPanel.add(eLabel); eTextArea = new TextArea("", 2, 50, 1); eTextPanel.add(eTextArea); add(eTextPanel); Panel ePanel = new Panel(); generate_eButton = new Button("GENERER LA CLE PUBLIQUE"); ePanel.add(generate_eButton); generate_e_sizeLabel = new Label("BIT LENGTH OF PUBLIC KEY"); ePanel.add(generate_e_sizeLabel); generate_e_sizeField = new TextField("", 5); ePanel.add(generate_e_sizeField); eSpacer = new Label(" "); ePanel.add(eSpacer); add(ePanel); Panel dTextPanel = new Panel(); dLabel = new Label("CLE PRIVEE"); dTextPanel.add(dLabel); dTextArea = new TextArea("", 2, 50, 1); dTextPanel.add(dTextArea); add(dTextPanel); Panel dPanel = new Panel(); calculate_dButton = new Button("GENERER LA CLE PRIVEE"); dPanel.add(calculate_dButton); dSpacer = new Label(" "); dPanel.add(dSpacer); add(dPanel); useSpacer = new Label(" ENTRER LE MESSAGE A CRYPTER "); add(useSpacer); plainTextArea = new TextArea("", 4, 54, 1); add(plainTextArea); Panel convertButtonPanel = new Panel(); convert_to_numberButton = new Button("REPRESENTATION NUMERIQUE"); convertButtonPanel.add(convert_to_numberButton); convertButtonSpacer = new Label(" "); convertButtonPanel.add(convertButtonSpacer); convert_to_textButton = new Button("TEXT REPRESENTATION"); convertButtonPanel.add(convert_to_textButton); add(convertButtonPanel); Panel cryptButtonPanel = new Panel(); encryptButton = new Button("CRYPTER"); cryptButtonPanel.add(encryptButton); add(cryptButtonPanel); decryptButton = new Button("DECRYPTER"); cryptButtonPanel.add(decryptButton); add(cryptButtonPanel); mTextArea = new TextArea("", 4, 54, 1); add(mTextArea); cTextArea = new TextArea("", 4, 54, 1); add(cTextArea); /* * On attache un écouteur d'action à chaque éléments */ generate_pqButton.addActionListener(this); calculate_nButton.addActionListener(this); generate_eButton.addActionListener(this); calculate_dButton.addActionListener(this); convert_to_numberButton.addActionListener(this); convert_to_textButton.addActionListener(this); encryptButton.addActionListener(this); decryptButton.addActionListener(this); }
/* * cette méthode est obligatoire dès qu'on implémente ActionListener elle * permet d'appeler une méthode en fonction de l'évènement qui survient */ public void actionPerformed(ActionEvent event) { if (event.getSource() == generate_pqButton) { int pq_size = new Integer(generate_pq_sizeField.getText()) .intValue(); if (pq_size >= 4) { qTextArea.setText(new BigInteger(pq_size + 1, prime_certainty, new Random()).toString()); pTextArea.setText(new BigInteger(pq_size - 1, prime_certainty, new Random()).toString()); } else { pTextArea.setText("Enter larger p and q size."); } } else if (event.getSource() == calculate_nButton) { nTextArea.setText(calculate_n(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText())).toString()); } else if (event.getSource() == generate_eButton) { eTextArea.setText(generate_e(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText()), new Integer(generate_e_sizeField.getText()).intValue()) .toString()); } else if (event.getSource() == calculate_dButton) { dTextArea.setText(calculate_d(new BigInteger(pTextArea.getText()), new BigInteger(qTextArea.getText()), new BigInteger(eTextArea.getText())).toString()); } else if (event.getSource() == convert_to_numberButton) { mTextArea .setText(new BigInteger(plainTextArea.getText().getBytes()) .toString()); } else if (event.getSource() == convert_to_textButton) { plainTextArea.setText(new String( new BigInteger(mTextArea.getText()).toByteArray())); } else if (event.getSource() == encryptButton) { cTextArea.setText(encrypt(new BigInteger(mTextArea.getText()), new BigInteger(eTextArea.getText()), new BigInteger(nTextArea.getText())).toString()); } else if (event.getSource() == decryptButton) { mTextArea.setText(decrypt(new BigInteger(cTextArea.getText()), new BigInteger(dTextArea.getText()), new BigInteger(nTextArea.getText())).toString()); } }
BigInteger generate_e(BigInteger p, BigInteger q, int bitsize) { BigInteger e, phi; e = new BigInteger("0"); /* BigInteger est une classe qui permet de travailler sur des * entiers longs. * l'un des constructeur de BigInteger permet de créer un entier long à * partir d'une chaine de caractère ' new BigInteger("1")' */ phi = q.subtract(new BigInteger("1")); /* * comme la classe BigInteger ne peut pas surchager les oppérateur binaires * ( + - * /) on utilise des méthodes comme "subtract(BigInteger)" */ phi = phi.multiply(p.subtract(new BigInteger("1"))); int i = 0; do { e = (new BigInteger(bitsize, 0, new Random())).setBit(0); i = i + 1; } while (i < 100 && (e.gcd(phi).compareTo(new BigInteger("1")) != 0)); return e; }
BigInteger calculate_d(BigInteger p, BigInteger q, BigInteger e) { BigInteger d, phi; phi = q.subtract(new BigInteger("1")); phi = phi.multiply(p.subtract(new BigInteger("1"))); d = e.modInverse(phi); return d; }
BigInteger calculate_n(BigInteger p, BigInteger q) { return p.multiply(q); }
BigInteger encrypt(BigInteger m, BigInteger e, BigInteger n) { BigInteger c, bitmask; c = new BigInteger("0"); int i = 0; bitmask = (new BigInteger("2")).pow(n.bitLength() - 1).subtract( new BigInteger("1")); while (m.compareTo(bitmask) == 1) { c = m.and(bitmask).modPow(e, n).shiftLeft(i * n.bitLength()).or(c); m = m.shiftRight(n.bitLength() - 1); i = i + 1; } c = m.modPow(e, n).shiftLeft(i * n.bitLength()).or(c); return c; }
BigInteger decrypt(BigInteger c, BigInteger d, BigInteger n) { BigInteger m, bitmask; m = new BigInteger("0"); int i = 0; bitmask = (new BigInteger("2")).pow(n.bitLength()).subtract( new BigInteger("1")); while (c.compareTo(bitmask) == 1) { m = c.and(bitmask).modPow(d, n).shiftLeft(i * (n.bitLength() - 1)) .or(m); c = c.shiftRight(n.bitLength()); i = i + 1; } m = c.modPow(d, n).shiftLeft(i * (n.bitLength() - 1)).or(m); return m; } } pvb
|
|
Cette discussion est classée dans : label, add, panel, biginteger, generate
Répondre à ce message
Sujets en rapport avec ce message
imprime trop gros [ par jackhabbot ]
Bonjour à tous,je souhaite imprimer le contenu d'une fenêtre à une certaine échelle, car pour le moment lorsque j'imprime, c'est environ 2 fois plus g
Fermer une fenêtre2 [ par EvilGost ]
en fait, ce n'est pas une JFrame, voici le code:import java.awt.*;import java.io.*;public class DivxFrame extends Frame{ public DivxFrame
problèmes graphiques(débutant) [ par guilouis ]
bonjour à tous, je suis nouveau sur ce forum et j'ai pas mal de difficultés en java avec lequel je débute...je vous joins dans la suite de mon message
apparition de Panel (un coup ça marche, un coup non) [ par guilouis ]
bonjour à tousvoilà, j'ai un programme qui est censé faire apparaitre un panel ou un autre(au meme endroit..) selon le choix...mon probleme c que ce p
Container Component [ par anzize ]
Bonjour tout le monde !J'ai un le problème suivant :JPanel panel=new JPanel();JButton buton1=new JButton("1");JButton buton2=new JButton("2");panel.ad
scrollpane et panel :) [ par Ricool ]
Bonjourj'ai un petit probleme de mise en page d'une jdialogen effet, dans celle ci je dois faire apparaitre le contenu d'un fichier text represnetant
JPanel et JFrame [ par chtiBout ]
salut tout le monde ! je dois développer un Jframe avec dedans des panel dc je fais une classe panel ds laquelle je décris mes panel et ds le main je
Probleme de refresh d'une applet [ par fabgog ]
Bonjour à tous,Voila je viens de concevoir une applet qui est un editeur de textelors du premiere affichage de la page tout est corect, mais lorsque j
visualiser une application après compilation [ par Mentag ]
Bonjour à tousJ'ai écrit une application (en java : j2sdk1.4.2_07), j'ai eu le succés de compilation ,j'ai bien un autre fichier Sondage .classmais co
probleme de calcul en JAVA [ par oceane751 ]
bonjour à tous!!voila comme le dit le sujet, je rencontre un problee lorsque je veux faire l'addition du prix dun "melon" et celui dune "salade"en eff
Livres en rapport
|
Derniers Blogs
GESTION D'EXCEPTION AVEC LES TASKSGESTION D'EXCEPTION AVEC LES TASKS par richardc
Nous avons vu dans un précédent article comment utiliser Task pour effectuer des opérations dans un autre thread.
Malheureusement, comme tout le monde n'est pas parfait, il se peut que cette exécution se passe mal et qu'une exception se produise.
La...
Cliquez pour lire la suite de l'article par richardc DéMARRONS AVEC LES TASKSDéMARRONS AVEC LES TASKS par richardc
Que vous le vouliez ou non, le développement multi-tâche est maintenant une obligation pour toute nouvelle application. Il est donc vital d'en comprendre les mécanismes et de s'y mettre le plus tôt possible.
En attendant le .NET Framework 4.5 avec le...
Cliquez pour lire la suite de l'article par richardc SLIDE & DéMO TECHDAYS 2012 - FAST & FURIOUS XAML APPSSLIDE & DéMO TECHDAYS 2012 - FAST & FURIOUS XAML APPS par Vko
Retrouvez les slides et les démo de ma session Fast & Furious XAML Apps. A ceux qui se posent la question : "est-ce que le code de la DataGrid est disponible?", je vous répondrais "pas encore". Je vais mettre en place un projet codeplex pour part...
Cliquez pour lire la suite de l'article par Vko XNA IS DEAD!XNA IS DEAD! par richardc
Depuis la semaine dernière (et grâce aux TechDays 2012), je me penche activement sur la nouvelle version de Windows, aka Windows 8. Vous me direz, il était temps puisque la première preview date de Septembre dernier.
OK. Remarquez, on n'en est qu'aux...
Cliquez pour lire la suite de l'article par richardc TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 !TECHDAYS PARIS 2012 : WINDOWS SERVER "8" QUOI DE 9 ! par ROMELARD Fabrice
Speakers: Fabrice Meillon et Stanislas Quastana Cette session est basée entièrement sur celle donnée lors de la BUILD cet hiver. Il n'y a pas d'ajout d'information en rapport avec cet évènement passé. Windows 8 Server sera intégralem...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Forum
RE : COURRE : COUR par barhoum1111
Cliquez pour lire la suite par barhoum1111 RE : COURRE : COUR par Julien39
Cliquez pour lire la suite par Julien39
Logiciels
DocTranslate (V3.1.0.0)DOCTRANSLATE (V3.1.0.0)DocTranslate est un traducteur de document Microsoft Word, PowerPoint et Excel. Il permet d'autom... Cliquez pour télécharger DocTranslate Tribler (2012)TRIBLER (2012)Tribler est un client pair à pair (P2P/Peer-to-Peer) open source avec la capacité de regarder des... Cliquez pour télécharger Tribler OneSwarm (2012)ONESWARM (2012)Le peer-to-peer qui protège votre vie privée, c'est OneSwarm.
Ce logiciel de peer-to-peer crypté... Cliquez pour télécharger OneSwarm PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO (V8.4)PONAMEDIA TV DEVIENS HELLLOOO FLASH
LA TV SUR VOTRE ORDINATEUR.
Toute une plateforme Multi... Cliquez pour télécharger PONAMEDIA PREMIUM - HELLLOOO FLASH DEMO Academy System (17.2.1.0)ACADEMY SYSTEM (17.2.1.0)Logiciel de gestion des établissements.
- élèves/étudiants (inscription, dossier, absence...)
-... Cliquez pour télécharger Academy System
|