Closes issue #130

This commit is contained in:
Joe0 2012-03-15 01:20:09 -05:00
parent 469e4651fa
commit 1a59778484
14 changed files with 10103 additions and 297 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -94,4 +94,9 @@
<!-- This is displayed on login. Each line will be sent as a new message. Make sure you're using XML entities for things like <, new lines, etc. -->
<entry key="MOTD">@yel@Welcome to MoparClassic Alpha!&#10;@red@Report all bugs on GitHub.&#10;@cya@Commands: ::town &lt;townname>, ::item &lt;id>, ::say &lt;msg>, ::goto &lt;name></entry>
<!-- This is the location of the captcha dictionary -->
<entry key="captcha-dictionary">conf/data/dictionary.txt</entry>
<!-- This is the directory that contains the fonts -->
<entry key="font-dir">conf/fonts</entry>
</properties>

View File

@ -48,6 +48,8 @@ public class Config {
public static String DATA_SERVICE;
public static String REPORT_HANDLER;
public static String MOTD;
public static String CAPTCHA_DICTIONARY;
public static String FONT_DIR;
static {
loadEnv();
@ -144,6 +146,9 @@ public class Config {
MOTD = props.getProperty("MOTD");
CAPTCHA_DICTIONARY = props.getProperty("captcha-dictionary");
FONT_DIR = props.getProperty("font-dir");
props.clear();
}

View File

@ -9,13 +9,13 @@ import org.moparscape.msc.config.Constants;
import org.moparscape.msc.config.Formulae;
import org.moparscape.msc.gs.Instance;
import org.moparscape.msc.gs.connection.RSCPacket;
import org.moparscape.msc.gs.core.GameEngine;
import org.moparscape.msc.gs.model.Bank;
import org.moparscape.msc.gs.model.InvItem;
import org.moparscape.msc.gs.model.Player;
import org.moparscape.msc.gs.model.Shop;
import org.moparscape.msc.gs.model.World;
import org.moparscape.msc.gs.quest.Quest;
import org.moparscape.msc.gs.tools.Captcha;
public class MiscPacketBuilder {
/**
@ -219,7 +219,7 @@ public class MiscPacketBuilder {
*/
public void sendEnterSleep() {
player.setSleeping(true);
byte[] image = GameEngine.getCaptcha().generateCaptcha(player);
byte[] image = Captcha.generateCaptcha(player);
RSCPacketBuilder s = new RSCPacketBuilder();
s.setID(206);
s.addBytes(image, 0, image.length);

View File

@ -24,7 +24,6 @@ import org.moparscape.msc.gs.model.snapshot.Snapshot;
import org.moparscape.msc.gs.phandler.PacketHandler;
import org.moparscape.msc.gs.phandler.PacketHandlerDef;
import org.moparscape.msc.gs.plugins.dependencies.NpcAI;
import org.moparscape.msc.gs.tools.Captcha;
import org.moparscape.msc.gs.util.Logger;
/**
@ -33,16 +32,11 @@ import org.moparscape.msc.gs.util.Logger;
*/
public final class GameEngine extends Thread {
private static Captcha captcha;
/**
* World instance
*/
private static final World world = Instance.getWorld();
public static Captcha getCaptcha() {
return captcha;
}
/**
* Responsible for updating all connected clients
*/
@ -88,8 +82,6 @@ public final class GameEngine extends Thread {
* Constructs a new game engine with an empty packet queue.
*/
public GameEngine() {
captcha = new Captcha();
captcha.init();
packetQueue = new PacketQueue<RSCPacket>();
try {
loadPacketHandlers();

View File

@ -4,177 +4,121 @@ import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.imageio.ImageIO;
import org.moparscape.msc.config.Config;
import org.moparscape.msc.gs.model.Player;
import org.moparscape.msc.gs.util.Logger;
public class Captcha {
/*
* ArrayList that includes the preset colours.
*/
public ArrayList<Color> colors = new ArrayList<Color>();
/*
* Boolean to decide whether to draw the grid on top or not
*/
public boolean drawGrid = true;
/*
* String that represents the folder to load the fonts from
*/
public String fontFolder = "." + File.separator + "conf" + File.separator
+ "fonts" + File.separator;
private final int LETTERS_MAX = 5;
private final int LETTERS_MIN = 4;
private final int LINES_MAX = 10;
private final int LINES_MIN = 5;
/*
* Font array that includes all the loaded fonts with a preset size (between
* 25 and 30)
*/
public Font loadedFonts[];
private Random rand = new Random();
private final int SQUARES_MAX = 13;
/*
* Settings to disable OCRs
*/
private final int SQUARES_MIN = 7;
private final static Font[] fonts = new Font[4];
private final static Random random = new Random();
private final static String[] words;
/*
* Boolean that defines if we should display what Font we loaded.
*/
public boolean verboseLoad = false;
static {
public byte[] generateCaptcha(Player p) {
BufferedImage image = new BufferedImage(307, 49,
BufferedImage.TYPE_INT_RGB);
Graphics2D gfx = image.createGraphics();
String captcha = "";
gfx.setColor(Color.white);
gfx.fillRect(0, 0, 308, 52);
int howManyLetters = random(LETTERS_MIN, LETTERS_MAX);
for (int i = 1; i <= howManyLetters; i++) {
char temp = generateLetter();
if (temp == 'i' || temp == 'l') {
temp = 'q'; // ez fix.
}
captcha += temp;
gfx.setColor(colors.get(random(0, colors.size() - 1)));
gfx.setFont(loadedFonts[random(0, loadedFonts.length - 1)]);
double shear = (rand.nextDouble()) - 0.5;
gfx.shear(shear, 0);
gfx.drawString(String.valueOf(temp), i * random(40, 45),
random(30, 40));
gfx.shear(-shear, 0);
}
int howManySquares = random(SQUARES_MIN, SQUARES_MAX);
for (int i = 0; i < howManySquares; i++) // Draw the squares, math by
// xEnt.
{
gfx.setColor(colors.get(random(0, colors.size() - 1)));
gfx.drawRect((int) random(0, image.getWidth() - 80),
(int) random(0, image.getHeight()), 3, 3);
}
int howManyLines = random(LINES_MIN, LINES_MAX);
for (int i = 0; i < howManyLines; i++) // Draw the lines, math by xEnt.
{
gfx.setColor(colors.get(random(0, colors.size() - 1)));
int x = random(0, image.getWidth() - 80);
int y = random(0, image.getHeight());
gfx.drawLine(x, y, x + random(0, 30), y - random(0, 30));
}
if (drawGrid) // Draws the gray grid
{
gfx.setColor(Color.gray);
gfx.drawLine(0, 13, image.getWidth(), 13);
gfx.drawLine(0, 26, image.getWidth(), 26);
gfx.drawLine(0, 39, image.getWidth(), 39);
for (int i = 1; i < (int) (image.getWidth() / 10); i++) {
gfx.drawLine(20 * i, 0, 20 * i, image.getHeight());
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] returnVal = null;
// Load fonts
try {
ImageIO.write(image, "PNG", baos);
returnVal = baos.toByteArray();
// DataOutputStream out = new DataOutputStream(new
// FileOutputStream("newcaptchas/" + captcha + ".png"));
// out.write(returnVal);
String fontDir = Config.FONT_DIR;
fonts[0] = Font.createFont(Font.TRUETYPE_FONT,
new File(fontDir, "Harakiri.ttf")).deriveFont(30f);
fonts[1] = Font.createFont(Font.TRUETYPE_FONT,
new File(fontDir, "IntellectaBodoned Trash.ttf"))
.deriveFont(30f);
fonts[2] = Font.createFont(Font.TRUETYPE_FONT,
new File(fontDir, "MiseryLovesCompanyDEMO.ttf"))
.deriveFont(20f);
fonts[3] = Font.createFont(Font.TRUETYPE_FONT,
new File(fontDir, "ADDSBP__.TTF")).deriveFont(20f);
} catch (Exception e) {
Logger.error("Font loading error: " + e.getMessage());
e.printStackTrace();
}
// Load word list
List<String> wordList = new ArrayList<String>();
File file = new File(Config.CAPTCHA_DICTIONARY);
FileInputStream in = null;
BufferedReader reader = null;
FileChannel chan = null;
try {
in = new FileInputStream(file);
chan = in.getChannel();
reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null) {
wordList.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
chan.close();
if (reader != null) {
reader.close();
}
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
gfx.dispose();
p.setSleepword(captcha);
return returnVal;
}
private char generateLetter() {
char returnVal = '-';
switch (random(0, 1)) {
case 0:
returnVal = (char) random(65, 89);
break;
case 1:
returnVal = (char) random(97, 121);
break;
}
return returnVal;
words = wordList.toArray(new String[0]);
}
public void init() {
loadFonts();
colors.clear();
colors.add(Color.BLUE);
colors.add(Color.GREEN);
colors.add(Color.GRAY);
colors.add(Color.BLACK);
colors.add(Color.RED);
colors.add(Color.PINK);
colors.add(Color.DARK_GRAY);
public static byte[] generateCaptcha(Player p) {
BufferedImage image = new BufferedImage(255, 40,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = image.createGraphics();
g.setColor(Color.black);
g.fillRect(0, 0, 255, 40);
g.setColor(Color.white);
String word = getWord();
p.setSleepword(word);
int lastx = 5;
for (char c : word.toCharArray()) {
Font font = fonts[random.nextInt(fonts.length)];
char chr = Character.toUpperCase(c);
g.setFont(font);
// y = 35 +- 5
g.drawString(String.valueOf(chr), lastx, 35 + 5 * randomSignFlip());
// Width +- an element of (0 through 5)
lastx += g.getFontMetrics().charWidth(chr)
+ randomSignFlip() * random.nextInt(6);
}
/**
* Loads fonts from a folder to a font array
*/
public void loadFonts() {
File fontFolderFile = new File(fontFolder);
String[] fonts = fontFolderFile.list();
loadedFonts = new Font[fonts.length];
for (int i = 0; i < fonts.length; i++) {
g.dispose();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte bytes[] = null;
try {
FileInputStream fontStream = new FileInputStream(fontFolder
+ fonts[i]);
Font temp = java.awt.Font.createFont(
java.awt.Font.TRUETYPE_FONT, fontStream);
loadedFonts[i] = temp.deriveFont(Float.valueOf(random(35, 40)));
if (verboseLoad) {
Logger.println("Loaded font: "
+ loadedFonts[i].getFontName());
ImageIO.write(image, "png", baos);
bytes = baos.toByteArray();
} catch (IOException ioe) {
Logger.error("Error generating sleep word: " + ioe.getMessage());
ioe.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
Logger.println("Loaded " + fonts.length + " fonts.");
return bytes;
}
/**
* returns a random number within the given bounds
*/
public int random(int low, int high) {
return low + rand.nextInt(high - low + 1);
private static int randomSignFlip() {
return random.nextBoolean() ? 1 : -1;
}
public static String getWord() {
int row = random.nextInt(words.length);
return words[row];
}
}

View File

@ -1,140 +0,0 @@
package org.moparscape.msc.gs.tools;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.Transparency;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.ImageIcon;
public class PaintCaptcha {
private final static boolean GRAPH = true;
private final static Color GRAPH_COLOR = Color.GRAY;
private final static int LINES = 10;
/**
* @author xEnt
* @info Paints over an Image(Captcha) to make it more secure, with Lines,
* Squares and a Graph.
*/
private final static int SQUARES_MAX = 25;
private final static int SQUARES_MIN = 10;
/*
* public static void main(String [] args) throws Exception { Image img =
* Toolkit.getDefaultToolkit().getImage("C:\\heh.png");
* ImageIO.write(Img.toBufferedImage(secure(img)), "png", new
* File("C:\\roflrofl.png")); }
*/
public static long randomNumber(int min, int max) {
return Math.round((Math.random() * (max - min)) + min);
}
public static BufferedImage secure(BufferedImage b) {
try {
// BufferedImage b = toBufferedImage(img);
Graphics2D gfx = b.createGraphics();
gfx.setPaintMode();
// Draw the Squares.
Random random = new Random();
for (int i = 0; i < (int) randomNumber(SQUARES_MIN, SQUARES_MAX); i++) {
Color randomColor = Color.getHSBColor(random.nextFloat(), 1.0F,
1.0F);
gfx.setColor(randomColor);
gfx.drawRect((int) randomNumber(0, b.getWidth() - 80),
(int) randomNumber(0, b.getHeight()), 3, 3);
}
// Draw the Lines.
gfx.setColor(Color.ORANGE);
for (int i = 0; i < LINES; i++) {
int x = (int) randomNumber(0, b.getWidth() - 80);
int y = (int) randomNumber(0, b.getHeight());
gfx.drawLine(x, y, x + (int) randomNumber(0, 30), y
- (int) randomNumber(0, 30));
}
if (GRAPH) {
// Graph, Lines from Top to Bottom.
gfx.setColor(GRAPH_COLOR);
for (int i = 0; i < 17; i++) {
gfx.drawLine(5 + i * 15, b.getHeight(), 5 + i * 15, 0);
}
for (int i = 0; i < 3; i++) {
gfx.drawLine(b.getWidth(), i * 14, 0, i * 14);
}
}
gfx.dispose();
return b;
} catch (Exception e) {
return null;
}
}
public static BufferedImage toBufferedImage(Image image) {
if (image instanceof BufferedImage) {
return (BufferedImage) image;
}
// This code ensures that all the pixels in the image are loaded
image = new ImageIcon(image).getImage();
// Determine if the image has transparent pixels; for this method's
// implementation, see e661 Determining If an Image Has Transparent
// Pixels
boolean hasAlpha = false;
// Create a buffered image with a format that's compatible with the
// screen
BufferedImage bimage = null;
GraphicsEnvironment ge = GraphicsEnvironment
.getLocalGraphicsEnvironment();
try {
// Determine the type of transparency of the new buffered image
int transparency = Transparency.OPAQUE;
if (hasAlpha) {
transparency = Transparency.BITMASK;
}
// Create the buffered image
GraphicsDevice gs = ge.getDefaultScreenDevice();
GraphicsConfiguration gc = gs.getDefaultConfiguration();
bimage = gc.createCompatibleImage(image.getWidth(null),
image.getHeight(null), transparency);
} catch (HeadlessException e) {
// The system does not have a screen
}
if (bimage == null) {
// Create a buffered image using the default color model
int type = BufferedImage.TYPE_INT_RGB;
if (hasAlpha) {
type = BufferedImage.TYPE_INT_ARGB;
}
bimage = new BufferedImage(image.getWidth(null),
image.getHeight(null), type);
}
// Copy image to buffered image
Graphics g = bimage.createGraphics();
// Paint the image onto the buffered image
g.drawImage(image, 0, 0, null);
g.dispose();
return bimage;
}
}