[gatein-commits] gatein SVN: r2410 - in components/simplecaptcha: trunk and 14 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Wed Mar 31 11:23:51 EDT 2010
Author: thomas.heute at jboss.com
Date: 2010-03-31 11:23:50 -0400 (Wed, 31 Mar 2010)
New Revision: 2410
Added:
components/simplecaptcha/tags/
components/simplecaptcha/trunk/
components/simplecaptcha/trunk/.classpath
components/simplecaptcha/trunk/.project
components/simplecaptcha/trunk/.settings/
components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs
components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs
components/simplecaptcha/trunk/patch.txt
components/simplecaptcha/trunk/pom.xml
components/simplecaptcha/trunk/src/
components/simplecaptcha/trunk/src/main/
components/simplecaptcha/trunk/src/main/java/
components/simplecaptcha/trunk/src/main/java/nl/
components/simplecaptcha/trunk/src/main/java/nl/captcha/
components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/
components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/
components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java
components/simplecaptcha/trunk/src/main/java/nl/captcha/util/
components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java
Log:
Adding simplecatcha
Added: components/simplecaptcha/trunk/.classpath
===================================================================
--- components/simplecaptcha/trunk/.classpath (rev 0)
+++ components/simplecaptcha/trunk/.classpath 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
Added: components/simplecaptcha/trunk/.project
===================================================================
--- components/simplecaptcha/trunk/.project (rev 0)
+++ components/simplecaptcha/trunk/.project 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>sc</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
+ <arguments>
+ <dictionary>
+ <key>LaunchConfigHandle</key>
+ <value><project>/.externalToolBuilders/build-jar.launch</value>
+ </dictionary>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
Added: components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs
===================================================================
--- components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs (rev 0)
+++ components/simplecaptcha/trunk/.settings/org.eclipse.jdt.core.prefs 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,5 @@
+#Wed Mar 31 16:06:54 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
Added: components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs
===================================================================
--- components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs (rev 0)
+++ components/simplecaptcha/trunk/.settings/org.maven.ide.eclipse.prefs 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,9 @@
+#Wed Mar 31 16:05:04 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
Added: components/simplecaptcha/trunk/patch.txt
===================================================================
--- components/simplecaptcha/trunk/patch.txt (rev 0)
+++ components/simplecaptcha/trunk/patch.txt 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1 @@
+This is a fork from SimpleCaptchia 1.1.1 to be compiled on JDK 5 and to use the com.jhlabs.filters libs available from iBiblio Maven repository
Added: components/simplecaptcha/trunk/pom.xml
===================================================================
--- components/simplecaptcha/trunk/pom.xml (rev 0)
+++ components/simplecaptcha/trunk/pom.xml 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,30 @@
+<project>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.gatein</groupId>
+ <artifactId>gatein-parent</artifactId>
+ <version>1.0.0-GA</version>
+ </parent>
+
+ <groupId>org.gatein.simplecaptcha</groupId>
+ <artifactId>simplecaptcha</artifactId>
+ <version>1.1.1-GA-Patch01-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.jhlabs</groupId>
+ <artifactId>filters</artifactId>
+ <version>2.0.235</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ </dependency>
+ </dependencies>
+
+</project>
+
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/Captcha.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,265 @@
+package nl.captcha;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import javax.imageio.ImageIO;
+
+import nl.captcha.backgrounds.BackgroundProducer;
+import nl.captcha.backgrounds.TransparentBackgroundProducer;
+import nl.captcha.gimpy.GimpyRenderer;
+import nl.captcha.gimpy.RippleGimpyRenderer;
+import nl.captcha.noise.CurvedLineNoiseProducer;
+import nl.captcha.noise.NoiseProducer;
+import nl.captcha.text.producer.DefaultTextProducer;
+import nl.captcha.text.producer.TextProducer;
+import nl.captcha.text.renderer.DefaultWordRenderer;
+import nl.captcha.text.renderer.WordRenderer;
+
+
+/**
+ * A builder for generating a CAPTCHA image/answer pair.
+ *
+ * <p>
+ * Example for generating a new CAPTCHA:
+ * </p>
+ * <pre>Captcha captcha = new Captcha.Builder(200, 50)
+ * .addText()
+ * .addBackground()
+ * .build();</pre>
+ * <p>Note that the <code>build()</code> must always be called last. Other methods are optional,
+ * and can sometimes be repeated. For example:</p>
+ * <pre>Captcha captcha = new Captcha.Builder(200, 50)
+ * .addText()
+ * .addNoise()
+ * .addNoise()
+ * .addNoise()
+ * .addBackground()
+ * .build();</pre>
+ * <p>Adding multiple backgrounds has no affect; the last background added will simply be the
+ * one that is eventually rendered.</p>
+ * <p>To validate that <code>answerStr</code> is a correct answer to the CAPTCHA:</p>
+ *
+ * <code>captcha.isCorrect(answerStr);</code>
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ * v
+ */
+public final class Captcha implements Serializable {
+
+ private static final long serialVersionUID = 617511236L;
+ public static final String NAME = "simpleCaptcha";
+ private Builder _builder;
+
+ private Captcha(Builder builder) {
+ _builder = builder;
+ }
+
+ public static class Builder implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * @serial
+ */
+ private String _answer = "";
+ /**
+ * @serial
+ */
+ private BufferedImage _img;
+ /**
+ * @serial
+ */
+ private BufferedImage _bg;
+ private boolean _addBorder = false;
+
+ public Builder(int width, int height) {
+ _img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ /**
+ * Add a background using the default BackgroundProducer.
+ *
+ * @return
+ */
+ public Builder addBackground() {
+ return addBackground(new TransparentBackgroundProducer());
+ }
+
+ /**
+ * Add a background using the given BackgroundProducer.
+ *
+ * @param bgProd
+ * @return
+ */
+ public Builder addBackground(BackgroundProducer bgProd) {
+ _bg = bgProd.getBackground(_img.getWidth(), _img.getHeight());
+
+ return this;
+ }
+
+ /**
+ * Add text to the image using the default TextProducer
+ *
+ * @return
+ */
+ public Builder addText() {
+ return addText(new DefaultTextProducer());
+ }
+
+ /**
+ * Add text to the image using the given TextProducer
+ *
+ * @param txtProd
+ * @return
+ */
+ public Builder addText(TextProducer txtProd) {
+ return addText(txtProd, new DefaultWordRenderer());
+ }
+
+ /**
+ * Display the answer on the image using the given WordRenderer.
+ *
+ * @param wRenderer
+ * @return
+ */
+ public Builder addText(WordRenderer wRenderer) {
+ return addText(new DefaultTextProducer(), wRenderer);
+ }
+
+ public Builder addText(TextProducer txtProd, WordRenderer wRenderer) {
+ _answer += txtProd.getText();
+ wRenderer.render(_answer, _img);
+
+ return this;
+ }
+
+ /**
+ * Add noise using the default NoiseProducer.
+ *
+ * @return
+ */
+ public Builder addNoise() {
+ return this.addNoise(new CurvedLineNoiseProducer());
+ }
+
+ /**
+ * Add noise using the given NoiseProducer.
+ *
+ * @param nProd
+ * @return
+ */
+ public Builder addNoise(NoiseProducer nProd) {
+ nProd.makeNoise(_img);
+ return this;
+ }
+
+ /**
+ * Gimp the image using the default GimpyRenderer.
+ *
+ * @return
+ */
+ public Builder gimp() {
+ return gimp(new RippleGimpyRenderer());
+ }
+
+ /**
+ * Gimp the image using the given GimpyRenderer.
+ *
+ * @param gimpy
+ * @return
+ */
+ public Builder gimp(GimpyRenderer gimpy) {
+ gimpy.gimp(_img);
+ return this;
+ }
+
+ /**
+ * Draw a single-pixel wide black border around the image.
+ *
+ * @return
+ */
+ public Builder addBorder() {
+ _addBorder = true;
+
+ return this;
+ }
+
+ /**
+ * Build the CAPTCHA. This method should always be called, and should always
+ * be called last.
+ *
+ * @return
+ */
+ public Captcha build() {
+ if (_bg == null) {
+ _bg = new TransparentBackgroundProducer().getBackground(_img.getWidth(), _img.getHeight());
+ }
+
+ // Paint the main image over the background
+ Graphics2D g = _bg.createGraphics();
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
+ g.drawImage(_img, null, null);
+
+ // Add the border, if necessary
+ if (_addBorder) {
+ int width = _img.getWidth();
+ int height = _img.getHeight();
+
+ g.setColor(Color.BLACK);
+ g.drawLine(0, 0, 0, width);
+ g.drawLine(0, 0, width, 0);
+ g.drawLine(0, height - 1, width, height - 1);
+ g.drawLine(width - 1, height - 1, width - 1, 0);
+ }
+
+ _img = _bg;
+
+ return new Captcha(this);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("[Answer: ");
+ sb.append(_answer);
+ sb.append("][Image: ");
+ sb.append(_img);
+ sb.append("]");
+
+ return sb.toString();
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.writeObject(_answer);
+ ImageIO.write(_img, "png", ImageIO.createImageOutputStream(out));
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException,
+ ClassNotFoundException {
+ _answer = (String) in.readObject();
+ _img = ImageIO.read(ImageIO.createImageInputStream(in));
+ }
+ }
+
+ public boolean isCorrect(String answer) {
+ return _builder._answer.equals(answer);
+ }
+
+ public String getAnswer() {
+ return _builder._answer;
+ }
+
+ public BufferedImage getImage() {
+ return _builder._img;
+ }
+
+ @Override
+ public String toString() {
+ return _builder.toString();
+ }
+}
\ No newline at end of file
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/CaptchaBean.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,122 @@
+package nl.captcha;
+
+import java.awt.AlphaComposite;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import nl.captcha.backgrounds.BackgroundProducer;
+import nl.captcha.backgrounds.TransparentBackgroundProducer;
+import nl.captcha.gimpy.GimpyRenderer;
+import nl.captcha.noise.NoiseProducer;
+import nl.captcha.text.producer.TextProducer;
+import nl.captcha.text.renderer.DefaultWordRenderer;
+import nl.captcha.text.renderer.WordRenderer;
+
+
+/**
+ * Simple CAPTCHA bean intended to be used by Spring.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James
+ *
+ */
+public class CaptchaBean {
+ private BackgroundProducer _bgProd = new TransparentBackgroundProducer();
+ private TextProducer _txtProd;
+ private NoiseProducer _noiseProd;
+ private GimpyRenderer _gimpy;
+ private boolean _addBorder = false;
+
+ private String _answer = "";
+ private BufferedImage _img;
+ private BufferedImage _bg;
+
+ public CaptchaBean(int width, int height) {
+ _img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ }
+
+ public CaptchaBean build() {
+ // Add and render the text
+ if (_txtProd != null) {
+ _answer += _txtProd.getText();
+ WordRenderer wr = new DefaultWordRenderer();
+ wr.render(_answer, _img);
+ }
+
+ if (_noiseProd != null) {
+ _noiseProd.makeNoise(_img);
+ }
+
+ if (_gimpy != null) {
+ _gimpy.gimp(_img);
+ }
+
+ _bg = _bgProd.getBackground(_img.getWidth(), _img.getHeight());
+
+ // Paint the main image over the background
+ Graphics2D g = _bg.createGraphics();
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
+ g.drawImage(_img, null, null);
+
+ // Add the border, if necessary
+ if (_addBorder) {
+ int width = _img.getWidth();
+ int height = _img.getHeight();
+
+ g.setColor(Color.BLACK);
+ g.drawLine(0, 0, 0, width);
+ g.drawLine(0, 0, width, 0);
+ g.drawLine(0, height - 1, width, height - 1);
+ g.drawLine(width - 1, height - 1, width - 1, 0);
+ }
+ _img = _bg;
+ g.dispose();
+
+ return this;
+ }
+
+ public boolean isCorrect(String answer) {
+ return answer.equals(_answer);
+ }
+
+ public BufferedImage getImage() {
+ return _img;
+ }
+
+ public BackgroundProducer getBgProd() {
+ return _bgProd;
+ }
+ public void setBgProd(BackgroundProducer bgProd) {
+ _bgProd = bgProd;
+ }
+ public TextProducer getTxtProd() {
+ return _txtProd;
+ }
+ public void setTxtProd(TextProducer txtProd) {
+ _txtProd = txtProd;
+ }
+ public NoiseProducer getNoiseProd() {
+ return _noiseProd;
+ }
+ public void setNoiseProd(NoiseProducer noiseProd) {
+ _noiseProd = noiseProd;
+ }
+ public GimpyRenderer getGimpy() {
+ return _gimpy;
+ }
+ public void setGimpy(GimpyRenderer gimpy) {
+ _gimpy = gimpy;
+ }
+ public boolean isAddBorder() {
+ return _addBorder;
+ }
+ public void setAddBorder(boolean addBorder) {
+ _addBorder = addBorder;
+ }
+ public String getAnswer() {
+ return _answer;
+ }
+ public void setAnswer(String answer) {
+ _answer = answer;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/BackgroundProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,21 @@
+package nl.captcha.backgrounds;
+
+import java.awt.image.BufferedImage;
+
+/**
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public interface BackgroundProducer {
+
+ /**
+ * Add the background to the given image.
+ *
+ * @param image
+ * @return
+ */
+ public BufferedImage addBackground(BufferedImage image);
+
+ public BufferedImage getBackground(int width, int height);
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/FlatColorBackgroundProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,38 @@
+package nl.captcha.backgrounds;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+public final class FlatColorBackgroundProducer implements BackgroundProducer {
+
+ private Color _color = Color.GRAY;
+
+ public FlatColorBackgroundProducer() {
+ this(Color.GRAY);
+ }
+
+ public FlatColorBackgroundProducer(Color color) {
+ _color = color;
+ }
+
+ public BufferedImage addBackground(BufferedImage bi) {
+ int width = bi.getWidth();
+ int height = bi.getHeight();
+ return this.getBackground(width, height);
+ }
+
+ public BufferedImage getBackground(int width, int height) {
+ BufferedImage img = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics2D graphics = img.createGraphics();
+ graphics.setPaint(_color);
+ graphics.fill(new Rectangle2D.Double(0, 0, width, height));
+ graphics.drawImage(img, 0, 0, null);
+ graphics.dispose();
+
+ return img;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/GradiatedBackgroundProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,64 @@
+package nl.captcha.backgrounds;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Creates a gradiated background with the given <i>from</i> and <i>to</i>
+ * Color values. If none are specified they default to light gray and white
+ * respectively.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class GradiatedBackgroundProducer implements BackgroundProducer {
+
+ private Color _fromColor = Color.DARK_GRAY;
+ private Color _toColor = Color.WHITE;
+
+ public BufferedImage getBackground(int width, int height) {
+ // create an opaque image
+ BufferedImage img = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+
+ Graphics2D g = img.createGraphics();
+ RenderingHints hints = new RenderingHints(
+ RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+
+ g.setRenderingHints(hints);
+
+ // create the gradient color
+ GradientPaint ytow = new GradientPaint(0, 0, _fromColor, width, height,
+ _toColor);
+
+ g.setPaint(ytow);
+ // draw gradient color
+ g.fill(new Rectangle2D.Double(0, 0, width, height));
+
+ // draw the transparent image over the background
+ g.drawImage(img, 0, 0, null);
+ g.dispose();
+
+ return img;
+ }
+
+ public BufferedImage addBackground(BufferedImage image) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+
+ return getBackground(width, height);
+ }
+
+ public void setFromColor(Color fromColor) {
+ _fromColor = fromColor;
+ }
+
+ public void setToColor(Color toColor) {
+ _toColor = toColor;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/SquigglesBackgroundProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,49 @@
+package nl.captcha.backgrounds;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Graphics2D;
+import java.awt.geom.Arc2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Adds a black and white squiggly background to the image.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class SquigglesBackgroundProducer implements BackgroundProducer {
+
+ public BufferedImage addBackground(BufferedImage image) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+ return getBackground(width, height);
+ }
+
+ public BufferedImage getBackground(int width, int height) {
+ BufferedImage result = new BufferedImage(width, height,
+ BufferedImage.TYPE_INT_RGB);
+ Graphics2D graphics = result.createGraphics();
+
+ BasicStroke bs = new BasicStroke(2.0f, BasicStroke.CAP_BUTT,
+ BasicStroke.JOIN_MITER, 2.0f, new float[] { 2.0f, 2.0f }, 0.0f);
+ graphics.setStroke(bs);
+ AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
+ 0.75f);
+ graphics.setComposite(ac);
+
+ graphics.translate(width * -1.0, 0.0);
+ double delta = 5.0;
+ double xt;
+ double ts = 0.0;
+ for (xt = 0.0; xt < (2.0 * width); xt += delta) {
+ Arc2D arc = new Arc2D.Double(0, 0, width, height, 0.0, 360.0,
+ Arc2D.OPEN);
+ graphics.draw(arc);
+ graphics.translate(delta, 0.0);
+ ts += delta;
+ }
+ graphics.dispose();
+ return result;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/backgrounds/TransparentBackgroundProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,29 @@
+package nl.captcha.backgrounds;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Generates a transparent background.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class TransparentBackgroundProducer implements BackgroundProducer {
+
+ public BufferedImage addBackground(BufferedImage image) {
+ return getBackground(image.getWidth(), image.getHeight());
+ }
+
+ public BufferedImage getBackground(int width, int height) {
+ BufferedImage bg = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
+ Graphics2D g = bg.createGraphics();
+
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+ g.fillRect(0, 0, width, height);
+
+ return bg;
+ }
+
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/BlockGimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,28 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+import com.jhlabs.image.BlockFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+public class BlockGimpyRenderer implements GimpyRenderer {
+
+ private static final int DEF_BLOCK_SIZE = 3;
+ private final int _blockSize;
+
+ public BlockGimpyRenderer() {
+ this(DEF_BLOCK_SIZE);
+ }
+
+ public BlockGimpyRenderer(int blockSize) {
+ _blockSize = blockSize;
+ }
+
+ public void gimp(BufferedImage image) {
+ BlockFilter filter = new BlockFilter();
+ filter.setBlockSize(_blockSize);
+
+ BufferedImage buffer = filter.filter(image, null);
+ applyFilter(buffer, null);
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/DropShadowGimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,38 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+import com.jhlabs.image.ShadowFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+/**
+ * Twists text and adds a dark drop-shadow.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class DropShadowGimpyRenderer implements GimpyRenderer {
+ private static final int DEFAULT_RADIUS = 3;
+ private static final int DEFAULT_OPACITY = 75;
+
+ private final int _radius;
+ private final int _opacity;
+
+ public DropShadowGimpyRenderer() {
+ this(DEFAULT_RADIUS, DEFAULT_OPACITY);
+ }
+
+ public DropShadowGimpyRenderer(int radius, int opacity) {
+ _radius = radius;
+ _opacity = opacity;
+ }
+
+ public void gimp(BufferedImage image) {
+ ShadowFilter sFilter = new ShadowFilter();
+ sFilter.setRadius(_radius);
+ sFilter.setOpacity(_opacity);
+
+ BufferedImage buffer = sFilter.filter(image, null);
+ applyFilter(buffer, null);
+ }
+}
\ No newline at end of file
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/FishEyeGimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,107 @@
+package nl.captcha.gimpy;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Overlays a warped grid to the image.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class FishEyeGimpyRenderer implements GimpyRenderer {
+ private final Color _hColor;
+ private final Color _vColor;
+
+ public FishEyeGimpyRenderer() {
+ this(Color.BLACK, Color.BLACK);
+ }
+
+ public FishEyeGimpyRenderer(Color hColor, Color vColor) {
+ _hColor = hColor;
+ _vColor = vColor;
+ }
+
+ public void gimp(BufferedImage image) {
+ int height = image.getHeight();
+ int width = image.getWidth();
+
+ int hstripes = height / 7;
+ int vstripes = width / 7;
+
+ // Calculate space between lines
+ int hspace = height / (hstripes + 1);
+ int vspace = width / (vstripes + 1);
+
+ Graphics2D graph = (Graphics2D) image.getGraphics();
+ // Draw the horizontal stripes
+ for (int i = hspace; i < height; i = i + hspace) {
+ graph.setColor(_hColor);
+ graph.drawLine(0, i, width, i);
+ }
+
+ // Draw the vertical stripes
+ for (int i = vspace; i < width; i = i + vspace) {
+ graph.setColor(_vColor);
+ graph.drawLine(i, 0, i, height);
+ }
+
+ // Create a pixel array of the original image.
+ // we need this later to do the operations on..
+ int pix[] = new int[height * width];
+ int j = 0;
+
+ for (int j1 = 0; j1 < width; j1++) {
+ for (int k1 = 0; k1 < height; k1++) {
+ pix[j] = image.getRGB(j1, k1);
+ j++;
+ }
+ }
+
+ double distance = ranInt(width / 4, width / 3);
+
+ // put the distortion in the (dead) middle
+ int wMid = image.getWidth() / 2;
+ int hMid = image.getHeight() / 2;
+
+ // again iterate over all pixels..
+ for (int x = 0; x < image.getWidth(); x++) {
+ for (int y = 0; y < image.getHeight(); y++) {
+
+ int relX = x - wMid;
+ int relY = y - hMid;
+
+ double d1 = Math.sqrt(relX * relX + relY * relY);
+ if (d1 < distance) {
+
+ int j2 = wMid
+ + (int) (((fishEyeFormula(d1 / distance) * distance) / d1) * (x - wMid));
+ int k2 = hMid
+ + (int) (((fishEyeFormula(d1 / distance) * distance) / d1) * (y - hMid));
+ image.setRGB(x, y, pix[j2 * height + k2]);
+ }
+ }
+ }
+
+ graph.dispose();
+ }
+
+ private final int ranInt(int i, int j) {
+ double d = Math.random();
+ return (int) (i + ((j - i) + 1) * d);
+ }
+
+ private final double fishEyeFormula(double s) {
+ // implementation of:
+ // g(s) = - (3/4)s3 + (3/2)s2 + (1/4)s, with s from 0 to 1.
+ if (s < 0.0D) {
+ return 0.0D;
+ }
+ if (s > 1.0D) {
+ return s;
+ }
+
+ return -0.75D * s * s * s + 1.5D * s * s + 0.25D * s;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/GimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,12 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+
+public interface GimpyRenderer {
+ public void gimp(BufferedImage image);
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/RippleGimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,33 @@
+package nl.captcha.gimpy;
+
+import java.awt.image.BufferedImage;
+
+import com.jhlabs.image.RippleFilter;
+import com.jhlabs.image.TransformFilter;
+
+import static nl.captcha.util.ImageUtil.applyFilter;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class RippleGimpyRenderer implements GimpyRenderer {
+
+ /**
+ * Apply a RippleFilter to the image.
+ *
+ * @param image The image to be distorted
+ */
+ public void gimp(BufferedImage image) {
+ RippleFilter filter = new RippleFilter();
+ filter.setWaveType(RippleFilter.SINE);
+ filter.setXAmplitude(2.6f);
+ filter.setYAmplitude(1.7f);
+ filter.setXWavelength(15);
+ filter.setYWavelength(5);
+
+ filter.setEdgeAction(TransformFilter.BILINEAR);
+
+ BufferedImage buffer = filter.filter(image, null);
+ applyFilter(buffer, null);
+ }
+}
\ No newline at end of file
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/gimpy/ShearGimpyRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,67 @@
+package nl.captcha.gimpy;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.Random;
+
+public class ShearGimpyRenderer implements GimpyRenderer {
+
+ private final Random _gen = new SecureRandom();
+ private final Color _color;
+
+ public ShearGimpyRenderer() {
+ this(Color.GRAY);
+ }
+
+ public ShearGimpyRenderer(Color color) {
+ _color = color;
+ }
+
+ public void gimp(BufferedImage bi) {
+ Graphics2D g = bi.createGraphics();
+ shearX(g, bi.getWidth(), bi.getHeight());
+ shearY(g, bi.getWidth(), bi.getHeight());
+ g.dispose();
+ }
+
+ private void shearX(Graphics2D g, int w1, int h1) {
+ int period = _gen.nextInt(10) + 5;
+
+ boolean borderGap = true;
+ int frames = 15;
+ int phase = _gen.nextInt(5) + 2;
+
+ for (int i = 0; i < h1; i++) {
+ double d = (period >> 1)
+ * Math.sin((double) i / (double) period
+ + (6.2831853071795862D * phase) / frames);
+ g.copyArea(0, i, w1, 1, (int) d, 0);
+ if (borderGap) {
+ g.setColor(_color);
+ g.drawLine((int) d, i, 0, i);
+ g.drawLine((int) d + w1, i, w1, i);
+ }
+ }
+ }
+
+ private void shearY(Graphics2D g, int w1, int h1) {
+ int period = _gen.nextInt(30) + 10; // 50;
+
+ boolean borderGap = true;
+ int frames = 15;
+ int phase = 7;
+ for (int i = 0; i < w1; i++) {
+ double d = (period >> 1)
+ * Math.sin((float) i / period
+ + (6.2831853071795862D * phase) / frames);
+ g.copyArea(i, 0, 1, h1, 0, (int) d);
+ if (borderGap) {
+ g.setColor(_color);
+ g.drawLine(i, (int) d, i, 0);
+ g.drawLine(i, (int) d + h1, i, h1);
+ }
+ }
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/CurvedLineNoiseProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,87 @@
+package nl.captcha.noise;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.geom.CubicCurve2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * Adds a randomly curved line to the image.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class CurvedLineNoiseProducer implements NoiseProducer {
+
+ private static final Random RAND = new SecureRandom();
+
+ private final Color _color;
+ private final float _width;
+
+ public CurvedLineNoiseProducer() {
+ this(Color.BLACK, 3.0f);
+ }
+
+ public CurvedLineNoiseProducer(Color color, float width) {
+ _color = color;
+ _width = width;
+ }
+
+ public void makeNoise(BufferedImage image) {
+ int width = image.getWidth();
+ int height = image.getHeight();
+
+ // the curve from where the points are taken
+ CubicCurve2D cc = new CubicCurve2D.Float(width * .1f, height
+ * RAND.nextFloat(), width * .1f, height
+ * RAND.nextFloat(), width * .25f, height
+ * RAND.nextFloat(), width * .9f, height
+ * RAND.nextFloat());
+
+ // creates an iterator to define the boundary of the flattened curve
+ PathIterator pi = cc.getPathIterator(null, 2);
+ Point2D tmp[] = new Point2D[200];
+ int i = 0;
+
+ // while pi is iterating the curve, adds points to tmp array
+ while (!pi.isDone()) {
+ float[] coords = new float[6];
+ switch (pi.currentSegment(coords)) {
+ case PathIterator.SEG_MOVETO:
+ case PathIterator.SEG_LINETO:
+ tmp[i] = new Point2D.Float(coords[0], coords[1]);
+ }
+ i++;
+ pi.next();
+ }
+
+ // the points where the line changes the stroke and direction
+ Point2D[] pts = new Point2D[i];
+ // copies points from tmp to pts
+ System.arraycopy(tmp, 0, pts, 0, i);
+
+ Graphics2D graph = (Graphics2D) image.getGraphics();
+ graph.setRenderingHints(new RenderingHints(
+ RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON));
+
+ graph.setColor(_color);
+
+ // for the maximum 3 point change the stroke and direction
+ for (i = 0; i < pts.length - 1; i++) {
+ if (i < 3) {
+ graph.setStroke(new BasicStroke(_width));
+ }
+ graph.drawLine((int) pts[i].getX(), (int) pts[i].getY(),
+ (int) pts[i + 1].getX(), (int) pts[i + 1].getY());
+ }
+
+ graph.dispose();
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/NoiseProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,11 @@
+package nl.captcha.noise;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public interface NoiseProducer {
+ public void makeNoise(BufferedImage image);
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/noise/StraightLineNoiseProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,78 @@
+package nl.captcha.noise;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+
+/**
+ * Draws a 4-pixel thick straight red line through the given image.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class StraightLineNoiseProducer implements NoiseProducer {
+
+ private final Color _color;
+ private final int _thickness;
+ private final SecureRandom _gen = new SecureRandom();
+
+ /**
+ * Default constructor creates a 4-pixel wide red line.
+ */
+ public StraightLineNoiseProducer() {
+ this(Color.RED, 4);
+ }
+
+ public StraightLineNoiseProducer(Color color, int thickness) {
+ _color = color;
+ _thickness = thickness;
+ }
+
+ public void makeNoise(BufferedImage image) {
+ Graphics2D graphics = image.createGraphics();
+ int height = image.getHeight();
+ int width = image.getWidth();
+ int y1 = _gen.nextInt(height) + 1;
+ int y2 = _gen.nextInt(height) + 1;
+ drawLine(graphics, y1, width, y2);
+ }
+
+ private void drawLine(Graphics g, int y1, int x2, int y2) {
+ int X1 = 0;
+
+ // The thick line is in fact a filled polygon
+ g.setColor(_color);
+ int dX = x2 - X1;
+ int dY = y2 - y1;
+ // line length
+ double lineLength = Math.sqrt(dX * dX + dY * dY);
+
+ double scale = _thickness / (2 * lineLength);
+
+ // The x and y increments from an endpoint needed to create a
+ // rectangle...
+ double ddx = -scale * dY;
+ double ddy = scale * dX;
+ ddx += (ddx > 0) ? 0.5 : -0.5;
+ ddy += (ddy > 0) ? 0.5 : -0.5;
+ int dx = (int) ddx;
+ int dy = (int) ddy;
+
+ // Now we can compute the corner points...
+ int xPoints[] = new int[4];
+ int yPoints[] = new int[4];
+
+ xPoints[0] = X1 + dx;
+ yPoints[0] = y1 + dy;
+ xPoints[1] = X1 - dx;
+ yPoints[1] = y1 - dy;
+ xPoints[2] = x2 - dx;
+ yPoints[2] = y2 - dy;
+ xPoints[3] = x2 + dx;
+ yPoints[3] = y2 + dy;
+
+ g.fillPolygon(xPoints, yPoints, 4);
+ }
+}
\ No newline at end of file
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/CaptchaServletUtil.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,30 @@
+package nl.captcha.servlet;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+
+public final class CaptchaServletUtil {
+
+ public static void writeImage(HttpServletResponse response, BufferedImage bi) {
+ response.setHeader("Cache-Control", "private,no-cache,no-store");
+ response.setContentType("image/png"); // PNGs allow for transparency. JPGs do not.
+ try {
+ writeImage(response.getOutputStream(), bi);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void writeImage(OutputStream os, BufferedImage bi) {
+ try {
+ ImageIO.write(bi, "png", os);
+ os.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/ChineseCaptchaServlet.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,49 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import nl.captcha.Captcha;
+import nl.captcha.backgrounds.GradiatedBackgroundProducer;
+import nl.captcha.text.producer.ChineseTextProducer;
+
+/**
+ * Generate a CAPTCHA image/answer pair using Chinese characters.
+ *
+ * @author <a href="james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class ChineseCaptchaServlet extends SimpleCaptchaServlet {
+
+ private static final long serialVersionUID = -66324012009340831L;
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ HttpSession session = req.getSession();
+ Captcha captcha;
+ if (session.getAttribute(NAME) == null) {
+ captcha = new Captcha.Builder(_width, _height)
+ .addText(new ChineseTextProducer())
+ .gimp()
+ .addBorder()
+ .addNoise()
+ .addBackground(new GradiatedBackgroundProducer())
+ .build();
+
+ session.setAttribute(NAME, captcha);
+ CaptchaServletUtil.writeImage(resp, captcha.getImage());
+
+ return;
+ }
+
+ captcha = (Captcha) session.getAttribute(NAME);
+ CaptchaServletUtil.writeImage(resp, captcha.getImage());
+ }
+}
\ No newline at end of file
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/SimpleCaptchaServlet.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,58 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import nl.captcha.Captcha;
+import nl.captcha.backgrounds.GradiatedBackgroundProducer;
+
+
+/**
+ * Generates, displays, and stores in session a 200x50 CAPTCHA image with sheared black text,
+ * a solid dark grey background, and a straight, slanted red line through the text.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class SimpleCaptchaServlet extends HttpServlet {
+
+ private static final long serialVersionUID = 1L;
+
+ private static final String PARAM_HEIGHT = "height";
+ private static final String PARAM_WIDTH = "width";
+
+ protected int _width = 200;
+ protected int _height = 50;
+
+ @Override
+ public void init() throws ServletException {
+ if (getInitParameter(PARAM_HEIGHT) != null) {
+ _height = Integer.valueOf(getInitParameter(PARAM_HEIGHT));
+ }
+
+ if (getInitParameter(PARAM_WIDTH) != null) {
+ _width = Integer.valueOf(getInitParameter(PARAM_WIDTH));
+ }
+ }
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+
+ Captcha captcha = new Captcha.Builder(_width, _height)
+ .addText()
+ .addBackground(new GradiatedBackgroundProducer())
+ .gimp()
+ .addNoise()
+ .addBorder()
+ .build();
+
+ CaptchaServletUtil.writeImage(resp, captcha.getImage());
+ req.getSession().setAttribute(NAME, captcha);
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/servlet/StickyCaptchaServlet.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,74 @@
+package nl.captcha.servlet;
+
+import static nl.captcha.Captcha.NAME;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import nl.captcha.Captcha;
+
+
+/**
+ * Builds a 200x50 (default) CAPTCHA and attaches it to the session. This is intended to help prevent
+ * bots from simply reloading the page and getting new images until one is
+ * generated which they can successfully parse. Removal of the session attribute
+ * <code>CaptchaServletUtil.NAME</code> will force a new <code>Captcha</code>
+ * to be added to the session.
+ *
+ * <p>Image height and width may be customized by adding the "heigh" and "width" init-params to
+ * web.xml. For example:</p>
+ * <p><pre> <servlet>
+ <servlet-name>StickyCaptcha</servlet-name>
+ <servlet-class>nl.captcha.servlet.StickyCaptchaServlet</servlet-class>
+ <init-param>
+ <param-name>width</param-name>
+ <param-value>250</param-value>
+ </init-param>
+ <init-param>
+ <param-name>height</param-name>
+ <param-value>75</param-value>
+ </init-param>
+ </servlet>
+</pre></p>
+
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class StickyCaptchaServlet extends SimpleCaptchaServlet {
+
+ private static final long serialVersionUID = 40913456229L;
+
+ /**
+ * Write out the CAPTCHA image stored in the session. If not present,
+ * generate a new <code>Captcha</code> and write out its image.
+ *
+ */
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException {
+ HttpSession session = req.getSession();
+ Captcha captcha;
+ if (session.getAttribute(NAME) == null) {
+ captcha = new Captcha.Builder(_width, _height)
+ .addText()
+ .gimp()
+ .addBorder()
+ .addNoise()
+ .addBackground()
+ .build();
+
+ session.setAttribute(NAME, captcha);
+ CaptchaServletUtil.writeImage(resp, captcha.getImage());
+
+ return;
+ }
+
+ captcha = (Captcha) session.getAttribute(NAME);
+ CaptchaServletUtil.writeImage(resp, captcha.getImage());
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,43 @@
+package nl.captcha.text.producer;
+
+/**
+ * TextProducer implementation that will return Chinese characters.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class ChineseTextProducer implements TextProducer {
+
+ static final int DEFAULT_LENGTH = 5;
+ // Here's hoping none of the characters in this range are offensive.
+ static final int CODE_POINT_START = 0x4E00;
+ static final int CODE_POINT_END = 0x4F6F;
+ private static final int NUM_CHARS = CODE_POINT_END - CODE_POINT_START;
+
+ private final TextProducer _txtProd; // Decorator
+
+ /**
+ * The default constructor will generate five Chinese characters.
+ *
+ */
+ public ChineseTextProducer() {
+ this(DEFAULT_LENGTH);
+ }
+
+ /**
+ * Generate <code>length</code> number of Chinese characters.
+ *
+ * @param length
+ */
+ public ChineseTextProducer(int length) {
+ char[] chars = new char[NUM_CHARS];
+ for (char c = CODE_POINT_START, i = 0; c < CODE_POINT_END; c++, i++) {
+ chars[i] = Character.valueOf(c);
+ }
+ _txtProd = new DefaultTextProducer(length, chars);
+ }
+
+ public String getText() {
+ return _txtProd.getText();
+ }
+}
Property changes on: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/ChineseTextProducer.java
___________________________________________________________________
Name: svn:executable
+ *
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/DefaultTextProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,57 @@
+package nl.captcha.text.producer;
+
+import java.security.SecureRandom;
+import java.util.Arrays;
+import java.util.Random;
+
+/**
+ * Produces text of a given length from a given array of characters. The default (no-args)
+ * constructor produces five Latin characters from a specific set of alphanumerics. Characters
+ * such as "1" (one) and "l" (lower-case 'ell') have been removed to reduce ambiguity in the
+ * generated CAPTCHA.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class DefaultTextProducer implements TextProducer {
+
+ private static final Random _gen = new SecureRandom();
+ private static final int DEFAULT_LENGTH = 5;
+ private static final char[] DEFAULT_CHARS = new char[] { 'a', 'b', 'c', 'd',
+ 'e', 'f', 'g', 'h', 'k', 'm', 'n', 'p', 'r', 'w', 'x', 'y',
+ '2', '3', '4', '5', '6', '7', '8', };
+
+ private final int _length;
+ private final char[] _srcChars;
+
+ public DefaultTextProducer() {
+ this(DEFAULT_LENGTH, DEFAULT_CHARS);
+ }
+
+ public DefaultTextProducer(int length) {
+ this(length, DEFAULT_CHARS);
+ }
+
+ public DefaultTextProducer(int length, char[] srcChars) {
+ _length = length;
+ _srcChars = srcChars != null ? copyOf(srcChars, srcChars.length) : DEFAULT_CHARS;
+ }
+
+ public String getText() {
+ int car = _srcChars.length - 1;
+
+ String capText = "";
+ for (int i = 0; i < _length; i++) {
+ capText += _srcChars[_gen.nextInt(car) + 1];
+ }
+
+ return capText;
+ }
+
+ public static char[] copyOf(char[] original, int newLength) {
+ char[] copy = new char[newLength];
+ System.arraycopy(original, 0, copy, 0,
+ Math.min(original.length, newLength));
+ return copy;
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/FiveLetterFirstNameTextProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,1054 @@
+package nl.captcha.text.producer;
+
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class FiveLetterFirstNameTextProducer implements TextProducer {
+
+ private static final Random GENERATOR = new SecureRandom();
+ private static final String[] FIRST_NAMES = new String[] { "jomah",
+ "yanae", "dagna", "aadel", "aaden", "aafia", "aamir", "aaran",
+ "aaren", "aaric", "aarin", "aarle", "aaron", "aarti", "aaryn",
+ "aasia", "aasif", "aasim", "abame", "abani", "abasi", "abbah",
+ "abban", "abbia", "abbie", "abbud", "abbye", "abdel", "abdou",
+ "abdul", "abdur", "abdus", "abebe", "abebi", "abeer", "abeli",
+ "abena", "abeni", "abhay", "abias", "abida", "abiel", "abija",
+ "abina", "abira", "abnar", "abner", "abnor", "aboor", "abott",
+ "abram", "abran", "abree", "abril", "abuid", "aceng", "achal",
+ "achaz", "achim", "achin", "acima", "ackim", "acree", "adala",
+ "adali", "adaly", "adama", "adamo", "adamu", "adara", "addal",
+ "addam", "addar", "addey", "addia", "addie", "addis", "adeen",
+ "adela", "adele", "adell", "adena", "adene", "adham", "adiah",
+ "adiba", "adiel", "adika", "adila", "adima", "adina", "adine",
+ "adira", "aditi", "adiva", "adjoa", "adlai", "adlan", "adlar",
+ "adler", "adley", "adlin", "adlyn", "admad", "admir", "admon",
+ "adnah", "adnan", "adnet", "adney", "adnot", "adola", "adolf",
+ "adoum", "adrea", "adrie", "adrik", "adron", "aemon", "aeric",
+ "aerin", "aesha", "afemo", "afeni", "affan", "affra", "afida",
+ "afsar", "aftan", "aftyn", "agace", "agafi", "agapi", "agata",
+ "aggye", "aghar", "aghna", "agias", "agnar", "agota", "agote",
+ "agoti", "agron", "ahanu", "ahava", "ahdaf", "ahern", "ahiva",
+ "ahlam", "ahley", "ahmad", "ahman", "ahmed", "ahmet", "ahran",
+ "ahren", "ahrin", "ahsan", "ahuda", "ahuva", "ahvie", "aidah",
+ "aidan", "aiden", "aidya", "aiken", "aikin", "ailee", "ailey",
+ "ailie", "ailin", "ailis", "ailli", "ailsa", "ailse", "aimal",
+ "aimee", "aimey", "aimia", "aimie", "aimil", "aimon", "ainah",
+ "ainka", "ainur", "airat", "airel", "airic", "airle", "aisha",
+ "aisia", "aitan", "aitor", "aizik", "ajaib", "ajali", "ajani",
+ "ajaya", "ajeya", "ajhon", "ajith", "ajmal", "ajsha", "akako",
+ "akara", "akash", "akati", "akbar", "akeam", "akeel", "akeem",
+ "akemi", "akhil", "akiba", "akiel", "akiem", "akiko", "akila",
+ "akili", "akima", "akins", "akira", "akiva", "akiyo", "akmal",
+ "akono", "akram", "aksel", "alade", "alaen", "alaia", "alain",
+ "alair", "alaka", "alana", "alani", "alann", "alano", "alard",
+ "alayn", "alban", "alben", "alber", "albie", "albis", "alcot",
+ "aldas", "aldea", "alden", "aldie", "aldin", "aldis", "aldon",
+ "aldus", "aldya", "aleah", "aleco", "aleda", "aleea", "aleen",
+ "aleia", "aleix", "alejo", "aleka", "aleki", "aleks", "alena",
+ "alene", "aleni", "aleta", "alexa", "alexi", "alexx", "alexy",
+ "aleya", "alfeo", "alfie", "alfio", "alfre", "alfri", "algar",
+ "algey", "algie", "algis", "algon", "alica", "alice", "alick",
+ "alida", "alies", "alija", "alika", "alina", "alisa", "alise",
+ "alisz", "alita", "alixe", "aliye", "aliza", "alize", "alkis",
+ "alkot", "allam", "allan", "allax", "allda", "allea", "allen",
+ "alles", "allex", "allfy", "allie", "allin", "allix", "allma",
+ "allon", "allta", "allyn", "allys", "almaz", "almil", "almir",
+ "alois", "alojz", "aloke", "alona", "aloni", "aloys", "alphy",
+ "alpin", "alred", "alric", "alrik", "alroy", "altaf", "alten",
+ "aluin", "aluki", "aluna", "alura", "aluse", "alvah", "alvan",
+ "alven", "alves", "alvie", "alvin", "alvis", "alvyn", "alvys",
+ "alwan", "alwin", "alwyn", "alyce", "alyda", "alyma", "alyna",
+ "alyne", "alynn", "alysa", "alyse", "alyso", "alyss", "amada",
+ "amado", "amadu", "amahd", "amahl", "amaka", "amaly", "amare",
+ "amary", "amasa", "amata", "amato", "amaui", "amaya", "ambie",
+ "ambra", "ambur", "amela", "amena", "amery", "amiah", "amica",
+ "amiel", "amiet", "amijo", "amiko", "amina", "amira", "amirh",
+ "amiri", "amisa", "amita", "amjad", "ammar", "ammer", "ammie",
+ "amneh", "amnon", "amona", "amory", "amrit", "amyas", "amyot",
+ "amyra", "amzie", "anais", "anaka", "anand", "anant", "ancel",
+ "andee", "ander", "andie", "andis", "andje", "andon", "andor",
+ "andra", "andre", "andri", "andru", "andry", "aneel", "aneka",
+ "anela", "aneta", "anete", "anett", "aneva", "angee", "angen",
+ "angey", "angie", "angil", "aniah", "anica", "anice", "anida",
+ "aniel", "anier", "anika", "aniko", "anina", "anisa", "anita",
+ "aniya", "anjel", "anjil", "ankie", "annee", "annes", "anney",
+ "annia", "annie", "annik", "annis", "annot", "annus", "annys",
+ "annza", "anoki", "anoop", "anora", "anouk", "anour", "ansam",
+ "ansel", "ansly", "anson", "ansor", "anssi", "ansun", "antaw",
+ "antha", "anthe", "antia", "antin", "antje", "anton", "antos",
+ "antti", "anuja", "anwar", "anwel", "anwen", "anwil", "anwyl",
+ "anwyn", "anyes", "aoife", "aphra", "apolo", "aponi", "apryl",
+ "aquil", "aralt", "arash", "arata", "arati", "arbel", "arben",
+ "archy", "ardah", "ardal", "ardia", "ardie", "ardin", "ardis",
+ "ardly", "ardon", "ardra", "ardys", "areck", "areen", "arela",
+ "areli", "arese", "areta", "argeo", "arial", "arick", "arics",
+ "arieh", "arien", "ariez", "arija", "arika", "arild", "arina",
+ "arinn", "arisa", "ariya", "ariza", "arize", "arjen", "arkan",
+ "arkin", "arkyn", "arlan", "arlea", "arlee", "arlen", "arlet",
+ "arley", "arlie", "arlin", "arlis", "arlyn", "armad", "arman",
+ "armin", "armon", "arnat", "arndt", "arnel", "arnet", "arney",
+ "arnie", "arnis", "arnny", "arnoe", "arnon", "arnou", "aroni",
+ "arren", "arria", "arric", "arrik", "arrio", "arron", "arryo",
+ "arsen", "artek", "artha", "arthi", "artie", "artin", "artis",
+ "artor", "artur", "artus", "aruna", "aruns", "arvah", "arvid",
+ "arvie", "arvon", "arwel", "arwen", "arwin", "arwyn", "aryeh",
+ "aryel", "asaad", "asafa", "asano", "asaph", "aseel", "ashah",
+ "ashar", "ashby", "ashia", "ashis", "ashla", "ashli", "ashly",
+ "ashon", "ashor", "asiah", "asiak", "asier", "asifa", "asiff",
+ "asima", "asiri", "asish", "asius", "aslak", "aslan", "aslin",
+ "asmaa", "asmus", "asoke", "asoma", "aspar", "asril", "asror",
+ "assad", "assaf", "assem", "assia", "assie", "asten", "astin",
+ "astra", "astri", "aswin", "aswyn", "atala", "atara", "atera",
+ "athan", "athie", "athol", "athra", "atida", "atifa", "atila",
+ "atima", "atina", "atiya", "atlea", "atley", "atner", "atrie",
+ "attie", "atyaf", "auban", "auben", "aubra", "aubre", "aubri",
+ "aubry", "audon", "audra", "audre", "audri", "audry", "audun",
+ "audun", "auggy", "augie", "aukai", "aulii", "aurea", "aurek",
+ "aurel", "aurey", "auria", "aurie", "ausaf", "ausra", "autry",
+ "autum", "auvit", "avada", "avais", "avari", "avary", "aveen",
+ "avent", "avern", "avery", "avice", "aviel", "aviva", "avivi",
+ "aviya", "avner", "avnit", "avram", "avrel", "avril", "avrim",
+ "avrit", "avrom", "avrum", "avtar", "awani", "axell", "axill",
+ "axton", "ayaan", "ayaaz", "ayako", "ayala", "ayame", "ayana",
+ "aydan", "ayden", "ayers", "ayham", "ayhan", "ayisa", "ayken",
+ "aykin", "aylee", "aylie", "aymen", "aymer", "aymil", "aymon",
+ "aynor", "ayoka", "ayrel", "ayres", "aysel", "aysha", "ayshe",
+ "aysia", "ayson", "aytac", "aytza", "ayubu", "ayumi", "ayzan",
+ "azael", "azami", "azaya", "azhar", "azibo", "azita", "aziza",
+ "azize", "azizi", "azmat", "azora", "azuba", "azura", "azwar",
+ "azzam", "babak", "babek", "babet", "babsy", "badal", "badih",
+ "badja", "badra", "badri", "bagot", "bahaa", "baher", "bahni",
+ "bahri", "baila", "baily", "baird", "bakri", "balak", "balal",
+ "balin", "bamby", "bandi", "banky", "bantz", "baqir", "barba",
+ "barbi", "barby", "barie", "barna", "barri", "barrt", "barta",
+ "barto", "bartt", "barty", "bartz", "barun", "baryn", "basak",
+ "basam", "basem", "basia", "basir", "basma", "basob", "basya",
+ "batia", "batya", "bauby", "baxie", "baxty", "bayly", "bayne",
+ "bayrd", "bazek", "bazel", "bazil", "beale", "beall", "beals",
+ "beann", "beate", "beaty", "beavo", "bebba", "bebel", "becca",
+ "becka", "becki", "becky", "bejun", "bekka", "bekki", "belal",
+ "belia", "bella", "bello", "belva", "beman", "benay", "benci",
+ "benek", "bengt", "benio", "benja", "benji", "benke", "benna",
+ "benno", "bennt", "benon", "bente", "bentz", "benyu", "benzi",
+ "beppe", "beppo", "berdj", "berdy", "beren", "bergh", "beril",
+ "berit", "berje", "berke", "berky", "berla", "berly", "berna",
+ "bernd", "berni", "berno", "bernt", "berny", "berte", "berti",
+ "berto", "berty", "besse", "bessi", "bessy", "betha", "bethe",
+ "betia", "betka", "betsi", "betsy", "bette", "betti", "betto",
+ "betul", "beula", "bevan", "beven", "bevin", "bevis", "bevon",
+ "bevys", "beyla", "beyle", "bheki", "biago", "biala", "biana",
+ "bibha", "bijan", "bikas", "bilal", "bilee", "billa", "bille",
+ "billi", "bimia", "bimla", "binah", "bindo", "bindu", "bingu",
+ "binky", "binni", "binod", "binta", "birdi", "biren", "birge",
+ "birky", "birly", "birny", "birol", "biron", "birte", "birty",
+ "biswa", "bitta", "bitya", "bjorn", "blaed", "blasi", "blayr",
+ "blaza", "bleda", "bledi", "blima", "blime", "blixa", "bluma",
+ "blyss", "boase", "bobbe", "bobbi", "bobek", "bobie", "bodan",
+ "bodee", "bodey", "bodie", "bodil", "bodin", "bogna", "boice",
+ "bojan", "bonar", "bondy", "bonie", "bonka", "bonni", "boona",
+ "boony", "boote", "bordy", "boris", "borja", "borka", "borya",
+ "borys", "boski", "botan", "bowen", "boxin", "boyce", "bozze",
+ "bradd", "brade", "brady", "brahm", "bramm", "brana", "brani",
+ "brann", "braun", "breah", "brear", "breay", "bredo", "breea",
+ "brena", "brenn", "breno", "breon", "breza", "briah", "brian",
+ "brice", "bridd", "bridi", "bridy", "brien", "briet", "brina",
+ "brinn", "brion", "brisa", "brita", "brodi", "brona", "broox",
+ "bruce", "brucy", "bruis", "bruna", "bruno", "bruns", "bryan",
+ "bryar", "bryce", "bryen", "bryga", "bryna", "brynn", "bryon",
+ "bubsy", "buchi", "bucky", "budde", "buell", "buena", "bugsy",
+ "bunky", "bunni", "burak", "burch", "burne", "burrt", "burtt",
+ "burty", "busse", "buzby", "byram", "byran", "byrdy", "byren",
+ "byrie", "byrle", "byrne", "byrom", "byron", "cacey", "cachi",
+ "cacia", "cacie", "cadao", "cadby", "cadel", "caden", "cadye",
+ "caeli", "cahan", "cahil", "cahit", "caily", "caira", "caisi",
+ "caity", "caius", "calab", "calah", "calan", "calee", "calem",
+ "caley", "calia", "calie", "calli", "cally", "calum", "calym",
+ "calyn", "camar", "camey", "camia", "cammi", "canda", "candi",
+ "cappi", "capys", "carah", "caree", "carel", "caren", "carew",
+ "carie", "caril", "carin", "caris", "carla", "carli", "carlo",
+ "carly", "carma", "carmi", "carmy", "carna", "carra", "carri",
+ "caryl", "caryn", "carys", "casar", "casca", "cascy", "casee",
+ "cashe", "cashi", "casia", "casie", "cassi", "casta", "catey",
+ "cathe", "cathi", "cathy", "catia", "catie", "cavas", "caven",
+ "cayce", "cayci", "cayla", "cayli", "cayly", "cayse", "caysi",
+ "cayte", "cazzi", "ceadd", "cecil", "cecyl", "ceila", "cejay",
+ "celes", "celia", "celie", "celio", "celka", "celly", "celso",
+ "cemal", "cenex", "cerea", "cerek", "cerel", "ceril", "cerys",
+ "cesar", "cesha", "cesia", "cesso", "cesur", "cesya", "cetta",
+ "cevan", "cezar", "chaad", "chadd", "chade", "chady", "chago",
+ "chaim", "chaka", "chamy", "chana", "chanc", "chand", "chane",
+ "chani", "chann", "charl", "charo", "charu", "chass", "chava",
+ "chavi", "chavo", "chayo", "chazz", "cheli", "chelo", "chene",
+ "chere", "chery", "chesa", "chevi", "cheyn", "chido", "chika",
+ "chike", "chiko", "chiku", "chilo", "chilt", "chimo", "chiyo",
+ "chloe", "chofa", "chona", "choni", "chope", "chris", "chrys",
+ "chuan", "chuki", "chuma", "chumo", "chung", "chyld", "chyna",
+ "ciana", "ciara", "cicek", "cidne", "cielo", "ciera", "cijay",
+ "cilka", "cilla", "cille", "cilly", "cinda", "cindi", "cindy",
+ "cinny", "cione", "ciril", "cirse", "ciske", "cissi", "clail",
+ "clair", "clari", "claud", "clell", "cleme", "clerc", "cleta",
+ "clete", "cleva", "clive", "cloda", "cloey", "clyff", "clyph",
+ "clyve", "clywd", "cnute", "coady", "cobey", "cobie", "coday",
+ "codee", "codey", "codie", "coedy", "cofer", "colan", "colbi",
+ "colen", "colis", "colum", "colyn", "conan", "condi", "conni",
+ "conny", "conon", "conor", "conry", "conso", "cooke", "coran",
+ "corbi", "cordi", "coren", "corey", "corie", "corin", "corio",
+ "corly", "corra", "corri", "corry", "corty", "coryn", "cosma",
+ "cosme", "cosmo", "cotey", "cowey", "cowie", "coyne", "cozmo",
+ "creag", "cregg", "creig", "criag", "crina", "crish", "crito",
+ "croix", "csaba", "csuba", "curan", "cyann", "cybel", "cybil",
+ "cydne", "cylin", "cynan", "cynda", "cynde", "cyndi", "cyndy",
+ "cynie", "cynth", "cyrah", "cyrel", "cyril", "cyris", "cyros",
+ "dabbs", "dabir", "dacee", "dacey", "dache", "dacie", "dacio",
+ "dacso", "dadie", "daffi", "dafna", "dafne", "dafny", "dagen",
+ "dagne", "dagny", "dahir", "dahud", "dahut", "daicy", "daija",
+ "daile", "daimi", "daina", "daine", "daire", "daisi", "dajan",
+ "dakim", "dakin", "dalal", "dalen", "daley", "dalia", "dalil",
+ "dalin", "dalma", "dalva", "dalya", "dalyn", "dalys", "damba",
+ "damee", "damek", "damen", "damia", "damie", "damir", "damya",
+ "danah", "danai", "danal", "danay", "danea", "danee", "danek",
+ "danel", "danen", "danet", "daney", "danfy", "dania", "danie",
+ "danis", "danit", "daniz", "danja", "danka", "danne", "danni",
+ "danno", "danny", "danon", "dante", "danya", "danyl", "danys",
+ "danzy", "daoud", "darab", "darah", "daran", "daray", "darbi",
+ "darce", "darci", "darda", "dareh", "darek", "daren", "daria",
+ "darik", "daril", "darin", "dario", "darja", "darko", "darla",
+ "darli", "darly", "daron", "darry", "darse", "darsi", "darsy",
+ "darun", "darva", "darya", "daryl", "daryn", "dasan", "dasco",
+ "dasey", "dasha", "dashi", "dasie", "datha", "datus", "daudi",
+ "dauid", "dause", "daved", "davee", "davey", "david", "davie",
+ "davin", "davis", "davon", "davor", "dawan", "dawid", "dawin",
+ "dawit", "dawne", "dawnn", "dawon", "dawud", "daycy", "dayle",
+ "dayma", "dayna", "dayne", "dayse", "daysi", "daysy", "deana",
+ "deane", "deann", "debbi", "debby", "debee", "debie", "debor",
+ "debre", "decca", "decha", "decia", "decka", "dedee", "dedie",
+ "dedra", "deeda", "deena", "deepa", "deept", "deeyn", "deion",
+ "dejah", "dejan", "dejon", "dekah", "dekel", "dekka", "delan",
+ "delea", "delia", "delie", "delle", "delli", "delma", "delon",
+ "deloy", "delra", "delsy", "delte", "delya", "delys", "deman",
+ "demas", "dembe", "demps", "denae", "denah", "denby", "denea",
+ "denee", "deney", "denie", "denis", "deniz", "denly", "denna",
+ "denni", "denny", "denya", "denys", "deona", "deone", "derak",
+ "deran", "derec", "derek", "deren", "derie", "derik", "deril",
+ "derin", "derit", "derke", "deron", "derth", "deryk", "deryl",
+ "deryn", "deshi", "desie", "desir", "dessi", "desta", "deste",
+ "desty", "detta", "deune", "devah", "deval", "devan", "deven",
+ "devin", "devoe", "devra", "devri", "devyn", "dewei", "dewie",
+ "dewon", "dexin", "deyda", "dezia", "dezra", "dhana", "dhane",
+ "dhani", "dhari", "dhary", "dheva", "diane", "diann", "dicko",
+ "didar", "didra", "diego", "dietz", "digby", "digna", "dikla",
+ "dilan", "dilip", "dilla", "dilon", "dilyn", "dilys", "dimas",
+ "dimon", "dimos", "dinah", "dinaz", "dinco", "dinis", "dinko",
+ "dinny", "dinse", "dinya", "diogo", "diona", "dioni", "dionn",
+ "diora", "diore", "diosa", "dipti", "dirce", "dirck", "dirke",
+ "diron", "ditta", "ditte", "diuan", "divam", "divya", "dixee",
+ "dixon", "djari", "djimi", "djuna", "djuro", "doane", "dobry",
+ "docie", "dodee", "dodek", "dodey", "dodie", "dodya", "doeda",
+ "dolan", "dolat", "dolen", "dolfe", "dolfi", "dolin", "dolli",
+ "dolph", "dolyn", "domek", "domka", "donal", "dondi", "donek",
+ "donia", "donni", "donny", "donta", "donya", "dorah", "dordi",
+ "dorie", "dorin", "dorit", "dorka", "dorle", "dorna", "dorne",
+ "dorri", "dorry", "dorte", "doryn", "dorys", "dosha", "dosia",
+ "dosta", "dosya", "dotan", "dotti", "dougy", "douta", "dovid",
+ "dowid", "doyal", "doyel", "doyin", "doyle", "doyne", "draga",
+ "draxy", "dreda", "drenk", "drewe", "dreya", "driss", "druan",
+ "druce", "druci", "drucy", "drugi", "drumi", "drusi", "drusy",
+ "duain", "duana", "duane", "dudly", "dugal", "dugan", "dugey",
+ "dulan", "dulci", "dulcy", "dulie", "dunja", "dunta", "duong",
+ "duran", "durel", "durko", "duron", "dusan", "dusav", "dusha",
+ "dusti", "duval", "duwan", "dvora", "dwain", "dwana", "dwane",
+ "dwaun", "dwawn", "dwora", "dyami", "dyana", "dyane", "dyani",
+ "dyann", "dyese", "dylan", "dylis", "dylon", "dylys", "dymas",
+ "dymek", "dynah", "dyolf", "dyron", "dysen", "dyske", "dyson",
+ "dyvon", "eaden", "eadie", "eadin", "eagan", "eagon", "eames",
+ "eamon", "eanid", "earla", "earld", "earle", "easha", "eason",
+ "eaton", "eavan", "ebany", "ebbie", "ebert", "ebner", "ebone",
+ "eboni", "edana", "eddee", "eddie", "eddna", "eddra", "eddye",
+ "edeet", "edena", "edene", "edgar", "edina", "edisa", "edita",
+ "edite", "edith", "ediva", "edlin", "edlyn", "edmar", "edmon",
+ "ednah", "edney", "edolf", "edrea", "edred", "edric", "edris",
+ "edrys", "edson", "edvig", "edwig", "edwin", "edwyn", "edyna",
+ "edyta", "edyth", "edzio", "eefje", "eefke", "effam", "effia",
+ "efram", "efrat", "efrem", "efren", "efrim", "efrum", "egann",
+ "egeus", "egide", "ehren", "ehsan", "ehsin", "eikki", "eiley",
+ "eilif", "eilis", "eilsa", "eilyn", "einar", "einat", "einav",
+ "eiren", "eirin", "eiryn", "eitan", "eival", "ejnar", "ekene",
+ "ekraj", "elama", "elana", "elane", "elani", "elann", "elasa",
+ "elata", "elayn", "elbio", "eldad", "eldar", "elden", "eldin",
+ "eldon", "eleen", "elene", "eleni", "eleny", "eleph", "eleri",
+ "elers", "elery", "elesa", "elese", "eleta", "elexa", "elfie",
+ "elfre", "elgan", "elgar", "elgen", "elger", "elham", "eliam",
+ "elias", "elice", "elida", "elidi", "eliel", "elier", "eliga",
+ "elihu", "elija", "elika", "elimu", "elina", "eline", "eliot",
+ "elise", "elish", "elita", "eliud", "eliut", "eliza", "elize",
+ "elkan", "elkin", "ellan", "ellee", "ellen", "elley", "ellia",
+ "ellie", "ellin", "ellis", "ellma", "ellsa", "ellse", "ellsi",
+ "ellsy", "ellyn", "elman", "elmar", "elmaz", "elmer", "elmir",
+ "elmyr", "eloda", "elodi", "elois", "elora", "elrad", "elric",
+ "elroi", "elroy", "elsee", "elsey", "elsha", "elshe", "elsie",
+ "elsje", "eltan", "eltha", "elvah", "elvia", "elvie", "elvin",
+ "elvio", "elvis", "elvyn", "elvys", "elwin", "elwyn", "elxis",
+ "elyas", "elyce", "elyci", "elyot", "elysa", "elyse", "elyza",
+ "elyze", "emaan", "emani", "emari", "emeka", "emeli", "emely",
+ "emera", "emeri", "emiko", "emila", "emile", "emili", "emill",
+ "emilo", "emils", "emily", "emina", "emine", "emira", "emitt",
+ "emlen", "emlin", "emlou", "emlyn", "emmey", "emmie", "emmit",
+ "emmot", "emmye", "emory", "emrah", "emryk", "emrys", "emyle",
+ "encke", "endre", "engie", "enidd", "ennea", "ennio", "enock",
+ "enoka", "enora", "enosh", "enria", "enric", "enver", "enydd",
+ "eocha", "ephan", "ephie", "eppia", "eppie", "epsey", "eraca",
+ "erast", "erdne", "ereck", "erena", "erene", "ereni", "erhan",
+ "erich", "erico", "eriel", "erika", "eriko", "eriks", "erina",
+ "erine", "erinn", "erino", "eriqa", "erkan", "erkki", "erlan",
+ "erlin", "ermis", "erney", "ernie", "ernst", "erold", "erric",
+ "errol", "erryl", "ersin", "ertha", "ervin", "ervyn", "erwan",
+ "erwin", "erwyn", "eryan", "eryka", "erynn", "esben", "esera",
+ "eskil", "esmat", "esmie", "espen", "esref", "essad", "essae",
+ "essam", "essan", "essey", "essie", "essom", "essop", "estee",
+ "estel", "estie", "eston", "eszti", "etain", "eteri", "etgar",
+ "ethan", "ethel", "ethem", "ethna", "ethne", "ethyn", "etina",
+ "etore", "ettey", "ettie", "etyen", "etzio", "eubie", "eudel",
+ "eudes", "euell", "eugen", "eulia", "evald", "evana", "evann",
+ "evany", "evard", "eveny", "evett", "evike", "evita", "evlin",
+ "evlyn", "evony", "evvie", "evyan", "ewald", "eward", "ewart",
+ "ewert", "ewing", "ewynn", "eydie", "eytan", "eyton", "ezeck",
+ "ezell", "ezera", "ezhno", "ezola", "ezrah", "ezvan", "ezzat",
+ "ezzie", "faada", "fabek", "fabia", "fabio", "fabra", "fabre",
+ "fadal", "fadel", "fadey", "fadil", "fadwa", "fahad", "faida",
+ "faiga", "faina", "faisl", "faiza", "fakih", "fakri", "falah",
+ "falan", "falau", "faleh", "falen", "falin", "falke", "falyn",
+ "famke", "fanci", "fania", "fanis", "fanni", "fanus", "fanya",
+ "farai", "faran", "faren", "farid", "farin", "fario", "fariq",
+ "faroh", "farok", "faron", "farqy", "farra", "faruk", "faruq",
+ "farye", "faryn", "fasil", "faten", "fathi", "fatih", "fatil",
+ "fatin", "fatma", "fatos", "fatur", "faune", "faure", "fawna",
+ "fawne", "fawzi", "fawzy", "faxon", "fayda", "fayez", "fayik",
+ "fayla", "fayme", "fayne", "fayth", "fazel", "fazil", "fedja",
+ "fedor", "fedya", "feena", "fekri", "felcy", "felda", "felia",
+ "felic", "felim", "felix", "feliz", "felka", "felyx", "femie",
+ "femmi", "feran", "feras", "ferda", "ferde", "ferdo", "ferdy",
+ "ferin", "ferne", "ferni", "feron", "feroz", "feste", "feyla",
+ "ffion", "fiach", "fiala", "fidel", "filia", "filma", "filya",
+ "finan", "finly", "finty", "fiona", "fionn", "fiora", "fiore",
+ "fioza", "firaq", "firas", "firat", "firuz", "fiske", "flana",
+ "flann", "fleda", "fleta", "flinn", "flody", "flois", "flori",
+ "floyd", "flynn", "flynt", "foard", "folke", "fonso", "fonta",
+ "fonya", "fonzo", "forbe", "forey", "forry", "fosca", "fosco",
+ "fouad", "frang", "franh", "frani", "frann", "frano", "frans",
+ "franz", "fraya", "frean", "freda", "fredd", "fredi", "fredo",
+ "fredy", "freek", "freen", "freja", "freny", "friba", "frici",
+ "frick", "frida", "frode", "froma", "fryda", "fuaad", "fujio",
+ "fulla", "fumio", "furio", "fyffe", "fyodr", "gabbe", "gabbi",
+ "gabie", "gabin", "gabko", "gabor", "gabri", "gabys", "gaddy",
+ "gaela", "gagan", "gahan", "gaiea", "gaila", "gaile", "gaill",
+ "gaius", "galan", "galia", "galib", "galin", "galit", "galya",
+ "galyn", "gamal", "gamid", "gamil", "ganit", "ganna", "ganya",
+ "gareb", "gared", "garek", "garen", "garet", "garey", "gargi",
+ "garie", "garik", "garri", "garvy", "garyn", "gasha", "gaute",
+ "gavan", "gaven", "gavin", "gavra", "gavri", "gavyn", "gawen",
+ "gayel", "gayil", "gayla", "gayle", "gayna", "gazit", "geane",
+ "geany", "gearr", "geber", "geela", "geena", "geert", "geeta",
+ "geina", "gelda", "gelya", "genah", "genay", "genea", "genek",
+ "genia", "genna", "genni", "geoff", "geona", "georg", "gerad",
+ "geran", "gerco", "gerda", "gerdi", "gerdy", "gerek", "gergo",
+ "gerik", "gerre", "gerri", "gerry", "gerta", "gerte", "gerti",
+ "gerty", "geula", "gevin", "ghada", "ghaib", "ghatu", "ghena",
+ "ghian", "ghino", "ghita", "ghlam", "giamo", "giana", "giann",
+ "gibbs", "gibor", "gidey", "gidon", "giesa", "giffy", "gifty",
+ "gigia", "gihan", "gilad", "gilah", "gilby", "gilda", "gilde",
+ "gildy", "gilen", "giles", "gilie", "gilli", "gillo", "gilon",
+ "ginia", "ginna", "ginni", "gints", "ginya", "giona", "giray",
+ "giric", "girod", "gitel", "githa", "gitle", "gitta", "gitte",
+ "giula", "giuma", "giusy", "gizat", "gjorg", "gleda", "glena",
+ "glenn", "gleny", "glori", "gojko", "golda", "goldi", "gonza",
+ "gordy", "gorje", "gorya", "gosia", "gough", "gower", "gowon",
+ "gozal", "graca", "graci", "gracy", "grady", "graef", "graem",
+ "graig", "grear", "greer", "gregg", "greig", "greil", "greta",
+ "gretl", "greye", "grier", "gries", "gryta", "guido", "guila",
+ "gulam", "gulay", "gunar", "gunay", "gunda", "guram", "gurit",
+ "gussi", "gusta", "gusti", "guyan", "guyon", "guyte", "gwayn",
+ "gwenn", "gwinn", "gwynn", "gyasi", "gylla", "gytha", "gyuri",
+ "habib", "hacib", "hadas", "haden", "hadia", "hadja", "hadly",
+ "hadon", "hadyn", "hafed", "hafid", "hafsa", "hagai", "hagan",
+ "hagit", "hagly", "hagop", "haiko", "haila", "haili", "hajar",
+ "hajim", "hajna", "hakan", "hakon", "halbe", "halen", "haley",
+ "halie", "halla", "halli", "hally", "halsy", "haluk", "halya",
+ "halye", "hamar", "hamdi", "hamel", "hamer", "hamet", "hamif",
+ "hamil", "hamin", "hamit", "hanaa", "hanae", "hanah", "hanan",
+ "hanef", "hanik", "hanim", "hanin", "hanja", "hanka", "hanly",
+ "hanna", "hanne", "hanni", "hannu", "hanny", "hansh", "hansl",
+ "hantz", "hanus", "haona", "harah", "harbi", "harel", "harin",
+ "harla", "harli", "harly", "haron", "harri", "harro", "harun",
+ "harve", "hasad", "hasan", "hasen", "hasib", "hasil", "hasin",
+ "hason", "hasse", "hasso", "hatem", "hatim", "hatsy", "hatti",
+ "hauke", "havah", "havin", "havis", "haviv", "hawes", "hawly",
+ "hayah", "hayam", "hayat", "hayde", "haydn", "hayfa", "hayim",
+ "hayli", "hayly", "hayne", "hayse", "hazal", "hazem", "hazim",
+ "hazra", "hazyl", "heall", "hearn", "hedda", "heddi", "heddy",
+ "hedia", "hedir", "hedly", "hedva", "heida", "heide", "heidi",
+ "heike", "heiko", "heimo", "heinz", "heith", "helah", "helen",
+ "helga", "helge", "helki", "helli", "helma", "helmi", "helmy",
+ "helon", "helsa", "helyn", "hendl", "henia", "henie", "henka",
+ "henni", "henny", "henri", "henya", "herin", "hermy", "hersh",
+ "hersz", "herta", "herva", "hervy", "herzl", "hesam", "heshu",
+ "hesky", "hesti", "hesty", "hetal", "hetta", "hetti", "hetty",
+ "heven", "hewet", "hewie", "hewit", "hiatt", "hibah", "hidee",
+ "hideo", "hieda", "hiede", "hilda", "hilde", "hildi", "hildo",
+ "hildy", "hilel", "hilia", "hilit", "hille", "hilma", "hilmi",
+ "himan", "hinda", "hindy", "hiner", "hinju", "hinke", "hinto",
+ "hinun", "hiram", "hirem", "hirji", "hirom", "hirov", "hirsh",
+ "hisao", "hitka", "hitty", "hivet", "hiwot", "hoang", "hobey",
+ "holda", "holde", "holic", "holic", "holle", "holli", "holub",
+ "homan", "honna", "honon", "honza", "hopey", "hopie", "horaz",
+ "hosea", "hoshi", "hosni", "hosny", "houda", "houry", "hovan",
+ "howey", "howie", "howin", "hrank", "hrolf", "huber", "hubey",
+ "hubie", "hughy", "hulda", "humam", "hunny", "huong", "huram",
+ "husam", "husnu", "huxly", "hyatt", "hyder", "hydie", "hylda",
+ "hyman", "hymie", "hynda", "hynee", "hyram", "hyrum", "hywel",
+ "iakob", "iakov", "ianna", "ianos", "ibbie", "ibram", "idaia",
+ "idaya", "idell", "idina", "idrys", "idwal", "iesha", "ifrah",
+ "ifraz", "iggie", "ignac", "ignaz", "ignes", "ihsan", "ikemi",
+ "ikkei", "iklas", "ikram", "ikuko", "ilana", "ilani", "ilean",
+ "ileen", "ilena", "ilene", "ilese", "ilham", "ilhan", "ilias",
+ "ilich", "ilida", "ilina", "iline", "ilisa", "ilise", "ilita",
+ "ilker", "ilkka", "illan", "illia", "illya", "ilona", "ilone",
+ "ilsey", "ilyas", "ilyaz", "ilyna", "ilysa", "ilyse", "imani",
+ "imany", "imena", "imran", "inaki", "inbal", "indya", "ineke",
+ "inela", "inell", "ingar", "inger", "iniga", "iniki", "iniko",
+ "innes", "innis", "ioana", "ioann", "iolee", "iolia", "ionel",
+ "ioney", "ionie", "ionut", "ioseb", "iosep", "iosif", "iosua",
+ "iouri", "iqbal", "iradj", "irana", "ireen", "irena", "irfan",
+ "irien", "irina", "irini", "irisa", "irita", "irona", "irven",
+ "irvin", "irwin", "irwyn", "iryna", "isaac", "isaak", "isack",
+ "isaia", "isaid", "isaih", "isais", "isamu", "isbel", "isela",
+ "iseut", "isham", "ishaq", "isiah", "isild", "isman", "ismar",
+ "ismet", "isoka", "isold", "isolt", "issac", "issai", "issam",
+ "issca", "isser", "issey", "issia", "issie", "issur", "istar",
+ "italo", "ithel", "ittai", "itzak", "itzik", "iulia", "ivana",
+ "ivann", "ivano", "iveta", "ivete", "iveth", "ivett", "ivica",
+ "ivona", "ivone", "ivori", "ivree", "ivria", "iwona", "ixaka",
+ "iyabo", "iyapo", "iyari", "iyman", "iyoka", "izaac", "izaak",
+ "izbul", "izeke", "izhar", "izola", "izora", "izsak", "iztok",
+ "izzak", "izzet", "izzie", "jaali", "jaber", "jabes", "jabin",
+ "jabir", "jacan", "jacee", "jacek", "jacen", "jacey", "jacia",
+ "jacie", "jacki", "jacob", "jacsi", "jadah", "jadda", "jadea",
+ "jadee", "jadel", "jaden", "jader", "jadey", "jadie", "jadin",
+ "jadon", "jadyn", "jaeda", "jaela", "jaeli", "jafar", "jafit",
+ "jafra", "jaggi", "jagur", "jahan", "jahel", "jahja", "jahla",
+ "jahna", "jaicy", "jaida", "jaide", "jaima", "jaime", "jaimi",
+ "jaimy", "jaine", "jaira", "jairo", "jairy", "jakab", "jakea",
+ "jakia", "jakiv", "jakki", "jakob", "jakov", "jakub", "jakup",
+ "jalal", "jaleh", "jalen", "jalil", "jalin", "jamaa", "jamal",
+ "jamar", "jamay", "jamea", "jamee", "jamel", "jamey", "jamia",
+ "jamie", "jamil", "jamin", "jamis", "jamod", "jamon", "jamya",
+ "jamye", "jamyi", "janae", "janah", "janai", "janak", "janan",
+ "janay", "janco", "jando", "jandy", "janea", "janee", "janei",
+ "janek", "janel", "janet", "janey", "janez", "jania", "janie",
+ "janis", "janit", "janka", "janko", "janna", "janne", "janos",
+ "janot", "janou", "janse", "jante", "janvi", "jaqui", "jarad",
+ "jarah", "jarda", "jareb", "jared", "jarek", "jarel", "jaren",
+ "jaret", "jaria", "jarib", "jaric", "jarid", "jaris", "jarko",
+ "jarod", "jaron", "jaryd", "jasai", "jasan", "jasek", "jasen",
+ "jasha", "jasia", "jasin", "jasma", "jasme", "jasna", "jason",
+ "jasun", "jauan", "jaume", "javad", "javar", "javed", "javen",
+ "javid", "javin", "javon", "javos", "jawon", "jaxon", "jayce",
+ "jayci", "jaycy", "jayda", "jayde", "jaydi", "jaydn", "jaydy",
+ "jayke", "jayla", "jayma", "jayme", "jaymi", "jayms", "jayna",
+ "jayne", "jayni", "jayol", "jazan", "jazze", "jazzi", "jeana",
+ "jeane", "jeani", "jeany", "jeays", "jecho", "jecis", "jeddy",
+ "jeeda", "jeena", "jeffe", "jeffy", "jefre", "jefri", "jefry",
+ "jegar", "jehan", "jehmu", "jehna", "jehri", "jeisa", "jelle",
+ "jemal", "jemar", "jemel", "jemes", "jemie", "jemma", "jemon",
+ "jenae", "jenah", "jenai", "jenal", "jenan", "jenay", "jenda",
+ "jendy", "jenee", "jenel", "jenet", "jenie", "jenik", "jenis",
+ "jenji", "jenka", "jenna", "jenni", "jenno", "jensy", "jeorg",
+ "jeppe", "jerad", "jerae", "jerah", "jerai", "jered", "jeree",
+ "jerel", "jeret", "jeric", "jerie", "jerik", "jeril", "jerin",
+ "jeris", "jerme", "jerod", "jerom", "jeron", "jerre", "jerri",
+ "jeryl", "jerzy", "jesca", "jesee", "jesey", "jeska", "jessa",
+ "jessi", "jessy", "jesus", "jetje", "jetro", "jetta", "jevan",
+ "jevin", "jevon", "jeyes", "jhona", "jiana", "jicky", "jihan",
+ "jijun", "jilan", "jilli", "jilly", "jimae", "jimar", "jimbo",
+ "jimel", "jimly", "jimoh", "jinae", "jincy", "jinda", "jinfu",
+ "jinia", "jinna", "jiske", "jitka", "jivan", "jivin", "joaby",
+ "joana", "joane", "joani", "joann", "joary", "joash", "joayn",
+ "joben", "jobey", "jobie", "jobst", "jobye", "jocek", "jocia",
+ "jodan", "jodee", "jodey", "jodhi", "jodie", "jodin", "jodon",
+ "joedy", "joela", "joeli", "joell", "joely", "joerg", "joern",
+ "jofre", "johan", "johna", "johne", "johni", "johnl", "johny",
+ "joice", "jokin", "jokla", "jolan", "jolea", "jolee", "joley",
+ "jolie", "jolin", "jolye", "jolyn", "jomei", "jonae", "jonai",
+ "jonam", "jonas", "jonay", "jonci", "jonda", "jonee", "jonel",
+ "jonie", "jonis", "jonit", "jonna", "jonni", "jonno", "jonta",
+ "jonte", "jools", "joost", "jopie", "jorah", "jorai", "joran",
+ "jordi", "jordu", "jordy", "jorea", "jorel", "jorey", "jorge",
+ "jorie", "jorik", "jorim", "jorin", "joris", "jorja", "jorma",
+ "jorry", "jorun", "josee", "josef", "josep", "joses", "joset",
+ "josey", "josha", "joshe", "joshi", "joshu", "josia", "josif",
+ "josip", "joska", "josko", "josse", "jossy", "josua", "josup",
+ "josye", "jouko", "jouni", "joval", "jovan", "jovin", "jovon",
+ "jowad", "jowie", "joxel", "joyan", "joyce", "joyia", "joyti",
+ "jozee", "jozef", "jozhe", "jozie", "jozio", "jozka", "jozsa",
+ "jozsi", "jozua", "jozus", "juana", "juann", "juaun", "jubal",
+ "juday", "judee", "judie", "judit", "judye", "jueen", "jueri",
+ "juhan", "jukie", "jukka", "julas", "julee", "julen", "jules",
+ "julet", "juley", "julia", "julie", "julka", "jumah", "juney",
+ "junia", "junie", "junji", "junot", "junya", "juraj", "jurek",
+ "jurik", "jurre", "jusak", "justa", "justi", "justo", "justy",
+ "jutta", "juval", "juvan", "juwan", "juwon", "juzef", "juziu",
+ "jyoti", "kaare", "kabir", "kacee", "kacey", "kacia", "kacie",
+ "kadar", "kaden", "kader", "kadey", "kadie", "kadin", "kadye",
+ "kaela", "kaeli", "kaely", "kaese", "kaesy", "kaffe", "kaffi",
+ "kahan", "kahil", "kahki", "kaian", "kaija", "kaila", "kaile",
+ "kaine", "kaipo", "kaira", "kaire", "kairo", "kaisa", "kaite",
+ "kaity", "kajsa", "kakha", "kakwa", "kalab", "kalea", "kaleb",
+ "kalee", "kalei", "kalel", "kalen", "kaleo", "kaleu", "kaley",
+ "kalib", "kalie", "kalil", "kalim", "kalin", "kaliq", "kalla",
+ "kalle", "kalli", "kally", "kalun", "kalye", "kalyn", "kamal",
+ "kaman", "kambo", "kamea", "kamel", "kamen", "kameo", "kamey",
+ "kamil", "kamla", "kammi", "kammy", "kamra", "kanan", "kanda",
+ "kaney", "kange", "kania", "kanny", "kanoa", "kanta", "kantu",
+ "kaomi", "kaoru", "kapil", "kapri", "kaprr", "kapua", "karah",
+ "karan", "karem", "karey", "karie", "karif", "karim", "karin",
+ "karla", "karle", "karly", "karna", "karny", "karol", "karon",
+ "karru", "karry", "karyl", "karyn", "karys", "kasci", "kascy",
+ "kasee", "kasen", "kasey", "kasho", "kasia", "kasib", "kasie",
+ "kasim", "kasin", "kasja", "kason", "kassi", "kassy", "kasya",
+ "katee", "katey", "kathi", "kathy", "katia", "katie", "katja",
+ "katka", "katla", "katri", "katti", "katus", "katya", "katye",
+ "kavai", "kavan", "kaveh", "kavin", "kayci", "kayde", "kaydi",
+ "kaydy", "kayel", "kayia", "kayin", "kayla", "kayli", "kayne",
+ "kaysi", "kaysy", "kayta", "kayte", "kazem", "kazia", "kazio",
+ "kazue", "kazuo", "keahi", "keaka", "keala", "keali", "kealy",
+ "keane", "keanu", "keara", "kearn", "keary", "keath", "kecal",
+ "kecia", "keddy", "kedem", "keder", "keefe", "keela", "keeli",
+ "keely", "keena", "keene", "keeon", "keera", "keeth", "keeya",
+ "kegan", "kegun", "keida", "keiji", "keiko", "keily", "keion",
+ "keira", "keita", "keiti", "keiwa", "kekoa", "kelan", "kelby",
+ "kelci", "kelcy", "kelda", "kelee", "kelia", "kelii", "kelle",
+ "kelli", "kelsa", "kelse", "kelsi", "kelsy", "kelye", "kemah",
+ "kemal", "kemba", "kenan", "kenda", "kendi", "kendy", "kengo",
+ "kenia", "kenja", "kenly", "kenny", "kenol", "kenon", "kenpo",
+ "kenzy", "keoki", "keola", "keone", "keoni", "keony", "kerby",
+ "keree", "kerem", "kerey", "kerim", "kermy", "kerri", "keryn",
+ "kesha", "kesia", "kesin", "kesly", "kessa", "kesse", "kessi",
+ "ketan", "keter", "ketti", "ketty", "ketul", "ketzi", "keung",
+ "keura", "kevan", "keven", "kevin", "kevis", "kevon", "kevvy",
+ "kevyn", "keyla", "keyon", "keyse", "kezia", "khaim", "khali",
+ "khanh", "khara", "khava", "kheya", "khieu", "khiri", "khiry",
+ "khleo", "khory", "khris", "khrys", "kiana", "kiane", "kiani",
+ "kiant", "kiara", "kibah", "kichi", "kidan", "kiela", "kiele",
+ "kieli", "kiely", "kiera", "kifah", "kilan", "kilda", "kilee",
+ "kilen", "kilie", "kimba", "kimee", "kimia", "kimie", "kimit",
+ "kimme", "kimmi", "kimmo", "kimmy", "kimon", "kimya", "kinan",
+ "kindi", "kinna", "kiona", "kioni", "kiral", "kiran", "kirbi",
+ "kiria", "kiril", "kirky", "kiron", "kirsi", "kirya", "kisha",
+ "kishi", "kitti", "kitts", "kivah", "kizza", "kizzy", "kjell",
+ "klaas", "klaes", "klara", "klari", "klaus", "kleef", "kleng",
+ "kleon", "kliff", "klint", "kliti", "knute", "kobet", "kobra",
+ "kodey", "kodie", "koffe", "koffi", "kohei", "kohki", "kokou",
+ "kolby", "kolia", "kolyn", "komal", "konga", "konni", "konny",
+ "kopla", "koral", "korbi", "koree", "koren", "korey", "korie",
+ "korio", "korka", "korny", "korra", "korri", "korry", "koryn",
+ "kosey", "kosma", "kosmo", "kosmy", "kosse", "kosta", "koula",
+ "kovit", "kozen", "kraig", "kreig", "krist", "kueng", "kumar",
+ "kunal", "kunio", "kunle", "kuper", "kuzih", "kwako", "kwame",
+ "kwami", "kwesi", "kyele", "kyjel", "kylah", "kylan", "kylea",
+ "kylee", "kylen", "kyler", "kylia", "kylyn", "kynan", "kynda",
+ "kyoji", "kyoko", "kyrah", "kyran", "kyria", "kyril", "kyros",
+ "labon", "lacee", "lache", "lacia", "lacie", "lacko", "ladan",
+ "ladis", "laela", "laeta", "lahea", "lahib", "laidi", "laila",
+ "laili", "laily", "laina", "lajos", "lakia", "lakva", "lalee",
+ "laleh", "lalit", "lalji", "lalka", "lalla", "lalli", "laloo",
+ "laman", "lamon", "lanae", "lanah", "lanay", "lanbo", "lancy",
+ "lando", "lanet", "lange", "lanna", "lanni", "lanny", "lantz",
+ "lanzo", "larah", "laran", "laren", "laria", "larie", "larka",
+ "larna", "laron", "larse", "lasca", "lashi", "lasho", "laslo",
+ "latai", "latau", "latea", "latha", "latia", "latif", "lauch",
+ "lauer", "lauge", "laure", "lauri", "lauro", "lauza", "lavan",
+ "lavar", "lavia", "lavon", "lawry", "laxmi", "layla", "layli",
+ "layna", "lazlo", "leala", "leana", "leane", "leann", "leasa",
+ "leavi", "lebzy", "lecia", "ledah", "ledis", "ledvi", "leeah",
+ "leean", "leeba", "leece", "leeda", "leela", "leena", "leesa",
+ "leevi", "leeza", "legra", "leial", "leian", "leiba", "leida",
+ "leidy", "leila", "leisa", "lekel", "leksi", "lelah", "lelan",
+ "lelia", "lelie", "lelio", "lella", "lelya", "lemae", "lemar",
+ "lemmy", "lenah", "lenci", "lenda", "lenea", "lenee", "lenia",
+ "lenka", "lenly", "lenna", "lenno", "lenny", "lenon", "lenor",
+ "leoda", "leola", "leoma", "leona", "leoni", "leora", "leory",
+ "leota", "lerai", "lerka", "leroi", "leron", "leroy", "lesha",
+ "lesia", "leska", "lesli", "lesly", "letha", "letif", "letta",
+ "letti", "levar", "levey", "levia", "levie", "levka", "levko",
+ "levon", "levya", "lewie", "lewin", "lewyn", "lexey", "leyla",
+ "lezli", "lezly", "libba", "libbi", "libby", "libia", "licha",
+ "licia", "lidah", "lider", "lidia", "lidio", "lidka", "lidya",
+ "liebe", "liena", "liene", "liesa", "liese", "liesl", "ligda",
+ "liisa", "lilah", "lilia", "lilie", "lilis", "lilja", "lilla",
+ "lilli", "lillo", "lilly", "lilya", "limor", "linah", "linal",
+ "linas", "linda", "lindz", "linek", "linel", "linet", "linly",
+ "linsi", "linsy", "linus", "linzi", "linzy", "liona", "liora",
+ "lippo", "liran", "liris", "liron", "lisby", "lisha", "lishe",
+ "lisia", "lison", "lissi", "lissy", "litah", "litia", "liton",
+ "litsa", "litto", "liuka", "livan", "livia", "livie", "livio",
+ "livna", "livvi", "livvy", "livya", "livye", "lizan", "lizka",
+ "lizzy", "ljube", "lloyd", "lnard", "locke", "lodie", "logen",
+ "loise", "lolee", "lolli", "loman", "lonan", "lonee", "lones",
+ "longy", "lonie", "lonna", "lonni", "lonny", "lonso", "lonzo",
+ "lorah", "loray", "loree", "loren", "lorey", "loria", "lorie",
+ "lorin", "lorna", "lorne", "lorra", "lorri", "loryn", "lotfi",
+ "lotie", "lotje", "lotti", "lotty", "louay", "loudy", "louka",
+ "loura", "lovel", "lovey", "lovie", "lowel", "loyce", "loyda",
+ "loyde", "luana", "luane", "luann", "lubba", "luben", "lubna",
+ "lubos", "lubov", "lucas", "lucho", "lucia", "lucie", "lucil",
+ "lucio", "lucus", "lucya", "lucza", "ludek", "ludie", "ludis",
+ "ludka", "ludko", "luigi", "luisa", "luise", "luiza", "lujza",
+ "lukas", "luken", "lukes", "lukus", "lulie", "lulla", "luray",
+ "lusia", "lusio", "luvvy", "luzca", "luzia", "lyall", "lycon",
+ "lydah", "lydie", "lydon", "lyell", "lygia", "lylah", "lyman",
+ "lynaa", "lynae", "lynah", "lynda", "lyndy", "lynea", "lynna",
+ "lynne", "lynsy", "lynzi", "lynzy", "lypsy", "lyris", "lyron",
+ "lysle", "lyssi", "lytie", "lyuba", "lyvon", "maaja", "mabel",
+ "mable", "mabry", "mabyn", "macey", "macha", "macia", "macie",
+ "macke", "madan", "maddi", "madea", "madee", "madel", "maden",
+ "madgi", "madhu", "madna", "madoc", "madog", "madox", "madra",
+ "maeko", "maels", "maemi", "maeve", "maevi", "maevy", "maffy",
+ "magan", "magda", "magdy", "maged", "magee", "magge", "maggi",
+ "maggy", "magid", "maglo", "magui", "maguy", "mahda", "maher",
+ "mahir", "mahsi", "maiah", "maida", "maiga", "maija", "maika",
+ "maina", "maira", "maire", "mairi", "maisa", "maisy", "maita",
+ "maite", "maive", "maiya", "maiza", "majdi", "majed", "majel",
+ "majer", "makda", "makey", "makie", "makin", "makoa", "maksa",
+ "malak", "malav", "malea", "malee", "maley", "malha", "malie",
+ "maliq", "maliz", "malka", "malki", "malle", "malli", "malte",
+ "malur", "malye", "mamed", "mamta", "manci", "manco", "mandi",
+ "mando", "mandy", "manee", "manel", "manfo", "manie", "manin",
+ "manka", "manni", "manno", "manoj", "manon", "mansy", "manue",
+ "manya", "manzi", "manzo", "marar", "marca", "marce", "marci",
+ "marcy", "marda", "marea", "maree", "marek", "maren", "marga",
+ "margo", "margy", "marie", "marii", "marin", "mario", "maris",
+ "marit", "marje", "marji", "marjy", "marke", "marko", "marla",
+ "marlo", "marna", "marni", "marny", "marra", "marsy", "marta",
+ "marth", "marti", "marty", "marva", "marve", "marvi", "marya",
+ "maryk", "maryl", "masae", "masao", "masia", "masim", "masna",
+ "masou", "massi", "masud", "matak", "matea", "matei", "matek",
+ "matel", "mateo", "mathe", "mathi", "mathu", "matia", "matis",
+ "matti", "matty", "matuq", "matus", "matya", "maude", "maudy",
+ "mauli", "mauni", "maura", "maure", "mauro", "maury", "mausi",
+ "mavon", "mavra", "maxey", "maxie", "maxna", "maxon", "mayam",
+ "mayim", "mayin", "mayme", "mayne", "mayra", "maysa", "mayte",
+ "mayur", "mayve", "mazal", "mazen", "mazie", "mazin", "mcgee",
+ "meade", "meara", "meari", "meave", "mechi", "mecki", "medel",
+ "medie", "meeka", "meeku", "meema", "meera", "megan", "megen",
+ "meggi", "meggy", "megha", "megyn", "mehdi", "mehta", "mehti",
+ "mehul", "meier", "meika", "meike", "meiko", "meila", "meilo",
+ "mekal", "melak", "melan", "melby", "melda", "melea", "melie",
+ "mella", "melli", "melva", "melya", "melyn", "mendy", "menes",
+ "menke", "menna", "menno", "menon", "menza", "merah", "meral",
+ "merce", "merci", "mered", "merek", "meric", "merie", "meril",
+ "merja", "merka", "merla", "merna", "meron", "merri", "merta",
+ "merti", "merva", "meryl", "mesum", "mesut", "metin", "metka",
+ "metsy", "metta", "mette", "meyer", "meyta", "mhari", "mhina",
+ "miata", "micah", "mical", "micci", "miccy", "micha", "michi",
+ "micho", "micki", "micol", "mieke", "mieko", "migel", "miggi",
+ "migul", "mihai", "miiko", "mikah", "mikal", "mikee", "mikel",
+ "miken", "mikey", "mikia", "mikie", "mikio", "mikis", "mikka",
+ "mikki", "mikko", "mikol", "miksa", "milah", "milda", "milek",
+ "miley", "milka", "milli", "milne", "milya", "mimma", "mimzy",
+ "minal", "minda", "mindi", "mindy", "minel", "minhy", "minik",
+ "minka", "minna", "minne", "minoo", "minta", "minya", "mique",
+ "mirae", "mirah", "miram", "miran", "mirar", "mirav", "mirek",
+ "mirel", "miren", "mirit", "mirja", "mirko", "mirna", "miron",
+ "mirra", "mirsa", "mirta", "mirto", "misha", "misho", "miska",
+ "missi", "mitch", "mitio", "mitja", "mitul", "mitya", "mitzi",
+ "miura", "mlada", "moala", "mohan", "mohen", "mohja", "moico",
+ "moien", "moina", "moise", "molia", "molli", "momoe", "monae",
+ "monah", "monay", "monca", "mondy", "monea", "monee", "monia",
+ "monna", "monro", "monti", "montu", "monty", "monya", "moore",
+ "mooro", "mopsa", "morad", "mordi", "mordy", "morey", "moria",
+ "morie", "morio", "moris", "morit", "moriz", "morla", "morly",
+ "morna", "morry", "morty", "mosha", "moshe", "mosie", "mosya",
+ "mosze", "motoo", "motti", "mouki", "mouna", "mousa", "moyna",
+ "moyra", "muffy", "mufid", "muire", "mujab", "mukta", "mukul",
+ "mundo", "mundy", "munib", "munio", "munir", "munna", "munny",
+ "murad", "murfy", "murti", "musin", "mussa", "muzzi", "mwaka",
+ "myarn", "mycah", "mykal", "mykel", "mylan", "mylee", "mylen",
+ "myles", "mylon", "myndy", "mynga", "mynor", "myrah", "myran",
+ "myria", "myrle", "myrna", "myrta", "myrth", "mysti", "mytch",
+ "myzel", "mzuzi", "nabih", "nabil", "nacia", "nacim", "nadav",
+ "nadea", "nader", "nadia", "nadim", "nadja", "nadya", "naeem",
+ "nafas", "nagib", "nagji", "nagla", "nahda", "nahid", "nahit",
+ "nahla", "naida", "naide", "naila", "naima", "naina", "nairm",
+ "naiym", "najah", "najai", "najam", "najat", "najee", "najia",
+ "najib", "najja", "najji", "najla", "najma", "najwa", "nakea",
+ "nakia", "nakos", "naldo", "namal", "namia", "namid", "namir",
+ "nance", "nanci", "nanda", "nando", "nanni", "nannu", "nanon",
+ "nanor", "nansi", "nanuk", "naoko", "naoma", "naomy", "naoto",
+ "naoya", "napea", "narah", "narda", "naren", "naser", "nasha",
+ "nasia", "nasim", "nasir", "nasit", "nasry", "nasya", "natan",
+ "natia", "natia", "natie", "natja", "natka", "natka", "natti",
+ "natya", "nauns", "navek", "navia", "navid", "navin", "navit",
+ "nawaf", "nawal", "nawaq", "nawat", "nayad", "nayan", "nayef",
+ "nayla", "nazar", "nazih", "nazli", "nazmi", "nazyf", "ndudi",
+ "neala", "neale", "neall", "nealy", "neary", "necha", "necia",
+ "necie", "necip", "nedda", "neddi", "nedra", "neefy", "neeka",
+ "neela", "neeli", "neely", "neema", "neeme", "neena", "neera",
+ "neeru", "neeta", "neeti", "nefen", "negla", "neicy", "neihl",
+ "neila", "neile", "neili", "neill", "neils", "nejib", "nelda",
+ "neleh", "nelek", "nelia", "nelie", "nelja", "nelka", "nella",
+ "nelle", "nelli", "nelse", "nelva", "nenad", "neneh", "nenet",
+ "nenno", "neola", "neoma", "neomi", "neomy", "neona", "nephi",
+ "neria", "nerin", "nerly", "neron", "nerys", "nesha", "nesia",
+ "nesim", "nesma", "nessa", "nessi", "nesta", "netia", "netie",
+ "netis", "netta", "netti", "nevan", "neven", "nevia", "nevil",
+ "nevin", "nevra", "nevsa", "nexcy", "neyla", "neyra", "neysa",
+ "neyva", "nezha", "nfana", "ngave", "ngila", "ngugi", "nhean",
+ "nhork", "niabi", "niall", "niamh", "niara", "nibaw", "nicci",
+ "niccy", "nicia", "nicki", "nicky", "nicos", "nidia", "nidya",
+ "nieca", "niecy", "nieem", "niele", "niels", "nigal", "nigel",
+ "nigil", "nigle", "nihad", "nihat", "nijel", "niket", "nikia",
+ "nikka", "nikky", "nikos", "niksa", "nilas", "nilce", "nilda",
+ "niles", "nilos", "niloy", "nilya", "nimaa", "nimah", "nimai",
+ "nimal", "nimmy", "ninia", "ninna", "ninor", "ninya", "niraj",
+ "niran", "nirav", "nirel", "nirin", "nirit", "nisao", "nisha",
+ "nissa", "nissi", "nisso", "nissy", "nitin", "nitis", "nitsa",
+ "nitza", "niura", "niuta", "niven", "nivia", "niyal", "nizah",
+ "noach", "noady", "noami", "nobie", "nobuo", "nodin", "noela",
+ "noell", "noemi", "nolan", "nolen", "nolia", "nolin", "nolly",
+ "nolyn", "nomar", "nonah", "nonia", "nonie", "nonna", "nonso",
+ "nonya", "noola", "noori", "norah", "norby", "noren", "normi",
+ "normy", "norna", "norri", "norty", "noson", "noton", "notra",
+ "nouni", "noura", "novia", "novka", "ntare", "nuala", "nubar",
+ "nucci", "nuela", "nuhra", "numan", "nupur", "nuran", "nuria",
+ "nurin", "nuris", "nurit", "nurul", "nutsa", "nuvia", "nyama",
+ "nydia", "nygel", "nyiko", "nyire", "nyoia", "nyoko", "nyome",
+ "nyomi", "nyree", "nyrie", "oakes", "oakly", "oates", "obbie",
+ "obert", "obery", "obrad", "oceon", "odair", "odall", "odela",
+ "odele", "odell", "odera", "odila", "odile", "odili", "odion",
+ "odolf", "odran", "ofrat", "ogdan", "ogdon", "ogier", "ogisi",
+ "ojana", "ojara", "ojars", "okbar", "okeke", "okley", "okoth",
+ "oktay", "olaff", "olafs", "olaus", "olave", "olavi", "oleda",
+ "olena", "olene", "oleta", "oleus", "olgen", "oliff", "olina",
+ "oline", "olisa", "olley", "ollye", "olner", "olrik", "olvan",
+ "olwen", "olwin", "olwyn", "omair", "omara", "omari", "omarr",
+ "ombra", "omero", "oneal", "oneil", "oneka", "onene", "onfre",
+ "onida", "oniel", "onnie", "onora", "onyda", "oonah", "oonie",
+ "opale", "ophra", "oprah", "orali", "orane", "orbel", "orela",
+ "orene", "orest", "oreta", "orhan", "orian", "orien", "orina",
+ "orino", "orlan", "orlee", "orlie", "orlin", "orman", "ormon",
+ "ornan", "ornia", "orono", "orpah", "orpha", "orran", "orrea",
+ "orren", "orrey", "orric", "orrie", "orsel", "orsen", "orsin",
+ "ortis", "orvie", "orvil", "orvin", "orwin", "osama", "osbon",
+ "oseye", "oshai", "oshay", "oshea", "osiel", "oskar", "osker",
+ "osmar", "osmel", "osmen", "osmer", "osner", "osred", "osric",
+ "ostad", "ostap", "osten", "ostin", "ostyn", "osvin", "oswin",
+ "oswyn", "osyth", "otess", "othon", "othor", "otila", "otman",
+ "otmar", "ottah", "ottey", "ottie", "ottla", "otton", "ouida",
+ "oveta", "owain", "owena", "owens", "owney", "owuor", "owynn",
+ "oxana", "ozara", "ozcan", "ozell", "ozgur", "ozias", "ozker",
+ "ozlem", "ozora", "ozrad", "ozzie", "paani", "paata", "paavo",
+ "pable", "pablo", "pachy", "pagen", "paget", "paige", "paili",
+ "paine", "paley", "palle", "palvi", "pammi", "pammy", "panas",
+ "pandi", "panom", "panos", "paola", "papni", "pappu", "parag",
+ "parke", "parys", "pasko", "patek", "patia", "paton", "patsi",
+ "patti", "patzi", "paula", "paule", "pauli", "paulo", "pauly",
+ "pavel", "pavit", "pavla", "pavle", "pavol", "pawel", "paxon",
+ "payal", "payam", "payat", "payge", "payne", "pazia", "pazit",
+ "pearu", "pecha", "peder", "peggi", "pejan", "pekah", "pekka",
+ "peleg", "pelin", "pello", "penee", "penly", "pepes", "peppe",
+ "peppi", "peral", "peran", "perce", "percy", "perec", "perka",
+ "perli", "perly", "perri", "persi", "petah", "petey", "petie",
+ "petru", "petta", "petur", "petya", "pheba", "pheby", "pheof",
+ "phila", "phili", "phill", "philo", "phoef", "phool", "phred",
+ "phuoc", "phuok", "phyfe", "phyll", "piedy", "piero", "pikke",
+ "pilan", "pilib", "pimen", "pimmi", "piotr", "pippa", "pippi",
+ "pippo", "pirjo", "pirro", "pista", "piter", "pitin", "pitte",
+ "pjotr", "plien", "pnina", "pohla", "poldi", "polla", "polli",
+ "popie", "poppi", "pouya", "powel", "premo", "prent", "priit",
+ "prinz", "prisi", "priti", "priya", "prudi", "prudy", "pruit",
+ "pryce", "pryor", "pucho", "pulak", "punyo", "purly", "purna",
+ "purvi", "puspa", "pyhis", "pyotr", "qabil", "qadim", "qadir",
+ "qadri", "qamar", "qamra", "qayum", "qiana", "qimat", "quent",
+ "queta", "quian", "quico", "quinn", "quita", "quock", "qusai",
+ "qusay", "quyen", "qwinn", "rabaa", "rabah", "rabee", "rabei",
+ "rabih", "rabri", "racel", "racha", "raddy", "radey", "radha",
+ "radik", "radim", "radly", "radue", "raeda", "raede", "raeed",
+ "raela", "raena", "raene", "rafal", "rafat", "rafee", "rafel",
+ "rafer", "raffi", "raffy", "rafic", "rafiq", "raful", "ragan",
+ "rageh", "raghd", "raghu", "ragna", "rahab", "raham", "rahel",
+ "rahil", "rahim", "rahna", "rahni", "rahul", "raiah", "raila",
+ "raina", "raine", "raini", "rainn", "raiph", "raisa", "raiza",
+ "rajaa", "rajai", "rajat", "rajiv", "rajni", "rakaa", "rakel",
+ "rakin", "ralee", "raley", "ralna", "ramaz", "ramey", "ramez",
+ "ramin", "ramos", "ramsy", "ramza", "ramzi", "ranae", "ranci",
+ "rancy", "randa", "rande", "randi", "ranen", "rania", "ranie",
+ "ranit", "ranji", "ranko", "ranna", "ranon", "raouf", "raoul",
+ "raphy", "rasha", "rasho", "rasia", "rasim", "rasja", "rasul",
+ "rasya", "rathi", "ratik", "ratip", "ratka", "ratna", "ratul",
+ "raula", "raulo", "ravan", "ravee", "ravia", "ravid", "raviv",
+ "ravon", "rawan", "rawhi", "rawia", "rawna", "rayan", "rayel",
+ "rayma", "rayna", "rayne", "rayya", "razel", "razia", "raziq",
+ "razzy", "reaad", "reade", "reamy", "reana", "rebah", "rebba",
+ "reeba", "reece", "reeda", "reema", "reena", "reeny", "reese",
+ "reeta", "reeva", "reggi", "reggy", "regia", "regin", "regis",
+ "rehna", "reida", "reide", "reijo", "reiko", "reine", "reino",
+ "reiny", "rekha", "remah", "remee", "remie", "remmy", "remzi",
+ "renae", "renan", "renat", "renee", "renia", "renie", "renke",
+ "renna", "renne", "renny", "renos", "renzo", "retha", "retta",
+ "revia", "rexan", "reyba", "reyde", "reyna", "reyne", "rezin",
+ "rezso", "rhawn", "rheba", "rheta", "rhett", "rhian", "rhoan",
+ "rhoda", "rhona", "rhyan", "riana", "riane", "riann", "riayn",
+ "ricca", "ricci", "ricco", "riccy", "richi", "richy", "ricka",
+ "ricke", "ricki", "ricky", "ricou", "riczi", "ridar", "ridha",
+ "ridly", "rieca", "rieka", "rieko", "riesa", "riess", "rieta",
+ "rifai", "rifha", "rifka", "rifki", "rigby", "rihab", "rihat",
+ "rikia", "rikki", "rikky", "riley", "rilie", "rilla", "rilya",
+ "rilye", "rinah", "rinat", "rinna", "riona", "riply", "riqua",
+ "riqui", "risha", "risly", "risto", "ritch", "ritha", "rithy",
+ "ritsa", "ritsi", "ritsy", "ritta", "rivah", "rivca", "rivka",
+ "rivvy", "riyad", "riyaz", "rizal", "rizus", "rizza", "roald",
+ "roana", "roann", "roark", "robbi", "robby", "robee", "roben",
+ "robhy", "robie", "rocco", "rocio", "rodas", "rodey", "rodgy",
+ "rodie", "rohin", "rohit", "roice", "rojay", "rolah", "rolan",
+ "roldy", "rolek", "roley", "rolfe", "rolle", "rollo", "rolon",
+ "rolph", "romel", "romen", "romie", "romke", "ronak", "ronal",
+ "ronan", "ronat", "rondi", "rondy", "ronee", "ronel", "ronen",
+ "ronia", "ronie", "ronit", "ronli", "ronna", "ronne", "ronni",
+ "ronny", "ronsy", "ronte", "roone", "roopa", "rorey", "rorie",
+ "rorke", "rorry", "rosan", "rosby", "rosco", "rosie", "rosio",
+ "rosle", "rosli", "rosse", "rossi", "rossy", "rotem", "rouda",
+ "rouza", "rowdi", "rowly", "roxcy", "roxey", "roxie", "royce",
+ "rozsa", "rozsi", "rozzi", "rozzy", "ruark", "rubee", "rubem",
+ "ruben", "rubey", "rubie", "rubin", "rubye", "ruchi", "ruddi",
+ "rudee", "rudek", "rudey", "rudin", "rufin", "ruhal", "rulan",
+ "rulon", "rumer", "ruppa", "rurik", "rusha", "rushi", "rusti",
+ "rutha", "ruthe", "ruthi", "ruthy", "ruven", "ruvim", "ruzha",
+ "ruzia", "ruzsa", "ruzya", "ryaad", "ryale", "ryana", "ryane",
+ "ryann", "rycca", "rylan", "rylee", "ryley", "rylie", "rylin",
+ "rylly", "rylyn", "ryman", "ryoji", "ryoko", "ryota", "ryozo",
+ "rysio", "ryssa", "ryuan", "saadi", "saamy", "saara", "sabel",
+ "saben", "sabit", "sabri", "sacha", "sachi", "sadad", "sadaf",
+ "sadah", "sadee", "sadek", "sadeq", "sadia", "sadie", "sadiq",
+ "sadja", "sadra", "sadri", "sadye", "sadyk", "saeed", "saeid",
+ "saemi", "safet", "saffi", "safia", "safra", "sagar", "sagia",
+ "sagit", "sahag", "sahan", "sahar", "sahen", "sahim", "sahir",
+ "sahla", "sahmi", "sahra", "saige", "saira", "sajad", "sajed",
+ "sajid", "sajit", "sakda", "salah", "saleh", "salil", "salim",
+ "salka", "salli", "salva", "salwa", "salye", "samad", "samah",
+ "sameh", "samet", "samie", "samil", "samir", "sammi", "samya",
+ "sanah", "sanat", "sande", "sandi", "sanja", "sanna", "sanne",
+ "sante", "sanyu", "saori", "sarad", "saraf", "sarah", "saral",
+ "sarey", "sarie", "sarit", "sarka", "sarog", "saroj", "sarri",
+ "saryn", "sasan", "sasha", "sasho", "sasie", "sason", "saulo",
+ "sauro", "savas", "savil", "savva", "sawad", "sawna", "saxbe",
+ "saxby", "saxen", "sayed", "sayge", "sayma", "scama", "scota",
+ "scott", "seana", "seane", "seann", "seany", "seara", "sebra",
+ "sedat", "seema", "seena", "seera", "seger", "seham", "sehba",
+ "sehed", "seidy", "seiji", "seila", "seira", "sekka", "sekou",
+ "selam", "selda", "selde", "selen", "selia", "selie", "selig",
+ "selim", "selin", "sello", "selwa", "semer", "semie", "semir",
+ "semon", "semra", "senad", "senay", "sener", "senga", "senia",
+ "senka", "senon", "senta", "seodi", "seppi", "seref", "seret",
+ "sergi", "sergo", "serko", "serle", "serug", "seryl", "serzh",
+ "sesar", "sesto", "sethe", "seula", "sevag", "sevgi", "seyed",
+ "seyla", "sezar", "shaan", "shabo", "shada", "shadd", "shadi",
+ "shaia", "shaka", "shana", "shane", "shani", "shann", "shary",
+ "shaud", "shaun", "shaye", "shayn", "shean", "sheff", "shela",
+ "sheli", "shems", "shena", "shene", "shepp", "shera", "sherb",
+ "shere", "sheri", "sherm", "sheye", "shiba", "shiek", "shifa",
+ "shika", "shila", "shile", "shilo", "shing", "shipp", "shiri",
+ "shiro", "shizu", "shoko", "shoma", "shoni", "shoun", "shree",
+ "shuka", "shuki", "shula", "shuma", "shyam", "shyan", "shyla",
+ "shyra", "siaka", "siana", "siara", "sibai", "sibby", "sibel",
+ "sibie", "siddy", "siegi", "siera", "sigal", "siggi", "siggy",
+ "signe", "signy", "siham", "sihem", "sihon", "silas", "silja",
+ "silka", "silke", "silvi", "silvy", "simah", "simao", "simba",
+ "simen", "simma", "simmi", "simms", "simmy", "simon", "sinae",
+ "sinan", "sinda", "sindi", "sindy", "siona", "sipho", "siraj",
+ "sirio", "sishi", "sissi", "sitah", "sitha", "sivia", "sivie",
+ "siwei", "sixta", "sixto", "sjaak", "sjohn", "sjure", "skeat",
+ "skila", "skipp", "skott", "skule", "skyla", "skyra", "slava",
+ "smeet", "smidt", "smita", "smyth", "sobhi", "sodek", "soffi",
+ "sofie", "sofka", "sofya", "sohar", "soile", "soley", "solje",
+ "solly", "solow", "somak", "somer", "sonal", "sonam", "sonay",
+ "sonei", "sonia", "sonja", "sonke", "sonni", "sonya", "sooki",
+ "sooze", "sophe", "sorah", "sorca", "soren", "sorin", "sosia",
+ "souad", "souza", "soyeb", "spero", "spiro", "spyke", "staas",
+ "stace", "staci", "stacy", "stana", "stano", "stasa", "stasy",
+ "stefa", "stefi", "steny", "steph", "steva", "stevi", "stevo",
+ "stevy", "stian", "stina", "stine", "storr", "strom", "studd",
+ "stuey", "suada", "suann", "subir", "sudeb", "sudha", "sudie",
+ "suela", "suely", "sueva", "sujal", "sujin", "sukee", "sulia",
+ "sulma", "sumed", "sumia", "sumie", "sumil", "sumio", "sumir",
+ "sumit", "sumon", "sumya", "sundi", "sundy", "sunee", "sunil",
+ "sunit", "sunne", "sunta", "sunya", "suphi", "suree", "susan",
+ "susen", "susey", "susie", "susil", "suson", "sussi", "sussy",
+ "sutan", "sutki", "suyen", "suzan", "suzie", "suzon", "suzue",
+ "suzyn", "svein", "svend", "sveva", "swane", "sybel", "sybil",
+ "syble", "sybyl", "sydel", "sydna", "sydni", "sydny", "sying",
+ "sylas", "sylke", "sylvi", "syman", "symia", "symin", "symms",
+ "symmy", "symon", "syndi", "syndy", "syrie", "syril", "syrus",
+ "sysky", "syver", "taavo", "tabbi", "tabea", "tabia", "tabib",
+ "tacey", "tacha", "tacia", "tacie", "tacye", "tadan", "tadao",
+ "taddy", "tadek", "tadeo", "tades", "tadey", "tadhg", "tadio",
+ "tadra", "tadzi", "taeke", "taghi", "taher", "tahir", "tahji",
+ "tahni", "taieb", "taija", "taika", "taimy", "taina", "taipa",
+ "taisa", "taite", "taitt", "taiva", "taiwo", "tajma", "takao",
+ "takis", "takra", "talad", "talal", "talan", "talat", "talea",
+ "talei", "talia", "talin", "talli", "tallu", "talna", "talor",
+ "talya", "talye", "tamaa", "tamah", "tamam", "taman", "tamia",
+ "tamie", "tamma", "tammi", "tamor", "tamra", "tamur", "tamya",
+ "tamye", "tanae", "tanaz", "tancy", "tandi", "tandy", "tanea",
+ "tanee", "tanek", "taner", "taney", "tanie", "tanja", "tanji",
+ "tanno", "tanny", "tansu", "tanun", "tanya", "tapio", "tarah",
+ "tarai", "tarak", "taran", "tarea", "taree", "tarek", "tareq",
+ "tarha", "taria", "tarif", "tarik", "tariq", "tarir", "taris",
+ "tarra", "tarun", "taryl", "taryn", "tasha", "tashi", "tasho",
+ "tasia", "tasja", "taska", "tasos", "tassi", "tasya", "tateo",
+ "tatia", "tatum", "tauna", "tauni", "tauno", "tavah", "tavey",
+ "tavia", "tavie", "tavis", "tawia", "tawni", "tawno", "tayah",
+ "tayib", "tayla", "tayna", "tayte", "tayva", "tazio", "teala",
+ "teale", "teana", "teann", "teara", "teata", "tecca", "techi",
+ "tecla", "tedda", "tedde", "teddi", "tedek", "tedik", "tedor",
+ "tedra", "teedy", "teena", "teeya", "tegan", "tegin", "tehar",
+ "tehra", "teige", "teiji", "teina", "teira", "tejah", "tejal",
+ "tejan", "tejas", "tekla", "tekle", "tekli", "telca", "telek",
+ "telem", "telka", "telle", "telmo", "telsa", "tembo", "temma",
+ "tenae", "tenea", "teney", "teral", "teran", "terel", "teren",
+ "terez", "teria", "terie", "teris", "terje", "terre", "tersa",
+ "terun", "teruo", "teryl", "teryn", "terza", "tesha", "tesia",
+ "tessa", "tessi", "tessy", "tetsu", "tetsy", "tetty", "teuku",
+ "teuvo", "tevel", "tevin", "tevis", "tevya", "tevye", "teyna",
+ "tezia", "thabo", "thada", "thadd", "thady", "thain", "thama",
+ "thanh", "thavi", "theda", "theia", "theon", "theys", "thiab",
+ "thian", "thien", "thilo", "thoma", "thomi", "thomy", "thora",
+ "thord", "thyra", "tiago", "tiana", "tiaon", "tiaya", "tibor",
+ "tichi", "ticho", "tiege", "tiena", "tiffi", "tifni", "tigan",
+ "tijan", "tijeh", "tikia", "tilar", "tilda", "tildi", "tildy",
+ "tilli", "tilly", "timae", "timie", "timin", "timka", "timmi",
+ "timmy", "timna", "timok", "timot", "timur", "tinai", "tiney",
+ "tinho", "tinka", "tippi", "tiqua", "tirah", "tirea", "tirel",
+ "tirsa", "tirza", "tisah", "tisha", "tison", "tissa", "titek",
+ "titia", "titos", "titus", "tivon", "tiyah", "toaha", "tobal",
+ "tobar", "tobby", "tobee", "tobey", "tobia", "tobie", "tobin",
+ "tobye", "todor", "tofer", "tofik", "tofiq", "tohon", "tohti",
+ "tokio", "tolek", "tolga", "tolia", "tomar", "tomas", "tomaz",
+ "tomcy", "tomek", "tomer", "tomey", "tomie", "tomik", "tomio",
+ "tomma", "tomme", "tommi", "tonda", "tonee", "tonek", "tonia",
+ "tonie", "tonik", "tonio", "tonis", "tonja", "tonni", "tonse",
+ "tonya", "tonye", "toren", "torey", "toria", "torie", "torin",
+ "torio", "torre", "torri", "torry", "torya", "torye", "tosha",
+ "toshi", "tosia", "tosin", "toska", "totsi", "totti", "tovah",
+ "tovia", "tovya", "traci", "tracy", "trava", "tresa", "trese",
+ "treva", "treve", "treza", "tribi", "tricy", "trigg", "trina",
+ "trini", "trink", "tripp", "trisa", "trish", "trixi", "trixy",
+ "troia", "trola", "trond", "troya", "troye", "truby", "truda",
+ "trude", "trudi", "trudy", "trula", "tryna", "tsend", "tsion",
+ "tsvia", "tuari", "tuffy", "tuija", "tukie", "tukun", "tulah",
+ "tulio", "tully", "tuluy", "tunde", "tuula", "tuvia", "tuvya",
+ "tuyen", "twayn", "twila", "twyla", "tyann", "tyara", "tybie",
+ "tycho", "tyesn", "tykia", "tylar", "tylda", "tyldy", "tylea",
+ "tylee", "tylia", "tylor", "tymon", "tynan", "tynka", "tyraa",
+ "tyrae", "tyrah", "tyray", "tyrea", "tyree", "tyrel", "tyria",
+ "tyrik", "tyriq", "tyron", "tysha", "tysie", "tysne", "tyson",
+ "tyssa", "tytan", "tytus", "tywan", "tywon", "tzahi", "tzevi",
+ "tzion", "uaine", "udale", "udall", "udele", "udell", "udolf",
+ "uford", "ugutz", "ujjal", "ukasz", "ulana", "ulane", "ulane",
+ "ulani", "ulger", "ulick", "ulima", "ullah", "ullas", "ulmar",
+ "ulmer", "ulrik", "ultan", "umang", "umarr", "umaru", "umayr",
+ "umeko", "umesh", "umeyo", "unica", "unice", "unika", "uniss",
+ "unita", "unsun", "unwin", "unwyn", "ureli", "uriah", "urian",
+ "urias", "uriel", "urien", "urika", "urmas", "ursei", "ursel",
+ "ursey", "ursie", "urtzi", "urvan", "usama", "ushma", "ustad",
+ "ustin", "utako", "utibe", "utina", "uttam", "uttra", "uzair",
+ "uziel", "uzzah", "vadim", "vadin", "vadit", "vadym", "vagit",
+ "vahan", "vaidy", "vaile", "vaill", "vaira", "vaiva", "valda",
+ "valen", "valia", "valin", "valle", "valli", "valma", "valry",
+ "valya", "valyn", "vanae", "vance", "vandi", "vanek", "vangy",
+ "vania", "vanko", "vanna", "vanni", "vanno", "vanny", "vanya",
+ "varel", "varga", "varro", "varun", "varya", "vasco", "vasek",
+ "vasil", "vasin", "vasko", "vasos", "vasti", "vasya", "vasyl",
+ "vayle", "vazul", "vedad", "vedis", "veeda", "veera", "veeta",
+ "veeva", "veida", "veiko", "veira", "velda", "velma", "vence",
+ "venis", "venna", "venya", "veola", "veran", "verda", "verdi",
+ "vered", "veria", "verka", "verla", "verly", "verna", "verne",
+ "veron", "verta", "veryl", "vesna", "vessy", "vesty", "vetha",
+ "veton", "viana", "viann", "vibhu", "vicci", "viccy", "viciu",
+ "vicke", "vicki", "vicky", "victa", "videl", "vidia", "vidor",
+ "vieda", "viera", "vieva", "viggo", "vijai", "vijay", "vikas",
+ "vikie", "vikki", "vikky", "vilay", "vilek", "vilem", "vilen",
+ "vilis", "viliy", "viljo", "vilma", "vimka", "vimla", "vinay",
+ "vince", "vinci", "vinco", "vincy", "vinia", "vinko", "vinna",
+ "vinni", "vinod", "viole", "viona", "vipin", "vipul", "virge",
+ "virgy", "virna", "vitel", "vitia", "vitin", "vitka", "vitke",
+ "vitus", "vitya", "vivan", "vivee", "vivek", "vivia", "vivie",
+ "vivva", "vivvy", "vizma", "vlade", "vlado", "volya", "vonda",
+ "vonna", "vonni", "vonny", "vraja", "vytas", "waban", "wadie",
+ "wadly", "wafik", "wafiq", "wahbi", "waide", "waiel", "waite",
+ "wakil", "walda", "waldi", "waldy", "walid", "walie", "walli",
+ "wally", "walon", "walsh", "waltr", "wamid", "wanda", "wandi",
+ "wanja", "wanye", "waqar", "warda", "warde", "waris", "warny",
+ "wasim", "wayan", "wayde", "wayne", "wayte", "webly", "wedad",
+ "weeko", "welby", "welda", "welti", "wenda", "wendi", "wendy",
+ "werth", "wesam", "wesla", "wesly", "whitt", "whoda", "whyte",
+ "wiatt", "widad", "wikie", "wilba", "wilda", "wildy", "wilek",
+ "wiley", "willa", "wille", "willi", "willo", "wilma", "wilna",
+ "wimar", "winda", "windi", "winne", "winni", "winny", "wintr",
+ "wisia", "witek", "witha", "woana", "wolfe", "wolff", "wolfy",
+ "wonda", "woney", "woolf", "worie", "worom", "wudeh", "wyant",
+ "wyatt", "wyche", "wyeth", "wylda", "wylie", "wylma", "wyman",
+ "wymer", "wyndi", "wyndy", "wynny", "xandy", "xanne", "xaver",
+ "xavia", "xavon", "xever", "xiang", "xylon", "yaani", "yacef",
+ "yachi", "yacov", "yaeko", "yaeli", "yaffa", "yafit", "yagel",
+ "yagil", "yahia", "yahir", "yahya", "yaile", "yaima", "yaisy",
+ "yajur", "yakez", "yakob", "yakov", "yamie", "yamka", "yanah",
+ "yanar", "yance", "yanci", "yancy", "yanet", "yaney", "yania",
+ "yanik", "yanis", "yaniv", "yanka", "yanna", "yanni", "yanno",
+ "yanti", "yarek", "yarey", "yariv", "yaron", "yasar", "yaser",
+ "yasha", "yasir", "yasma", "yasuo", "yatin", "yavin", "yazan",
+ "yazen", "yazid", "yeala", "yeats", "yefat", "yefim", "yegor",
+ "yehed", "yehor", "yehua", "yeira", "yelba", "yenih", "yenni",
+ "yenny", "yensy", "yeshi", "yesim", "yeska", "yetta", "yetty",
+ "yevno", "yezad", "yezzy", "yhaya", "yhuda", "yifan", "yigel",
+ "yihye", "yinka", "yipsi", "yitro", "yitta", "ylana", "yngve",
+ "yoana", "yoash", "yobie", "yodit", "yohji", "yokie", "yoley",
+ "yolie", "yolly", "yonah", "yonas", "yonat", "yonca", "yonit",
+ "yonna", "yoram", "yorga", "yorgo", "yorke", "yosef", "yoshi",
+ "yosif", "yosik", "yosor", "yosri", "yossi", "yosyf", "yotam",
+ "youri", "yovan", "ysann", "ysbel", "yseut", "ysolt", "ystad",
+ "yuana", "yuber", "yubin", "yucel", "yudah", "yudel", "yudit",
+ "yuiki", "yukie", "yulia", "yulie", "yulla", "yunas", "yunus",
+ "yuria", "yurii", "yurij", "yuriy", "yurko", "yurri", "yusef",
+ "yusha", "yusif", "yusri", "yusuf", "yusup", "yuuki", "yuval",
+ "yvana", "yvens", "yvone", "zabit", "zacha", "zachy", "zacky",
+ "zadie", "zadik", "zadoc", "zafar", "zafir", "zaher", "zahik",
+ "zahir", "zahra", "zahur", "zaiba", "zaide", "zaira", "zakes",
+ "zakey", "zakia", "zakir", "zakri", "zakry", "zaleh", "zalfa",
+ "zamah", "zamir", "zanda", "zandy", "zaned", "zanna", "zanne",
+ "zanny", "zanth", "zarai", "zareb", "zared", "zaree", "zarek",
+ "zarin", "zarko", "zarya", "zasha", "zayda", "zayed", "zayit",
+ "zayle", "zayna", "zayne", "zayta", "zazai", "zazie", "zealy",
+ "zeeba", "zeena", "zeeta", "zeeva", "zeevi", "zefir", "zeheb",
+ "zeina", "zelah", "zelda", "zelde", "zelia", "zelie", "zelig",
+ "zelik", "zella", "zelma", "zemah", "zemar", "zenab", "zenah",
+ "zenan", "zenas", "zenea", "zenia", "zenna", "zenon", "zenos",
+ "zenya", "zerah", "zerla", "zerom", "zetes", "zetta", "zevie",
+ "zeyno", "zhana", "zhora", "zhvie", "zibby", "zidan", "ziggy",
+ "zigor", "zihna", "zilah", "zilla", "zilya", "zimra", "zimri",
+ "zinah", "zinia", "zinka", "zinna", "zinny", "zinon", "zinya",
+ "ziral", "zirel", "zishe", "ziska", "ziven", "zivia", "zivie",
+ "zivit", "zivka", "zivko", "zivon", "zizou", "zocha", "zoela",
+ "zofer", "zofia", "zofka", "zohra", "zoila", "zoilo", "zolly",
+ "zonia", "zoran", "zorba", "zorie", "zorna", "zorya", "zouri",
+ "zoyya", "zsolt", "zubah", "zubin", "zulay", "zulma", "zurab",
+ "zuria", "zviad", "zylla"
+ };
+
+ public String getText() {
+ int car = FIRST_NAMES.length - 1;
+ return FIRST_NAMES[GENERATOR.nextInt(car) + 1];
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/producer/TextProducer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,16 @@
+package nl.captcha.text.producer;
+
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public interface TextProducer {
+
+ /**
+ * Generate a series of characters.
+ *
+ * @return
+ */
+ public String getText();
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/ColoredEdgesWordRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,103 @@
+package nl.captcha.text.renderer;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.font.FontRenderContext;
+import java.awt.font.TextAttribute;
+import java.awt.font.TextLayout;
+import java.awt.geom.AffineTransform;
+import java.awt.image.BufferedImage;
+import java.security.SecureRandom;
+import java.text.AttributedCharacterIterator;
+import java.text.AttributedString;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Creates an outlined version of the answer using the given colors and fonts.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public class ColoredEdgesWordRenderer implements WordRenderer {
+
+ private static final List<Color> DEFAULT_COLORS = new ArrayList<Color>();
+ private static final List<Font> DEFAULT_FONTS = new ArrayList<Font>();
+ private static final float DEFAULT_STROKE_WIDTH = 0.5f;
+ // The text will be rendered 25%/5% of the image height/width from the X and Y axes
+ private static final double YOFFSET = 0.25;
+ private static final double XOFFSET = 0.05;
+
+ private final List<Font> _fonts;
+ private final List<Color> _colors;
+ private final float _strokeWidth;
+
+ static {
+ DEFAULT_FONTS.add(new Font("Arial", Font.BOLD, 40));
+ DEFAULT_COLORS.add(Color.BLUE);
+ }
+
+ public ColoredEdgesWordRenderer() {
+ this(DEFAULT_COLORS, DEFAULT_FONTS, DEFAULT_STROKE_WIDTH);
+ }
+
+ public ColoredEdgesWordRenderer(List<Color> colors, List<Font> fonts) {
+ this(colors, fonts, DEFAULT_STROKE_WIDTH);
+ }
+
+ public ColoredEdgesWordRenderer(List<Color> colors, List<Font> fonts, float strokeWidth) {
+ _colors = colors != null ? colors : DEFAULT_COLORS;
+ _fonts = fonts != null ? fonts : DEFAULT_FONTS;
+ _strokeWidth = strokeWidth < 0 ? DEFAULT_STROKE_WIDTH : strokeWidth;
+ }
+
+ public void render(final String word, BufferedImage image) {
+ Graphics2D g = image.createGraphics();
+
+ RenderingHints hints = new RenderingHints(
+ RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ hints.add(new RenderingHints(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY));
+ g.setRenderingHints(hints);
+
+ AttributedString as = new AttributedString(word);
+ as.addAttribute(TextAttribute.FONT, getRandomFont());
+
+ FontRenderContext frc = g.getFontRenderContext();
+ AttributedCharacterIterator aci = as.getIterator();
+
+ TextLayout tl = new TextLayout(aci, frc);
+ int xBaseline = (int) Math.round(image.getWidth() * XOFFSET);
+ int yBaseline = image.getHeight() - (int) Math.round(image.getHeight() * YOFFSET);
+ Shape shape = tl.getOutline(AffineTransform.getTranslateInstance(xBaseline, yBaseline));
+
+ g.setColor(getRandomColor());
+ g.setStroke(new BasicStroke(_strokeWidth));
+
+ g.draw(shape);
+ }
+
+ private Color getRandomColor() {
+ return (Color) getRandomObject(_colors);
+ }
+
+ private Font getRandomFont() {
+ return (Font) getRandomObject(_fonts);
+ }
+
+ private Object getRandomObject(List<? extends Object> objs) {
+ if (objs.size() == 1) {
+ return objs.get(0);
+ }
+
+ Random gen = new SecureRandom();
+ int i = gen.nextInt(objs.size());
+ return objs.get(i);
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/DefaultWordRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,79 @@
+package nl.captcha.text.renderer;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.image.BufferedImage;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * Render a word using the given color and from a randomly selected font chosen from
+ * a list of fonts given in the constructor.
+ *
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ */
+public class DefaultWordRenderer implements WordRenderer {
+
+ private static final Color DEFAULT_COLOR = Color.BLACK;
+ private static final List<Font> DEFAULT_FONTS = new ArrayList<Font>();
+
+ private final Color _color;
+ private final List<Font> _fonts;
+
+ static {
+ DEFAULT_FONTS.add(new Font("Arial", Font.BOLD, 40));
+ DEFAULT_FONTS.add(new Font("Courier", Font.BOLD, 40));
+ }
+
+ /**
+ * Will render the characters in black and in either 40pt Arial or Courier.
+ */
+ public DefaultWordRenderer() {
+ this(DEFAULT_COLOR, DEFAULT_FONTS);
+ }
+
+ public DefaultWordRenderer(Color color, List<Font> fonts) {
+ _color = color != null ? color : DEFAULT_COLOR;
+ _fonts = fonts != null ? fonts : DEFAULT_FONTS;
+ }
+
+ /**
+ * Render a word onto a BufferedImage.
+ *
+ * @param word The word to be rendered.
+ * @param bi The BufferedImage onto which the word will be painted on to
+ */
+ public void render(String word, BufferedImage image) {
+ Graphics2D g = image.createGraphics();
+
+ RenderingHints hints = new RenderingHints(
+ RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ hints.add(new RenderingHints(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY));
+ g.setRenderingHints(hints);
+
+ g.setColor(_color);
+ FontRenderContext frc = g.getFontRenderContext();
+ int startPosX = 25;
+ char[] wc = word.toCharArray();
+ Random generator = new Random();
+ for (char element : wc) {
+ char[] itchar = new char[] { element };
+ int choiceFont = generator.nextInt(_fonts.size());
+ Font itFont = _fonts.get(choiceFont);
+ g.setFont(itFont);
+
+ GlyphVector gv = itFont.createGlyphVector(frc, itchar);
+ double charWitdth = gv.getVisualBounds().getWidth();
+
+ g.drawChars(itchar, 0, itchar.length, startPosX, 35);
+ startPosX = startPosX + (int) charWitdth;
+ }
+ }
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/text/renderer/WordRenderer.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,23 @@
+package nl.captcha.text.renderer;
+
+import java.awt.image.BufferedImage;
+
+/**
+ * @author <a href="mailto:james.childers at gmail.com">James Childers</a>
+ *
+ */
+public interface WordRenderer {
+ /**
+ * Render a word to a BufferedImage.
+ *
+ * @param word
+ * The word to be rendered.
+ * @param width
+ * The width of the image to be created.
+ * @param height
+ * The height of the image to be created.
+ * @return The BufferedImage created from the word.
+ */
+ public void render(String word, BufferedImage image);
+
+}
Added: components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java
===================================================================
--- components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java (rev 0)
+++ components/simplecaptcha/trunk/src/main/java/nl/captcha/util/ImageUtil.java 2010-03-31 15:23:50 UTC (rev 2410)
@@ -0,0 +1,18 @@
+package nl.captcha.util;
+
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+
+public class ImageUtil {
+ public static final void applyFilter(BufferedImage img, ImageFilter filter) {
+// FilteredImageSource src = new FilteredImageSource(img.getSource(), filter);
+ Image fImg = Toolkit.getDefaultToolkit().createImage(img.getSource());
+ Graphics2D g = img.createGraphics();
+ g.drawImage(fImg, 0, 0, null, null);
+ g.dispose();
+ }
+}
More information about the gatein-commits
mailing list