Author: thomas.heute(a)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@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@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@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@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@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@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@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@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@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@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@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@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@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(a)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@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@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@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@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@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@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@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@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@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();
+ }
+}