07f4dde2ee8831540669c85f461f545540576e23
[fms.git] / src / freenet / captcha / alternatecaptcha1.cpp
1 #include "../../../include/freenet/captcha/alternatecaptcha1.h"\r
2 \r
3 #include <Poco/Path.h>\r
4 #include <Poco/DirectoryIterator.h>\r
5 \r
6 #include <cmath>\r
7 \r
8 #ifdef ALTERNATE_CAPTCHA\r
9 \r
10 bool AlternateCaptcha1::m_fontsloaded(false);\r
11 std::vector<FreeImage::Font> AlternateCaptcha1::m_fonts;\r
12 \r
13 AlternateCaptcha1::AlternateCaptcha1()\r
14 {\r
15         if(m_fontsloaded==false)\r
16         {\r
17                 FreeImage_Initialise(true);\r
18                 LoadFonts();\r
19                 m_fontsloaded=true;\r
20         }\r
21 }\r
22 \r
23 void AlternateCaptcha1::Generate()\r
24 {\r
25         std::string puzzlestring=GenerateRandomString(5);\r
26         FreeImage::Bitmap tempchar(50,50,32);\r
27         tempchar.SetTransparent();\r
28         FreeImage::Bitmap bmp(110,50,32);\r
29         bmp.SetTransparent();\r
30 \r
31         m_solution.clear();\r
32         m_puzzle.clear();\r
33 \r
34         // draw the text\r
35         if(m_fonts.size()>0)\r
36         {\r
37                 for(int i=0; i<puzzlestring.size(); i++)\r
38                 {\r
39                         RGBQUAD black;\r
40                         black.rgbRed=0;\r
41                         black.rgbGreen=0;\r
42                         black.rgbBlue=0;\r
43                         int xoffset=(i*20)-(5+(rand()%5));\r
44                         int yoffset=(rand()%20)-10;\r
45                         int fontnum=rand()%m_fonts.size();\r
46                         FreeImage::Bitmap charbmp=m_fonts[fontnum].Char(puzzlestring[i]);\r
47 \r
48                         tempchar.SetTransparent();\r
49                         tempchar.ClearTransparent();\r
50                         tempchar.BlitTrans(charbmp,25-(charbmp.Width()/2),25-(charbmp.Height()/2),0,0,charbmp.Width(),charbmp.Height());\r
51                         tempchar.Rotate((rand()%60)-30,0,0,25,25);\r
52 \r
53                         bmp.BlitTrans(tempchar,xoffset,yoffset,0,0,50,50);\r
54                 }\r
55         }\r
56 \r
57         //place some random lines\r
58         RGBQUAD white;\r
59         white.rgbRed=255;\r
60         white.rgbGreen=255;\r
61         white.rgbBlue=255;\r
62         white.rgbReserved=255;\r
63         int numlines=(rand()%5)+10;\r
64         for(int i=0; i<numlines; i++)\r
65         {\r
66                 // draw 4 short lines very close to each other\r
67                 int x1[4];\r
68                 int y1[4];\r
69                 int x2[4];\r
70                 int y2[4];\r
71 \r
72                 x1[0]=rand()%bmp.Width();\r
73                 y1[0]=rand()%bmp.Height();\r
74                 x2[0]=x1[0]+(rand()%40)-20;\r
75                 y2[0]=y1[0]+(rand()%40)-20;\r
76 \r
77                 for(int i=1; i<4; i++)\r
78                 {\r
79                         x1[i]=x1[i-1]+rand()%3-1;\r
80                         y1[i]=y1[i-1]+rand()%3-1;\r
81                         x2[i]=x2[i-1]+rand()%3-1;\r
82                         y2[i]=y2[i-1]+rand()%3-1;\r
83                 }\r
84 \r
85                 for(int i=0; i<4; i++)\r
86                 {\r
87                         bmp.Line(x1[i],y1[i],x2[i],y2[i],white);\r
88                 }\r
89         }\r
90 \r
91         int offset=rand()%10000;\r
92         for(int y=0; y<bmp.Height(); y++)\r
93         {\r
94                 double shift=sin((double)(y+offset)/3.0);\r
95                 bmp.HorizontalOffset(y,shift);\r
96         }\r
97 \r
98         m_solution.clear();\r
99         m_solution.insert(m_solution.end(),puzzlestring.begin(),puzzlestring.end());\r
100         m_puzzle.clear();\r
101         bmp.SaveToMemory("bmp",m_puzzle);\r
102 \r
103 }\r
104 \r
105 const std::string AlternateCaptcha1::GenerateRandomString(const int len)\r
106 {\r
107         // no l,1 O,0 because they look too much alike\r
108         static std::string chars="abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789@#";\r
109         std::string temp="";\r
110         for(int i=0; i<len; i++)\r
111         {\r
112                 temp+=chars[rand()%chars.size()];\r
113         }\r
114         return temp;\r
115 }\r
116 \r
117 const bool AlternateCaptcha1::GetPuzzle(std::vector<unsigned char> &puzzle)\r
118 {\r
119         puzzle=m_puzzle;\r
120         return true;\r
121 }\r
122 \r
123 const bool AlternateCaptcha1::GetSolution(std::vector<unsigned char> &solution)\r
124 {\r
125         solution=m_solution;\r
126         return true;\r
127 }\r
128 \r
129 void AlternateCaptcha1::LoadFonts()\r
130 {\r
131         FreeImage::Bitmap bmp;\r
132         Poco::Path path("fonts");\r
133         Poco::DirectoryIterator di(path);\r
134         Poco::DirectoryIterator end;\r
135 \r
136         while(di!=end)\r
137         {\r
138                 if(di.name().find("bmp")!=std::string::npos)\r
139                 {\r
140                         bmp.Load("bmp",di.path().toString());\r
141                         m_fonts.push_back(FreeImage::Font(bmp));\r
142                 }\r
143                 ++di;\r
144         }\r
145 \r
146 }\r
147 \r
148 #endif  // ALTERNATE_CAPTCHA\r