source: pwntcha/trunk/src/linuxfr.c @ 438

Last change on this file since 438 was 430, checked in by Sam Hocevar, 16 years ago
  • support for -s / --share
  • Property svn:keywords set to Id
File size: 4.4 KB
Line 
1/*
2 * linuxfr.c: decode linuxfr.org captchas
3 * $Id: linuxfr.c 430 2005-01-06 00:51:07Z sam $
4 *
5 * Copyright: (c) 2005 Sam Hocevar <sam@zoy.org>
6 *   This program is free software; you can redistribute it and/or
7 *   modify it under the terms of the Do What The Fuck You Want To
8 *   Public License as published by Banlu Kemiyatorn. See
9 *   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <limits.h>
16
17#include "config.h"
18#include "common.h"
19
20#define FONTNAME "font_linuxfr.png"
21static struct image *font = NULL;
22
23/* Main function */
24char *decode_linuxfr(struct image *img)
25{
26    char all[] = "abcdefghijklmnopqrstuvwxyz"
27                 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
28                 "0123456789";
29    char *result;
30    struct image *tmp;
31    int x, y, r, g, b, i, j, c;
32    int *stats = malloc(img->height * sizeof(int));
33
34    if(!font)
35    {
36        char fontname[BUFSIZ];
37        sprintf(fontname, "%s/%s", share, FONTNAME);
38        font = image_load(fontname);
39        if(!font)
40        {
41            fprintf(stderr, "cannot load font %s\n", fontname);
42            exit(-1);
43        }
44    }
45
46    /* linuxfr captchas have 7 characters */
47    result = malloc(8 * sizeof(char));
48    memset(result, '\0', 8);
49
50    tmp = filter_equalize(img, 150);
51
52    for(y = 0; y < img->height; y++)
53    {
54        int count = 0;
55        for(x = 0; x < img->width; x++)
56        {
57            getpixel(tmp, x, y, &r, &g, &b);
58            if(r == 0)
59                count++;
60        }
61        stats[y] = count;
62    }
63
64    /* Find 7 consecutive lines that have at least 14 pixels; they're
65     * baseline candidates */
66    for(y = 0; y < img->height - 11; y++)
67    {
68        int ycan = 1;
69        for(j = 3; j < 10; j++)
70        {
71            if(stats[y + j] < 14)
72            {
73                ycan = 0;
74                y = y + j - 3;
75                break;
76            }
77        }
78        if(!ycan)
79            continue;
80
81        /* Find 7 consecutive cells that have at least 2 pixels on
82         * each line; they're base column candidates */
83        for(x = 0; x < img->width - 9 * 7 + 1; x++)
84        {
85            int goodx = 1;
86            for(c = 0; c < 7 && goodx; c++)
87            {
88                for(j = 3; j < 10; j++)
89                {
90                    int count = 0;
91                    for(i = 0; i < 8; i++)
92                    {
93                        getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b);
94                        if(r == 0)
95                        {
96                            count++;
97                            if(count == 2)
98                                break;
99                        }
100                    }
101                    if(count < 2)
102                    {
103                        goodx = 0;
104                        break;
105                    }
106                }
107            }
108            if(!goodx)
109                continue;
110
111            /* Now we have an (x,y) candidate - try to fit 7 characters */
112            for(c = 0; c < 7 && goodx; c++)
113            {
114                int r2, g2, b2, ch;
115                int minerror = INT_MAX;
116                for(ch = 0; ch < 62; ch++)
117                {
118                    int error = 0, goodch = 1;
119                    for(j = 0; j < 12 && goodch; j++)
120                        for(i = 0; i < 8; i++)
121                        {
122                            getpixel(tmp, x + c * 9 + i, y + j, &r, &g, &b);
123                            getpixel(font, ch * 9 + i, j, &r2, &g2, &b2);
124                            /* Only die if font is black and image is white */
125                            if(r > r2)
126                            {
127                                goodch = 0;
128                                break;
129                            }
130                            else if(r < r2)
131                                error++;
132                        }
133                    if(goodch && error < minerror)
134                    {
135                        minerror = error;
136                        result[c] = all[ch];
137                        result[c+1] = '\0';
138                    }
139                }
140                if(minerror == INT_MAX)
141                    goodx = 0;
142            }
143            /* Wow, that was a good guess! Exit this loop */
144            if(goodx)
145                break;
146        }
147    }
148
149    image_free(tmp);
150    free(stats);
151
152    if(strlen(result) != 7)
153    {
154        free(result);
155        return NULL;
156    }
157
158    return result;
159}
160
Note: See TracBrowser for help on using the repository browser.