version 0.2.15
[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                 pixel.Blue=100+(rand()%150);\r
57                 DrawArc(bmp,x1,y1,radius,startangle,endangle,pixel);\r
58         }\r
59 \r
60         for(int i=0; i<5; i++)\r
61         {\r
62                 // keep the colors dark\r
63                 lettercols[i].Red=(rand()%150);\r
64                 lettercols[i].Green=(rand()%150);\r
65                 lettercols[i].Blue=(rand()%150);\r
66                 // draw a line with the letter color\r
67                 DrawAALine(bmp,rand()%bmpwidth,rand()%bmpheight,rand()%bmpwidth,rand()%bmpheight,lettercols[i]);\r
68         }\r
69 \r
70         // print puzzle onto bitmap\r
71         for(int i=0; i<5; i++)\r
72         {\r
73                 PrintLetter(bmp,puzzlestring[i],5+(i*20)+(rand()%11)-5,10+(rand()%10),20,lettercols[i]);\r
74         }\r
75 \r
76         /* TOO dificult to solve with this\r
77         // skew image left/right\r
78         double skew=0;\r
79         for(int yy=0; yy<bmpheight; yy++)\r
80         {\r
81                 RGBApixel pixel;\r
82                 skew=skew+(double)((rand()%11)-5)/20.0;\r
83                 int xx;\r
84                 for(xx=0; xx<skew; xx++)\r
85                 {\r
86                         pixel.Red=255;\r
87                         pixel.Green=255;\r
88                         pixel.Blue=255;\r
89                         bmp.SetPixel(xx,yy,pixel);\r
90                 }\r
91                 if(skew<0)\r
92                 {\r
93                         for(xx=0; xx<bmpwidth+skew; xx++)\r
94                         {\r
95                                 pixel=bmp.GetPixel(xx-skew,yy);\r
96                                 bmp.SetPixel(xx,yy,pixel);\r
97                         }\r
98                 }\r
99                 else\r
100                 {\r
101                         for(xx=bmpwidth-1; xx>skew; xx--)\r
102                         {\r
103                                 pixel=bmp.GetPixel(xx-skew,yy);\r
104                                 bmp.SetPixel(xx,yy,pixel);\r
105                         }\r
106                 }\r
107                 for(xx=bmpwidth+skew; xx<bmpwidth; xx++)\r
108                 {\r
109                         pixel.Red=255;\r
110                         pixel.Green=255;\r
111                         pixel.Blue=255;\r
112                         bmp.SetPixel(xx,yy,pixel);\r
113                 }\r
114         }\r
115         */\r
116 \r
117         // generate noise for each pixel\r
118         for(int yy=0; yy<bmpheight; yy++)\r
119         {\r
120                 for(int xx=0; xx<bmpwidth; xx++)\r
121                 {\r
122                         RGBApixel pixel=bmp.GetPixel(xx,yy);\r
123                         int tempred=pixel.Red+(rand()%21)-10;\r
124                         int tempgreen=pixel.Green+(rand()%21)-10;\r
125                         int tempblue=pixel.Blue+(rand()%21)-10;\r
126 \r
127                         tempred < 0 ? tempred=0 : false;\r
128                         tempred > 255 ? tempred=255 : false;\r
129                         tempgreen < 0 ? tempgreen=0 : false;\r
130                         tempgreen > 255 ? tempgreen=255 : false;\r
131                         tempblue < 0 ? tempblue=0 : false;\r
132                         tempblue > 255 ? tempblue=255 : false;\r
133 \r
134                         pixel.Red=tempred;\r
135                         pixel.Green=tempgreen;\r
136                         pixel.Blue=tempblue;\r
137 \r
138                         bmp.SetPixel(xx,yy,pixel);\r
139                 }\r
140         }\r
141 \r
142         bmp.WriteToFile(tempfilename.c_str());\r
143         ReadPuzzleData(tempfilename);\r
144         unlink(tempfilename.c_str());\r
145 }\r
146 \r
147 const std::string SimpleCaptcha::GenerateRandomString(const int len)\r
148 {\r
149         // no l,1 O,0 because they look too much alike\r
150         static std::string chars="abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ23456789";\r
151         std::string temp="";\r
152         for(int i=0; i<len; i++)\r
153         {\r
154                 temp+=chars[rand()%chars.size()];\r
155         }\r
156         return temp;\r
157 }\r
158 \r
159 const bool SimpleCaptcha::GetPuzzle(std::vector<unsigned char> &puzzle)\r
160 {\r
161         puzzle=m_puzzle;\r
162         return true;\r
163 }\r
164 \r
165 const bool SimpleCaptcha::GetSolution(std::vector<unsigned char> &solution)\r
166 {\r
167         solution=m_solution;\r
168         return true;\r
169 }\r
170 \r
171 void SimpleCaptcha::ReadPuzzleData(const std::string &filename)\r
172 {\r
173         long filelen;\r
174         FILE *infile=fopen(filename.c_str(),"rb");\r
175         if(infile)\r
176         {\r
177                 fseek(infile,0,SEEK_END);\r
178                 filelen=ftell(infile);\r
179                 fseek(infile,0,SEEK_SET);\r
180                 m_puzzle.resize(filelen);\r
181                 fread(&m_puzzle[0],1,filelen,infile);\r
182                 fclose(infile);\r
183         }\r
184 }\r