version 0.2.13
[fms.git] / src / freenet / captcha / simplecaptcha.cpp
1 #include "../../../include/freenet/captcha/simplecaptcha.h"\r
2 #include "../../../include/freenet/captcha/easybmp/EasyBMP.h"\r
3 #include "../../../include/freenet/captcha/easybmp/EasyBMP_Font.h"\r
4 #include "../../../include/freenet/captcha/easybmp/EasyBMP_Geometry.h"\r
5 \r
6 #include <cstdlib>\r
7 \r
8 #ifdef XMEM\r
9         #include <xmem.h>\r
10 #endif\r
11 \r
12 void SimpleCaptcha::Generate()\r
13 {\r
14         BMP bmp;\r
15         int bmpwidth=110;\r
16         int bmpheight=50;\r
17         RGBApixel lettercols[5];\r
18         std::string puzzlestring;\r
19         std::string tempfilename=GenerateRandomString(10);\r
20         tempfilename+=".bmp";\r
21 \r
22         puzzlestring=GenerateRandomString(5);\r
23         m_solution.clear();\r
24         m_solution.insert(m_solution.begin(),puzzlestring.begin(),puzzlestring.end());\r
25 \r
26         bmp.SetSize(bmpwidth,bmpheight);\r
27 \r
28         // first draw some random lines around the bitmap\r
29         int numlines=(rand()%10)+10;\r
30         for(int i=0; i<numlines; i++)\r
31         {\r
32                 RGBApixel pixel;\r
33                 int x1=rand()%bmpwidth;\r
34                 int y1=rand()%bmpheight;\r
35                 int x2=rand()%bmpwidth;\r
36                 int y2=rand()%bmpwidth;\r
37                 // keep the colors light\r
38                 pixel.Red=100+(rand()%150);\r
39                 pixel.Green=100+(rand()%150);\r
40                 pixel.Blue=100+(rand()%150);\r
41                 DrawAALine(bmp,x1,y1,x2,y2,pixel);\r
42         }\r
43 \r
44         // draw some random arcs\r
45         int numarcs=(rand()%10)+10;\r
46         for(int i=0; i<numarcs; i++)\r
47         {\r
48                 RGBApixel pixel;\r
49                 int x1=rand()%bmpwidth;\r
50                 int y1=rand()%bmpwidth;\r
51                 int radius=rand()%(bmpheight/2);\r
52                 double startangle=(double)(rand()%360)*(3.14159/180);\r
53                 double endangle=(double)(rand()%360)*(3.14159/180);\r
54                 pixel.Red=100+(rand()%150);\r
55                 pixel.Green=100+(rand()%150);\r
56                 DrawArc(bmp,x1,y1,radius,startangle,endangle,pixel);\r
57         }\r
58 \r
59         for(int i=0; i<5; i++)\r
60         {\r
61                 // keep the colors dark\r
62                 lettercols[i].Red=(rand()%200);\r
63                 lettercols[i].Green=(rand()%200);\r
64                 lettercols[i].Blue=(rand()%200);\r
65                 // draw a line with the letter col\r
66                 DrawAALine(bmp,rand()%bmpwidth,rand()%bmpheight,rand()%bmpwidth,rand()%bmpheight,lettercols[i]);\r
67         }\r
68 \r
69         // print puzzle onto bitmap\r
70         for(int i=0; i<5; i++)\r
71         {\r
72                 PrintLetter(bmp,puzzlestring[i],5+(i*20)+(rand()%11)-5,10+(rand()%10),20,lettercols[i]);\r
73         }\r
74 \r
75         /* TOO dificult to solve with this\r
76         // skew image left/right\r
77         double skew=0;\r
78         for(int yy=0; yy<bmpheight; yy++)\r
79         {\r
80                 RGBApixel pixel;\r
81                 skew=skew+(double)((rand()%11)-5)/20.0;\r
82                 int xx;\r
83                 for(xx=0; xx<skew; xx++)\r
84                 {\r
85                         pixel.Red=255;\r
86                         pixel.Green=255;\r
87                         pixel.Blue=255;\r
88                         bmp.SetPixel(xx,yy,pixel);\r
89                 }\r
90                 if(skew<0)\r
91                 {\r
92                         for(xx=0; xx<bmpwidth+skew; xx++)\r
93                         {\r
94                                 pixel=bmp.GetPixel(xx-skew,yy);\r
95                                 bmp.SetPixel(xx,yy,pixel);\r
96                         }\r
97                 }\r
98                 else\r
99                 {\r
100                         for(xx=bmpwidth-1; xx>skew; xx--)\r
101                         {\r
102                                 pixel=bmp.GetPixel(xx-skew,yy);\r
103                                 bmp.SetPixel(xx,yy,pixel);\r
104                         }\r
105                 }\r
106                 for(xx=bmpwidth+skew; xx<bmpwidth; xx++)\r
107                 {\r
108                         pixel.Red=255;\r
109                         pixel.Green=255;\r
110                         pixel.Blue=255;\r
111                         bmp.SetPixel(xx,yy,pixel);\r
112                 }\r
113         }\r
114         */\r
115 \r
116         // generate noise for each pixel\r
117         for(int yy=0; yy<bmpheight; yy++)\r
118         {\r
119                 for(int xx=0; xx<bmpwidth; xx++)\r
120                 {\r
121                         RGBApixel pixel=bmp.GetPixel(xx,yy);\r
122                         int tempred=pixel.Red+(rand()%21)-10;\r
123                         int tempgreen=pixel.Green+(rand()%21)-10;\r
124                         int tempblue=pixel.Blue+(rand()%21)-10;\r
125 \r
126                         tempred < 0 ? tempred=0 : false;\r
127                         tempred > 255 ? tempred=255 : false;\r
128                         tempgreen < 0 ? tempgreen=0 : false;\r
129                         tempgreen > 255 ? tempgreen=255 : false;\r
130                         tempblue < 0 ? tempblue=0 : false;\r
131                         tempblue > 255 ? tempblue=255 : false;\r
132 \r
133                         pixel.Red=tempred;\r
134                         pixel.Green=tempgreen;\r
135                         pixel.Blue=tempblue;\r
136 \r
137                         bmp.SetPixel(xx,yy,pixel);\r
138                 }\r
139         }\r
140 \r
141         bmp.WriteToFile(tempfilename.c_str());\r
142         ReadPuzzleData(tempfilename);\r
143         unlink(tempfilename.c_str());\r
144 }\r
145 \r
146 const std::string SimpleCaptcha::GenerateRandomString(const int len)\r
147 {\r
148         // no l,1 O,0 because they look too much alike\r
149         static std::string chars="abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789";\r
150         std::string temp="";\r
151         for(int i=0; i<len; i++)\r
152         {\r
153                 temp+=chars[rand()%chars.size()];\r
154         }\r
155         return temp;\r
156 }\r
157 \r
158 const bool SimpleCaptcha::GetPuzzle(std::vector<unsigned char> &puzzle)\r
159 {\r
160         puzzle=m_puzzle;\r
161         return true;\r
162 }\r
163 \r
164 const bool SimpleCaptcha::GetSolution(std::vector<unsigned char> &solution)\r
165 {\r
166         solution=m_solution;\r
167         return true;\r
168 }\r
169 \r
170 void SimpleCaptcha::ReadPuzzleData(const std::string &filename)\r
171 {\r
172         long filelen;\r
173         FILE *infile=fopen(filename.c_str(),"rb");\r
174         if(infile)\r
175         {\r
176                 fseek(infile,0,SEEK_END);\r
177                 filelen=ftell(infile);\r
178                 fseek(infile,0,SEEK_SET);\r
179                 m_puzzle.resize(filelen);\r
180                 fread(&m_puzzle[0],1,filelen,infile);\r
181                 fclose(infile);\r
182         }\r
183 }\r