/src/jd/captcha/JAntiCaptcha.java
Java | 2022 lines | 1479 code | 249 blank | 294 comment | 391 complexity | c7b1cfed3d209b39158660b898c3aa15 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1// jDownloader - Downloadmanager 2// Copyright (C) 2008 JD-Team support@jdownloader.org 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// This program is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17package jd.captcha; 18 19import java.awt.Color; 20import java.awt.Graphics; 21import java.awt.GridBagLayout; 22import java.awt.GridLayout; 23import java.awt.Image; 24import java.awt.event.ActionEvent; 25import java.awt.event.ActionListener; 26import java.awt.image.BufferedImage; 27import java.io.File; 28import java.io.FileFilter; 29import java.io.IOException; 30import java.lang.reflect.Method; 31import java.util.ArrayList; 32import java.util.Collections; 33import java.util.Comparator; 34import java.util.ListIterator; 35import java.util.Vector; 36import java.util.logging.Logger; 37 38import javax.imageio.ImageIO; 39import javax.swing.ImageIcon; 40import javax.swing.JButton; 41import javax.swing.JCheckBox; 42import javax.swing.JDialog; 43import javax.swing.JFrame; 44import javax.swing.JLabel; 45import javax.swing.JOptionPane; 46import javax.swing.JPanel; 47import javax.swing.JScrollPane; 48import javax.swing.JTextArea; 49 50import jd.captcha.configuration.JACScript; 51import jd.captcha.gui.BasicWindow; 52import jd.captcha.gui.ImageComponent; 53import jd.captcha.gui.ScrollPaneWindow; 54import jd.captcha.pixelgrid.Captcha; 55import jd.captcha.pixelgrid.Letter; 56import jd.captcha.utils.Utilities; 57import jd.controlling.JDLogger; 58import jd.gui.userio.DummyFrame; 59import jd.http.Browser; 60import jd.nutils.Executer; 61import jd.nutils.JDHash; 62import jd.nutils.io.JDIO; 63import jd.utils.JDUtilities; 64 65import org.appwork.utils.Regex; 66import org.appwork.utils.os.CrossSystem; 67import org.w3c.dom.Document; 68import org.w3c.dom.Element; 69import org.w3c.dom.NamedNodeMap; 70import org.w3c.dom.Node; 71import org.w3c.dom.NodeList; 72 73/** 74 * Diese Klasse stellt alle public Methoden zur captcha Erkennung zur Verfügung. 75 * Sie verküpft Letter und captcha Klassen. Gleichzeitig dient sie als 76 * Parameter-Dump. 77 * 78 * @author JD-Team 79 */ 80public class JAntiCaptcha { 81 82 /** 83 * Logger 84 */ 85 private static Logger logger = Utilities.getLogger(); 86 87 /** 88 * Testet die Angegebene Methode. Dabei werden analysebilder erstellt. 89 * 90 * @param file 91 */ 92 public static void testMethod(File file) { 93 int checkCaptchas = 20; 94 String code; 95 String inputCode; 96 int totalLetters = 0; 97 int correctLetters = 0; 98 File captchaFile; 99 Image img; 100 String methodName = file.getName(); 101 File captchaDir = new File(file.getAbsolutePath() + "/captchas"); 102 if (Utilities.isLoggerActive()) { 103 logger.info("Test Method: " + methodName); 104 } 105 new JAntiCaptcha(methodName); 106 File[] entries = captchaDir.listFiles(new FileFilter() { 107 public boolean accept(File pathname) { 108 // if(Utilities.isLoggerActive())logger.info(pathname.getName( 109 // )); 110 if (pathname.getName().endsWith(".jpg") || pathname.getName().endsWith(".png") || pathname.getName().endsWith(".gif")) { 111 112 return true; 113 } else { 114 return false; 115 } 116 } 117 118 }); 119 ScrollPaneWindow w = new ScrollPaneWindow(); 120 w.setTitle(" Test Captchas: " + file.getAbsolutePath()); 121 122 w.resizeWindow(100); 123 if (Utilities.isLoggerActive()) { 124 logger.info("Found Testcaptchas: " + entries.length); 125 } 126 int testNum = Math.min(checkCaptchas, entries.length); 127 if (Utilities.isLoggerActive()) { 128 logger.info("Test " + testNum + " Captchas"); 129 } 130 int i = 0; 131 for (i = 0; i < testNum; i++) { 132 captchaFile = entries[(int) (Math.random() * entries.length)]; 133 134 logger.info("JJJJJJJJ" + captchaFile); 135 img = Utilities.loadImage(captchaFile); 136 w.setText(0, i, captchaFile.getName()); 137 w.setImage(1, i, img); 138 139 w.repack(); 140 141 JAntiCaptcha jac = new JAntiCaptcha(methodName); 142 // BasicWindow.showImage(img); 143 Captcha cap = jac.createCaptcha(img); 144 if (cap == null) { 145 if (Utilities.isLoggerActive()) { 146 logger.severe("Captcha Bild konnte nicht eingelesen werden"); 147 } 148 continue; 149 } 150 151 w.setImage(2, i, cap.getImage()); 152 // BasicWindow.showImage(cap.getImageWithGaps(2)); 153 code = jac.checkCaptcha(captchaFile, cap); 154 w.setImage(3, i, cap.getImage()); 155 156 w.setText(4, i, "JAC:" + code); 157 158 w.repack(); 159 160 inputCode = JOptionPane.showInputDialog("Bitte Captcha Code eingeben", code); 161 162 w.setText(5, i, "User:" + inputCode); 163 w.repack(); 164 if (code == null) { 165 code = ""; 166 } 167 if (inputCode == null) { 168 inputCode = ""; 169 } 170 code = code.toLowerCase(); 171 inputCode = inputCode.toLowerCase(); 172 for (int x = 0; x < inputCode.length(); x++) { 173 totalLetters++; 174 175 if (inputCode.length() == code.length() && inputCode.charAt(x) == code.charAt(x)) { 176 correctLetters++; 177 } 178 } 179 if (Utilities.isLoggerActive()) { 180 logger.info("Erkennung: " + correctLetters + "/" + totalLetters + " = " + Utilities.getPercent(correctLetters, totalLetters) + "%"); 181 } 182 } 183 w.setText(0, i + 1, "Erkennung: " + Utilities.getPercent(correctLetters, totalLetters) + "%"); 184 w.setText(4, i + 1, "Richtig: " + correctLetters); 185 w.setText(5, i + 1, "Falsch: " + (totalLetters - correctLetters)); 186 JOptionPane.showMessageDialog(new JFrame(), "Erkennung: " + correctLetters + "/" + totalLetters + " = " + Utilities.getPercent(correctLetters, totalLetters) + "%"); 187 } 188 189 /** 190 * Führt einen Testlauf mit den übergebenen Methoden durch 191 * 192 * @param methods 193 */ 194 public static void testMethods(File[] methods) { 195 for (File element : methods) { 196 JAntiCaptcha.testMethod(element); 197 } 198 199 } 200 201 /** 202 * Fenster die eigentlich nur zur Entwicklung sind um Basic GUI Elemente zu 203 * haben 204 */ 205 private BasicWindow bw2; 206 207 private BasicWindow bw3; 208 209 private JDialog f; 210 211 /** 212 * Bildtyp. Falls dieser von jpg unterschiedlich ist, muss zuerst 213 * konvertiert werden. 214 */ 215 private String imageType; 216 217 /** 218 * jas Script Instanz. Sie verarbneitet das JACScript und speichert die 219 * Parameter 220 */ 221 public JACScript jas; 222 /** 223 * Vector mit den Buchstaben aus der MTHO File 224 */ 225 public ArrayList<Letter> letterDB; 226 227 private int[][] letterMap = null; 228 229 /** 230 * Anzahl der Buchstaben im Captcha. Wird aus der jacinfo.xml gelesen 231 */ 232 private int letterNum; 233 234 /** 235 * ordnername der methode 236 */ 237 private String methodDirName; 238 239 private boolean showDebugGui = false; 240 241 private Vector<ScrollPaneWindow> spw = new Vector<ScrollPaneWindow>(); 242 243 private Captcha workingCaptcha; 244 245 private boolean extern; 246 247 public boolean isExtern() { 248 return extern; 249 } 250 251 private String command; 252 253 private String dstFile; 254 255 private String srcFile; 256 257 private Image sourceImage; 258 259 public JAntiCaptcha(String methodName) { 260 JACMethod method = JACMethod.forServiceName(methodName); 261 if (method == null) { 262 logger.severe("no such method found! " + methodName); 263 return; 264 } 265 methodDirName = method.getFileName(); 266 267 getJACInfo(); 268 269 jas = new JACScript(this, methodDirName); 270 long time = System.currentTimeMillis(); 271 loadMTHFile(); 272 273 time = System.currentTimeMillis() - time; 274 System.out.println(time); 275 if (Utilities.isLoggerActive()) { 276 logger.fine("letter DB loaded: Buchstaben: " + letterDB.size()); 277 } 278 } 279 280 /** 281 * prüft den übergebenen Captcha und gibt den Code als String zurück. Das 282 * lettersarray des Catchas wird dabei bearbeitet. Es werden decoedvalue, 283 * avlityvalue und parent gesetzt WICHTIG: Nach dem Decoden eines Captcha 284 * herrscht Verwirrung. Es stehen unterschiedliche Methoden zur Verfügung um 285 * an bestimmte Informationen zu kommen: captcha.getDecodedLetters() gibt 286 * Die letter aus der datenbank zurück. Deren werte sind nicht fest. Auf den 287 * Wert von getvalityvalue und getValityPercent kann man sich absolut nicht 288 * verlassen. Einzig getDecodedValue() lässt sich zuverlässig auslesen 289 * captcha.getLetters() gibt die Wirklichen Letter des captchas zurück. Hier 290 * lassen sich alle wichtigen Infos abfragen. z.B. ValityValue, 291 * ValityPercent, Decodedvalue, etc. Wer immer das hier liest sollte auf 292 * keinen fall den fehler machen und sich auf Wert aus dem getdecodedLetters 293 * array verlassen 294 * 295 * @param captcha 296 * Captcha instanz 297 * @return CaptchaCode 298 */ 299 public String checkCaptcha(File file, Captcha captcha) { 300 if (extern) return callExtern(); 301 workingCaptcha = captcha; 302 // Führe prepare aus 303 jas.executePrepareCommands(file, captcha); 304 Letter[] letters = captcha.getLetters(getLetterNum()); 305 if (letters == null) { 306 captcha.setValityPercent(100.0); 307 if (Utilities.isLoggerActive()) { 308 logger.severe("Captcha konnte nicht erkannt werden!"); 309 } 310 return null; 311 } 312 String ret = ""; 313 double correct = 0; 314 LetterComperator akt; 315 316 // Scannen 317 Vector<LetterComperator> newLettersVector = new Vector<LetterComperator>(); 318 for (int i = 0; i < letters.length; i++) { 319 letters[i].setId(i); 320 if (letters[i].detected != null) { 321 akt = letters[i].detected; 322 } else { 323 akt = getLetter(letters[i]); 324 } 325 akt.getA().setId(i); 326 327 newLettersVector.add(akt); 328 329 } 330 if (letters.length > getLetterNum()) { 331 // sortieren 332 Collections.sort(newLettersVector, new Comparator<LetterComperator>() { 333 public int compare(LetterComperator obj1, LetterComperator obj2) { 334 335 if (obj1.getValityPercent() < obj2.getValityPercent()) { return -1; } 336 if (obj1.getValityPercent() > obj2.getValityPercent()) { return 1; } 337 return 0; 338 } 339 }); 340 341 // schlechte entfernen 342 if (Utilities.isLoggerActive()) { 343 logger.info(getLetterNum() + ""); 344 } 345 346 if (!jas.getBoolean("autoLetterNum")) { 347 for (int i = newLettersVector.size() - 1; i >= getLetterNum(); i--) { 348 newLettersVector.remove(i); 349 } 350 } 351 // Wieder in die richtige reihenfolge sortieren 352 Collections.sort(newLettersVector, new Comparator<LetterComperator>() { 353 public int compare(LetterComperator obj1, LetterComperator obj2) { 354 355 if (obj1.getA().getId() < obj2.getA().getId()) { return -1; } 356 if (obj1.getA().getId() > obj2.getA().getId()) { return 1; } 357 return 0; 358 } 359 }); 360 } 361 362 if (getJas().getString("useLettercomparatorFilter") != null && getJas().getString("useLettercomparatorFilter").length() > 0) { 363 String[] ref = getJas().getString("useLettercomparatorFilter").split("\\."); 364 if (ref.length != 2) { 365 captcha.setValityPercent(100.0); 366 if (Utilities.isLoggerActive()) { 367 logger.severe("useLettercomparatorFilter should have the format Class.Method"); 368 } 369 return null; 370 } 371 String cl = ref[0]; 372 String methodname = ref[1]; 373 374 Class<?> newClass; 375 try { 376 newClass = Class.forName("jd.captcha.specials." + cl); 377 378 Class<?>[] parameterTypes = new Class[] { newLettersVector.getClass(), this.getClass() }; 379 Method method = newClass.getMethod(methodname, parameterTypes); 380 Object[] arguments = new Object[] { newLettersVector, this }; 381 Object instance = null; 382 method.invoke(instance, arguments); 383 384 } catch (Exception e) { 385 if (Utilities.isLoggerActive()) { 386 logger.severe("Fehler in useLettercomparatorFilter:" + e.getLocalizedMessage() + " / " + getJas().getString("useLettercomparatorFilter")); 387 } 388 JDLogger.exception(e); 389 } 390 391 } 392 for (int i = 0; i < newLettersVector.size(); i++) { 393 akt = newLettersVector.get(i); 394 395 if (akt == null || akt.getValityPercent() >= 100.0) { 396 ret += "-"; 397 correct += 100.0; 398 } else { 399 ret += akt.getDecodedValue(); 400 401 akt.getA().setId(i); 402 correct += akt.getValityPercent(); 403 404 } 405 // if(Utilities.isLoggerActive())logger.finer("Validty: " + 406 // correct); 407 } 408 if (newLettersVector.size() == 0) { 409 captcha.setValityPercent(100.0); 410 411 return null; 412 } 413 captcha.setLetterComperators(newLettersVector.toArray(new LetterComperator[] {})); 414 415 if (Utilities.isLoggerActive()) { 416 logger.finer("Vality: " + (int) (correct / newLettersVector.size())); 417 } 418 captcha.setValityPercent(correct / newLettersVector.size()); 419 return ret; 420 } 421 422 /** 423 * Exportiert die aktelle Datenbank als PNG einzelbilder 424 */ 425 public void exportDB() { 426 File path = Utilities.directoryChooser(); 427 428 File file; 429 BufferedImage img; 430 int i = 0; 431 for (Letter letter : letterDB) { 432 433 img = letter.getFullImage(); 434 file = new File(path + "/letterDB/" + i++ + "_" + letter.getDecodedValue() + ".png"); 435 file.mkdirs(); 436 437 try { 438 logger.info("Write Db: " + file); 439 ImageIO.write(img, "png", file); 440 } catch (IOException e) { 441 JDLogger.exception(e); 442 } 443 } 444 } 445 446 private BufferedImage toBufferedImage(Image i) { 447 if (i instanceof BufferedImage) { return (BufferedImage) i; } 448 Image img; 449 img = new ImageIcon(i).getImage(); 450 BufferedImage b; 451 b = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB); 452 Graphics g = b.createGraphics(); 453 g.drawImage(img, 0, 0, null); 454 g.dispose(); 455 return b; 456 } 457 458 private String callExtern() { 459 try { 460 File file = JDUtilities.getResourceFile(this.srcFile); 461 file.getParentFile().mkdirs(); 462 String ext = CrossSystem.getFileExtension(file.getName()); 463 ImageIO.write(toBufferedImage(this.sourceImage), ext, file); 464 } catch (Exception e) { 465 JDLogger.exception(e); 466 return null; 467 } 468 Executer exec = new Executer(JDUtilities.getResourceFile(this.command).getAbsolutePath()); 469 exec.setRunin(JDUtilities.getResourceFile(this.command).getParent()); 470 exec.setWaitTimeout(30); 471 exec.start(); 472 exec.waitTimeout(); 473 // String ret = exec.getOutputStream() + " \r\n " + 474 // exec.getErrorStream(); 475 476 String res = JDIO.readFileToString(JDUtilities.getResourceFile(this.dstFile)); 477 if (res == null) return null; 478 return res.trim(); 479 480 } 481 482 /** 483 * Gibt den erkannten CaptchaText zurück 484 * 485 * @param captchafile 486 * Pfad zum Bild 487 * @return CaptchaCode 488 */ 489 public String checkCaptcha(File captchafile) { 490 if (Utilities.isLoggerActive()) { 491 logger.finer("check " + captchafile); 492 } 493 Image captchaImage = Utilities.loadImage(captchafile); 494 Captcha captcha = createCaptcha(captchaImage); 495 if (captcha != null) captcha.setCaptchaFile(captchafile); 496 // captcha.printCaptcha(); 497 return checkCaptcha(captchafile, captcha); 498 } 499 500 /** 501 * Factory Methode zur Captcha erstellung 502 * 503 * @param captchaImage 504 * Image instanz 505 * @return captcha 506 */ 507 public Captcha createCaptcha(Image captchaImage) { 508 this.sourceImage = captchaImage; 509 if (extern) return null; 510 if (captchaImage.getWidth(null) <= 0 || captchaImage.getHeight(null) <= 0) { 511 if (Utilities.isLoggerActive()) { 512 logger.severe("Image Dimensionen zu klein. Image hat keinen Inahlt. Pfad/Url prüfen!"); 513 } 514 return null; 515 } 516 Captcha ret = Captcha.getCaptcha(captchaImage, this); 517 if (ret == null) { return null; } 518 ret.setOwner(this); 519 return ret; 520 } 521 522 /** 523 * Aus gründen der geschwindigkeit wird die MTH XMl in einen vector 524 * umgewandelt 525 */ 526 private void createLetterDBFormMTH(Document mth) { 527 letterDB = new ArrayList<Letter>(); 528 long start1 = System.currentTimeMillis(); 529 try { 530 531 if (mth == null || mth.getFirstChild() == null) { return; } 532 NodeList nl = mth.getFirstChild().getChildNodes(); 533 Letter tmp; 534 for (int i = 0; i < nl.getLength(); i++) { 535 // Get child node 536 Node childNode = nl.item(i); 537 if (childNode.getNodeName().equals("letter")) { 538 NamedNodeMap att = childNode.getAttributes(); 539 540 tmp = new Letter(); 541 tmp.setOwner(this); 542 String id = JDUtilities.getAttribute(childNode, "id"); 543 if (!tmp.setTextGrid(childNode.getTextContent())) { 544 545 logger.severe("Error in Letters DB line: " + i + ":" + childNode.getTextContent() + " id:" + id); 546 continue; 547 } 548 549 if (id != null) { 550 tmp.setId(Integer.parseInt(id)); 551 } 552 tmp.setSourcehash(att.getNamedItem("captchaHash").getNodeValue()); 553 tmp.setDecodedValue(att.getNamedItem("value").getNodeValue()); 554 tmp.setBadDetections(Integer.parseInt(JDUtilities.getAttribute(childNode, "bad"))); 555 tmp.setGoodDetections(Integer.parseInt(JDUtilities.getAttribute(childNode, "good"))); 556 letterDB.add(tmp); 557 } else if (childNode.getNodeName().equals("map")) { 558 if (Utilities.isLoggerActive()) { 559 logger.fine("Parse LetterMap"); 560 } 561 long start2 = System.currentTimeMillis(); 562 String[] map = childNode.getTextContent().split("\\|"); 563 letterMap = new int[map.length][map.length]; 564 for (int x = 0; x < map.length; x++) { 565 String[] row = map[x].split("\\,"); 566 for (int y = 0; y < map.length; y++) { 567 letterMap[x][y] = Integer.parseInt(row[y]); 568 } 569 570 } 571 if (Utilities.isLoggerActive()) { 572 logger.fine("LetterMap Parsing time: " + (System.currentTimeMillis() - start2)); 573 } 574 } 575 } 576 } catch (Exception e) { 577 JDLogger.exception(e); 578 if (Utilities.isLoggerActive()) { 579 logger.severe("Fehler bein lesen der MTH Datei!!. Methode kann nicht funktionieren!"); 580 } 581 582 } 583 if (Utilities.isLoggerActive()) { 584 logger.fine("Mth Parsing time: " + (System.currentTimeMillis() - start1)); 585 } 586 } 587 588 /** 589 * Diese methode trainiert einen captcha 590 * 591 * @param captchafile 592 * File zum Bild 593 * @param letterNum 594 * Anzahl der Buchstaben im captcha 595 * @return int -1: Übersprungen Sonst: anzahl der richtig erkanten Letter 596 */ 597 598 private Document createXMLFromLetterDB() { 599 Document xml = JDUtilities.parseXmlString("<jDownloader></jDownloader>", false); 600 if (letterMap != null) { 601 Element element = xml.createElement("map"); 602 xml.getFirstChild().appendChild(element); 603 element.appendChild(xml.createTextNode(getLetterMapString())); 604 } 605 606 int i = 0; 607 for (Letter letter : letterDB) { 608 Element element = xml.createElement("letter"); 609 xml.getFirstChild().appendChild(element); 610 element.appendChild(xml.createTextNode(letter.getPixelString())); 611 element.setAttribute("id", i++ + ""); 612 element.setAttribute("value", letter.getDecodedValue()); 613 element.setAttribute("captchaHash", letter.getSourcehash()); 614 element.setAttribute("good", letter.getGoodDetections() + ""); 615 element.setAttribute("bad", letter.getBadDetections() + ""); 616 617 } 618 return xml; 619 620 } 621 622 private void destroyScrollPaneWindows() { 623 while (spw.size() > 0) { 624 spw.remove(0).destroy(); 625 } 626 } 627 628 /** 629 * Zeigt die Momentane Library an. Buchstaben können gelöscht werden 630 */ 631 public void displayLibrary() { 632 if (letterDB == null || letterDB.size() == 0) { return; } 633 // final BasicWindow w = BasicWindow.getWindow("Library: " + 634 // letterDB.size() + " Datensätze", 400, 300); 635 final JFrame w = new JFrame(); 636 // w.setLayout(new GridBagLayout()); 637 sortLetterDB(); 638 JPanel p = new JPanel(new GridLayout(letterDB.size() + 1, 3)); 639 w.add(new JScrollPane(p)); 640 641 final Letter[] list = new Letter[letterDB.size()]; 642 643 int y = 0; 644 int i = 0; 645 ListIterator<Letter> iter = letterDB.listIterator(letterDB.size()); 646 final ArrayList<Integer> rem = new ArrayList<Integer>(); 647 while (iter.hasPrevious()) { 648 final Letter tmp = iter.previous(); 649 list[i] = tmp; 650 651 JLabel lbl = null; 652 if ((tmp.getGoodDetections() == 0 && tmp.getBadDetections() > 3) || ((double) tmp.getBadDetections() / (double) tmp.getGoodDetections() >= 3)) { 653 lbl = new JLabel("<html><p><font color=\"#ff0000\" " + "size=\"3\">" + tmp.getId() + ": " + tmp.getDecodedValue() + "(" + tmp.getGoodDetections() + "/" + tmp.getBadDetections() + ") Size: " + tmp.toPixelObject(0.85).getSize() + "</font> </p>" + "</html>"); 654 } else { 655 lbl = new JLabel(tmp.getId() + ": " + tmp.getDecodedValue() + "(" + tmp.getGoodDetections() + "/" + tmp.getBadDetections() + ") Size: " + tmp.toPixelObject(0.85).getSize()); 656 } 657 658 ImageComponent img = new ImageComponent(tmp.getImage()); 659 660 final JCheckBox bt = new JCheckBox("DELETE"); 661 final int ii = i; 662 bt.addActionListener(new ActionListener() { 663 public Integer id = ii; 664 665 public void actionPerformed(ActionEvent arg) { 666 JCheckBox src = ((JCheckBox) arg.getSource()); 667 if (src.getText().equals("DELETE")) { 668 rem.add(id); 669 } else { 670 rem.remove(id); 671 } 672 } 673 674 }); 675 p.add(lbl); 676 p.add(img); 677 p.add(bt); 678 i++; 679 y++; 680 // if (y > 20) { 681 // y = 0; 682 // x += 6; 683 // } 684 } 685 JButton b = new JButton("Invoke"); 686 p.add(b); 687 b.addActionListener(new ActionListener() { 688 689 public void actionPerformed(ActionEvent e) { 690 // System.out.println(rem + ""); 691 ArrayList<Letter> list = new ArrayList<Letter>(); 692 int s = letterDB.size(); 693 for (Integer i : rem) { 694 try { 695 Letter let = letterDB.get(s - 1 - i); 696 list.add(let); 697 698 } catch (Exception ew) { 699 JDLogger.exception(ew); 700 } 701 } 702 for (Letter letter : list) { 703 removeLetterFromLibrary(letter); 704 } 705 saveMTHFile(); 706 displayLibrary(); 707 } 708 }); 709 w.pack(); 710 w.setVisible(true); 711 } 712 713 public String getCodeFromFileName(String name) { 714 return new Regex(name, "captcha_(.*?)_code(.*?)\\.(.*?)").getMatch(1); 715 } 716 717 /** 718 * Liest den captchaornder aus 719 * 720 * @param path 721 * @return File Array 722 */ 723 public File[] getImages(String path) { 724 File dir = new File(path); 725 726 if (dir == null || !dir.exists()) { 727 if (Utilities.isLoggerActive()) { 728 logger.severe("Image dir nicht gefunden " + path); 729 } 730 731 } 732 logger.info(dir + ""); 733 File[] entries = dir.listFiles(new FileFilter() { 734 public boolean accept(File pathname) { 735 if (Utilities.isLoggerActive()) { 736 logger.info(pathname.getName()); 737 } 738 if (pathname.getName().endsWith(".bmp") || pathname.getName().endsWith(".jpg") || pathname.getName().endsWith(".png") || pathname.getName().endsWith(".gif")) { 739 740 return true; 741 } else { 742 return false; 743 } 744 } 745 746 }); 747 return entries; 748 749 } 750 751 /** 752 * @return the imageType 753 */ 754 public String getImageType() { 755 return imageType; 756 } 757 758 /** 759 * Die Methode parsed die jacinfo.xml 760 */ 761 private void getJACInfo() { 762 File f = getResourceFile("jacinfo.xml"); 763 if (!f.exists()) { 764 if (Utilities.isLoggerActive()) { 765 logger.severe("jacinfo.xml is missing2"); 766 } 767 return; 768 } 769 Document doc = JDUtilities.parseXmlString(JDIO.readFileToString(f), false); 770 if (doc == null) { 771 if (Utilities.isLoggerActive()) { 772 logger.severe("jacinfo.xml is missing2"); 773 } 774 return; 775 } 776 777 NodeList nl = doc.getFirstChild().getChildNodes(); 778 for (int i = 0; i < nl.getLength(); i++) { 779 // Get child node 780 Node childNode = nl.item(i); 781 782 if (childNode.getNodeName().equals("method")) { 783 try { 784 this.extern = JDUtilities.getAttribute(childNode, "type").equalsIgnoreCase("extern"); 785 } catch (Exception e) { 786 } 787 } else if (childNode.getNodeName().equals("command")) { 788 789 this.srcFile = JDUtilities.getAttribute(childNode, "src"); 790 this.dstFile = JDUtilities.getAttribute(childNode, "dst"); 791 this.command = JDUtilities.getAttribute(childNode, "cmd"); 792 793 } else if (childNode.getNodeName().equals("format")) { 794 try { 795 setLetterNum(Integer.parseInt(JDUtilities.getAttribute(childNode, "letterNum"))); 796 } catch (Exception e) { 797 } 798 799 setImageType(JDUtilities.getAttribute(childNode, "type")); 800 } 801 } 802 } 803 804 /** 805 * @return JACscript Instanz 806 */ 807 public JACScript getJas() { 808 return jas; 809 } 810 811 /** 812 * Vergleicht a und b und gibt eine Vergleichszahl zurück. a und b werden 813 * gegeneinander verschoben und b wird über die Parameter gedreht. Praktisch 814 * heißt das, dass derjenige Treffer als gut eingestuft wird, bei dem der 815 * Datenbank Datensatz möglichst optimal überdeckt wird. 816 * 817 * @param a 818 * Original Letter 819 * @param B 820 * Vergleichsletter 821 * @return int 0(super)-0xffffff (ganz übel) 822 */ 823 public LetterComperator getLetter(Letter letter) { 824 if (jas.getDouble("quickScanValityLimit") <= 0) { 825 logger.info("quickscan disabled"); 826 return getLetterExtended(letter); 827 828 } 829 830 logger.info("Work on Letter:" + letter); 831 // long startTime = Utilities.getTimer(); 832 LetterComperator res = null; 833 double lastPercent = 100.0; 834 int bvX, bvY; 835 try { 836 837 if (letterDB == null) { 838 if (Utilities.isLoggerActive()) { 839 logger.severe("letterDB nicht vorhanden"); 840 } 841 return null; 842 } 843 844 LetterComperator lc; 845 ScrollPaneWindow w = null; 846 if (isShowDebugGui()) { 847 w = new ScrollPaneWindow(); 848 849 w.setTitle(" Letter " + letter.getId()); 850 } 851 bvX = jas.getInteger("borderVarianceX"); 852 bvY = jas.getInteger("borderVarianceY"); 853 int line = 0; 854 lc = new LetterComperator(letter, null); 855 lc.setScanVariance(0, 0); 856 lc.setOwner(this); 857 res = lc; 858 int tt = 0; 859 logger.info("Do quickscan"); 860 Method preValueFilterMethod = null; 861 Class<?>[] preValueFilterParameterTypes = null; 862 Object[] preValueFilterArguments = new Object[] { null, this }; 863 if (jas.getString("preValueFilter").length() > 0) { 864 String[] ref = jas.getString("preValueFilter").split("\\."); 865 if (ref.length != 2) { 866 if (Utilities.isLoggerActive()) { 867 logger.severe("preValueFilter should have the format Class.Method"); 868 } 869 return null; 870 } 871 String cl = ref[0]; 872 String methodname = ref[1]; 873 Class<?> newClass; 874 try { 875 newClass = Class.forName("jd.captcha.specials." + cl); 876 preValueFilterParameterTypes = new Class[] { LetterComperator.class, this.getClass() }; 877 preValueFilterMethod = newClass.getMethod(methodname, preValueFilterParameterTypes); 878 879 } catch (Exception e) { 880 JDLogger.exception(e); 881 } 882 } 883 Method postValueFilterMethod = null; 884 Class<?>[] postValueFilterParameterTypes = null; 885 Object[] postValueFilterArguments = new Object[] { null, this }; 886 if (jas.getString("postValueFilter").length() > 0) { 887 String[] ref = jas.getString("postValueFilter").split("\\."); 888 if (ref.length != 2) { 889 if (Utilities.isLoggerActive()) { 890 logger.severe("postValueFilter should have the format Class.Method"); 891 } 892 return null; 893 } 894 String cl = ref[0]; 895 String methodname = ref[1]; 896 Class<?> newClass; 897 try { 898 newClass = Class.forName("jd.captcha.specials." + cl); 899 postValueFilterParameterTypes = new Class[] { LetterComperator.class, this.getClass() }; 900 postValueFilterMethod = newClass.getMethod(methodname, postValueFilterParameterTypes); 901 902 } catch (Exception e) { 903 JDLogger.exception(e); 904 } 905 } 906 for (Letter tmp : letterDB) { 907 if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); 908 909 if (Math.abs(tmp.getHeight() - letter.getHeight()) > bvY || Math.abs(tmp.getWidth() - letter.getWidth()) > bvX) { 910 continue; 911 } 912 913 lc = new LetterComperator(letter, tmp); 914 // commented out only experimental 915 // lc.setScanVariance(0, 0); 916 lc.setOwner(this); 917 918 if (preValueFilterMethod != null) { 919 preValueFilterArguments[0] = tmp; 920 preValueFilterArguments[1] = lc; 921 if (!((Boolean) preValueFilterMethod.invoke(null, preValueFilterArguments))) { 922 continue; 923 } 924 925 } 926 lc.run(); 927 tt++; 928 if (isShowDebugGui()) { 929 w.setText(0, line, "0° Quick " + tt); 930 w.setImage(1, line, lc.getA().getImage(2)); 931 w.setText(2, line, lc.getA().getDim()); 932 w.setImage(3, line, lc.getB().getImage(2)); 933 w.setText(4, line, lc.getB().getDim()); 934 w.setImage(5, line, lc.getIntersectionLetter().getImage(2)); 935 w.setText(6, line, lc.getIntersectionLetter().getDim()); 936 w.setText(7, line, lc); 937 line++; 938 } 939 postValueFilterArguments[0] = lc; 940 if (postValueFilterMethod == null || (Boolean) postValueFilterMethod.invoke(null, postValueFilterArguments)) { 941 if (res == null || lc.getValityPercent() < res.getValityPercent()) { 942 if (res != null && res.getValityPercent() < lastPercent) { 943 lastPercent = res.getValityPercent(); 944 } 945 res = lc; 946 if (jas.getDouble("LetterSearchLimitPerfectPercent") >= lc.getValityPercent()) { 947 if (Utilities.isLoggerActive()) { 948 logger.finer(" Perfect Match: " + res.getB().getDecodedValue() + res.getValityPercent() + " good:" + tmp.getGoodDetections() + " bad: " + tmp.getBadDetections() + " - " + res); 949 } 950 res.setDetectionType(LetterComperator.QUICKSCANPERFECTMATCH); 951 res.setReliability(lastPercent - res.getValityPercent()); 952 return res; 953 } 954 // if(Utilities.isLoggerActive())logger.finer("dim " 955 // + 956 // lc.getA().getDim() + "|" + lc.getB().getDim() + " New 957 // Best value: " + lc.getDecodedValue() + " " 958 // +lc.getValityPercent() + " good:" + 959 // tmp.getGoodDetections() + " bad: " + 960 // tmp.getBadDetections() + " - " + lc); 961 } else if (res != null) { 962 if (lc.getValityPercent() < lastPercent) { 963 lastPercent = lc.getValityPercent(); 964 } 965 } 966 } 967 } 968 969 } catch (Exception e) { 970 971 JDLogger.exception(e); 972 } 973 if (res != null && res.getB() != null) { 974 if (Utilities.isLoggerActive()) { 975 logger.finer(" Normal Match: " + res.getB().getDecodedValue() + " " + res.getValityPercent() + " good:" + res.getB().getGoodDetections() + " bad: " + res.getB().getBadDetections()); 976 } 977 // if (Utilities.isLoggerActive()) logger.fine("Letter erkannt 978 // in: " + (Utilities.getTimer() - startTime) + " ms"); 979 res.setReliability(lastPercent - res.getValityPercent()); 980 if (res.getReliability() >= jas.getDouble("quickScanReliabilityLimit") && res.getValityPercent() < jas.getDouble("quickScanValityLimit")) { 981 res.setDetectionType(LetterComperator.QUICKSCANMATCH); 982 logger.info("Qickscan found " + res.getValityPercent() + "<" + jas.getDouble("quickScanValityLimit")); 983 return res; 984 } else { 985 if (Utilities.isLoggerActive()) { 986 logger.warning("Letter nicht ausreichend erkannt. Try Extended " + res.getReliability() + " - " + jas.getDouble("quickScanReliabilityLimit") + " /" + res.getValityPercent() + "-" + jas.getDouble("quickScanValityLimit")); 987 } 988 return getLetterExtended(letter); 989 } 990 } else { 991 if (Utilities.isLoggerActive()) { 992 logger.warning("Letter nicht erkannt. Try Extended"); 993 } 994 return getLetterExtended(letter); 995 } 996 997 } 998 999 /** 1000 * Sucht in der MTH ANch dem besten übereinstimmenem letter 1001 * 1002 * @param letter 1003 * (refferenz) 1004 * @return Letter. Beste Übereinstimmung 1005 */ 1006 private LetterComperator getLetterExtended(Letter letter) { 1007 // long startTime = Utilities.getTimer(); 1008 LetterComperator res = null; 1009 logger.info("Extended SCAN"); 1010 double lastPercent = 100.0; 1011 JTextArea tf = null; 1012 try { 1013 1014 if (letterDB == null) { 1015 if (Utilities.isLoggerActive()) { 1016 logger.severe("letterDB nicht vorhanden"); 1017 } 1018 return null; 1019 } 1020 1021 Letter tmp; 1022 int leftAngle = jas.getInteger("scanAngleLeft"); 1023 int rightAngle = jas.getInteger("scanAngleRight"); 1024 if (leftAngle > rightAngle) { 1025 int temp = leftAngle; 1026 leftAngle = rightAngle; 1027 rightAngle = temp; 1028 if (Utilities.isLoggerActive()) { 1029 logger.warning("param.scanAngleLeft>paramscanAngleRight"); 1030 } 1031 } 1032 int steps = Math.max(1, jas.getInteger("scanAngleSteps")); 1033 boolean turnDB = jas.getBoolean("turnDB"); 1034 int angle; 1035 Letter orgLetter = letter; 1036 LetterComperator lc; 1037 1038 ScrollPaneWindow w = null; 1039 if (isShowDebugGui()) { 1040 w = new ScrollPaneWindow(); 1041 1042 w.setTitle(" Letter " + letter.getId()); 1043 } 1044 int line = 0; 1045 lc = new LetterComperator(letter, null); 1046 lc.setOwner(this); 1047 res = lc; 1048 1049 Method preValueFilterMethod = null; 1050 Class<?>[] preValueFilterParameterTypes = null; 1051 Object[] preValueFilterArguments = new Object[] { null, this }; 1052 if (jas.getString("preValueFilter").length() > 0) { 1053 String[] ref = jas.getString("preValueFilter").split("\\."); 1054 if (ref.length != 2) { 1055 if (Utilities.isLoggerActive()) { 1056 logger.severe("preValueFilter should have the format Class.Method"); 1057 } 1058 return null; 1059 } 1060 String cl = ref[0]; 1061 String methodname = ref[1]; 1062 Class<?> newClass; 1063 try { 1064 newClass = Class.forName("jd.captcha.specials." + cl); 1065 preValueFilterParameterTypes = new Class[] { LetterComperator.class, this.getClass() }; 1066 preValueFilterMethod = newClass.getMethod(methodname, preValueFilterParameterTypes); 1067 1068 } catch (Exception e) { 1069 JDLogger.exception(e); 1070 } 1071 } 1072 Method postValueFilterMethod = null; 1073 Class<?>[] postValueFilterParameterTypes = null; 1074 Object[] postValueFilterArguments = new Object[] { null, this }; 1075 if (jas.getString("postValueFilter").length() > 0) { 1076 String[] ref = jas.getString("postValueFilter").split("\\."); 1077 if (ref.length != 2) { 1078 if (Utilities.isLoggerActive()) { 1079 logger.severe("postValueFilter should have the format Class.Method"); 1080 } 1081 return null; 1082 } 1083 String cl = ref[0]; 1084 String methodname = ref[1]; 1085 Class<?> newClass; 1086 try { 1087 newClass = Class.forName("jd.captcha.specials." + cl); 1088 postValueFilterParameterTypes = new Class[] { LetterComperator.class, this.getClass() }; 1089 postValueFilterMethod = newClass.getMethod(methodname, postValueFilterParameterTypes); 1090 1091 } catch (Exception e) { 1092 JDLogger.exception(e); 1093 } 1094 } 1095 for (angle = Utilities.getJumperStart(leftAngle, rightAngle); Utilities.checkJumper(angle, leftAngle, rightAngle); angle = Utilities.nextJump(angle, leftAngle, rightAngle, steps)) { 1096 1097 if (turnDB) { 1098 letter = orgLetter; 1099 } else { 1100 letter = orgLetter.turn(angle); 1101 } 1102 // if(Utilities.isLoggerActive())logger.finer(" Angle " + 1103 // angle + " : " + letter.getDim()); 1104 1105 int tt = 0; 1106 for (Letter ltr : letterDB) { 1107 if (Thread.currentThread().isInterrupted()) throw new InterruptedException(); 1108 1109 if (turnDB) { 1110 tmp = ltr.turn(angle); 1111 1112 } else { 1113 tmp = ltr; 1114 } 1115 1116 if (Math.abs(tmp.getHeight() - letter.getHeight()) > jas.getInteger("borderVarianceY") || Math.abs(tmp.getWidth() - letter.getWidth()) > jas.getInteger("borderVarianceX")) { 1117 continue; 1118 } 1119 1120 lc = new LetterComperator(letter, tmp); 1121 lc.setOwner(this); 1122 1123 if (preValueFilterMethod != null) { 1124 preValueFilterArguments[0] = lc; 1125 preValueFilterArguments[1] = this; 1126 if (!((Boolean) preValueFilterMethod.invoke(null, preValueFilterArguments))) { 1127 continue; 1128 } 1129 1130 } 1131 lc.run(); 1132 // if(Utilities.isLoggerActive())logger.info("Duration: 1133 // "+(Utilities.getTimer()-timer) +" 1134 // Loops: "+lc.loopCounter); 1135 tt++; 1136 1137 if (isShowDebugGui()) { 1138 w.setText(0, line, angle + "° " + tt); 1139 w.setImage(1, line, lc.getA().getImage(2)); 1140 w.setText(2, line, lc.getA().getDim()); 1141 w.setImage(3, line, lc.getB().getImage(2)); 1142 w.setText(4, line, lc.getB().getDim()); 1143 w.setImage(5, line, lc.getIntersectionLetter().getImage(2)); 1144 w.setText(6, line, lc.getIntersectionLetter().getDim()); 1145 1146 w.setComponent(7, line, tf = new JTextArea()); 1147 tf.setText(lc.toString()); 1148 if (lc.getPreValityPercent() > jas.getInteger("preScanFilter") && jas.getInteger("preScanFilter") > 0) { 1149 tf.setBackground(Color.LIGHT_GRAY); 1150 } 1151 line++; 1152 } 1153 postValueFilterArguments[0] = lc; 1154 if (postValueFilterMethod == null || (Boolean) postValueFilterMethod.invoke(null, postValueFilterArguments)) { 1155 1156 if (res == null || lc.getValityPercent() < res.getValityPercent()) { 1157 if (res != null && res.getValityPercent() < lastPercent) { 1158 lastPercent = res.getValityPercent(); 1159 } 1160 res = lc; 1161 1162 if (jas.getDouble("LetterSearchLimitPerfectPercent") >= lc.getValityPercent()) { 1163 res.setDetectionType(LetterComperator.PERFECTMATCH); 1164 res.setReliability(lastPercent - res.getValityPercent()); 1165 if (Utilities.isLoggerActive()) { 1166 logger.finer(" Perfect Match: " + res.getB().getDecodedValue() + " " + res.getValityPercent() + " good:" + tmp.getGoodDetections() + " bad: " + tmp.getBadDetections() + " - " + res); 1167 } 1168 if (isShowDebugGui()) { 1169 tf.setBackground(Color.GREEN); 1170 } 1171 return res; 1172 } 1173 if (isShowDebugGui()) { 1174 tf.setBackground(Color.BLUE); 1175 } 1176 if (Utilities.isLoggerActive()) { 1177 logger.finer("Angle " + angle + "dim " + lc.getA().getDim() + "|" + lc.getB().getDim() + " New Best value: " + lc.getDecodedValue() + " " + lc.getValityPercent() + " good:" + tmp.getGoodDetections() + " bad: " + tmp.getBadDetections() + " - " + lc); 1178 } 1179 1180 } else if (res != null) { 1181 // if (Utilities.isLoggerActive()&& 1182 // lc.getDecodedValue().equalsIgnoreCase("G")) 1183 // logger.finer("Angle " + angle + "dim " + 1184 // lc.getA().getDim() + "|" + lc.getB().getDim() + " 1185 // value: " + lc.getDecodedValue() + " " + 1186 // lc.getValityPercent() + " good:" + 1187 // tmp.getGoodDetections() + " bad: " + 1188 // tmp.getBadDetections() + " - " + lc); 1189 1190 if (lc.getValityPercent() < lastPercent) { 1191 lastPercent = lc.getValityPercent(); 1192 } 1193 } 1194 } 1195 1196 } 1197 // if(Utilities.isLoggerActive())logger.info("Full Angle scan 1198 // in 1199 // "+(Utilities.getTimer()-startTime2)); 1200 } 1201 // w.refreshUI(); 1202 } catch (Exception e) { 1203 JDLogger.exception(e); 1204 } 1205 1206 if (res != null && res.getB() != null) { 1207 if (Utilities.isLoggerActive()) { 1208 logger.finer(" Normal Match: " + res.getB().getDecodedValue() + " " + res.getValityPercent() + " good:" + res.getB().getGoodDetections() + " bad: " + res.getB().getBadDetections()); 1209 } 1210 1211 res.setReliability(lastPercent - res.getValityPercent()); 1212 } else { 1213 if (getJas().getInteger("preScanEmergencyFilter") > getJas().getInteger("preScanFilter")) { 1214 logger.warning("nicht erkannt. Verwende erweiterte Emergencydatenbank"); 1215 int psf = getJas().getInteger("preScanFilter"); 1216 getJas().set("preScanFilter", getJas().getInteger("preScanEmergencyFilter")); 1217 LetterComperator ret = getLetterExtended(letter); 1218 getJas().set("preScanFilter", psf); 1219 return ret; 1220 1221 } 1222 if (Utilities.isLoggerActive()) { 1223 logger.severe("Letter entgültig nicht erkannt"); 1224 } 1225 if (isShowDebugGui() && tf != null) { 1226 tf.setBackground(Color.RED); 1227 } 1228 1229 } 1230 1231 return res; 1232 1233 } 1234 1235 /** 1236 * @return gibt die Lettermap als String zurück 1237 */ 1238 private String getLetterMapString() { 1239 StringBuilder ret = new StringBuilder(); 1240 int i = 0; 1241 for (int x = 0; x < letterMap.length; x++) { 1242 ret.append("|"); 1243 i++; 1244 for (int y = 0; y < letterMap[0].length; y++) { 1245 1246 ret.append(letterMap[x][y]); 1247 i++; 1248 ret.append(","); 1249 i++; 1250 } 1251 ret.deleteCharAt(ret.length() - 1); 1252 if (Utilities.isLoggerActive()) { 1253 …
Large files files are truncated, but you can click here to view the full file