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