source: trunk/lib/Epoll/DB/Poll/Bdata.pm @ 439

Last change on this file since 439 was 325, checked in by nanardon, 14 years ago
  • fix decrypt() when poll is uncrypted
  • Property svn:keywords set to Id Rev
File size: 4.4 KB
Line 
1package Epoll::DB::Poll::Bdata;
2
3# $Id$
4
5use strict;
6use warnings;
7use base 'Epoll::DB::common';
8use Epoll::DB::Poll;
9use YAML ();
10use Crypt::CBC;
11use Crypt::DES_EDE3; # Called from CBC
12
13=head1 NAME
14
15Epoll::Model::Vote - Catalyst Model
16
17=head1 DESCRIPTION
18
19Catalyst Model.
20
21=cut
22
23sub new {
24    my ($class, $dbstring, $poll) = @_;
25   
26    bless {
27        poll => $poll,
28        dbstring => $dbstring,
29        db => Epoll::DB::common::_newdb($dbstring),
30        data => {},
31    }, $class;
32}
33
34sub voteid { $_[0]->poll->voteid }
35
36sub poll {
37    my ($self) = @_;
38    $self->{poll};
39}
40
41sub uid {
42    my ($self) = @_;
43    $self->{data}{id} ||= Epoll::DB::common::gen_uid();
44}
45
46sub xmlout {
47    my ($self) = @_;
48    $self->uid;
49    YAML::Dump($self->{data});
50}
51
52sub xmlin {
53    my ($self, $data) = @_;
54    $self->{data} = YAML::Load($data);
55}
56
57sub _store_clear {
58    my ($self) = @_;
59    my $addb = $self->db->prepare_cached(
60        q{
61        insert into ballot (id, poll, invalid) values (?,?,?)
62        }
63    );
64
65    my $needvalid = 'f';
66    my %items = ();
67    foreach(keys %{$self->{data}{content} || {}}) {
68        if ($self->poll->find_choice_key($_)) {
69            $items{$_} = 't';
70        } else {
71            $items{$_} = 'f';
72            $needvalid = undef;
73        }
74    }
75
76    $addb->execute($self->uid, $self->voteid, $needvalid) or do {
77        $self->rollback;
78        return;
79    };
80
81    my $addbc = $self->db->prepare_cached(
82        q{
83        insert into ballot_item (id, value, fromlist, weight) values (?,?,?,?)
84        }
85    );
86    foreach (keys %{$self->{data}{content} || {}}) {
87        $_ or next;
88        $addbc->execute($self->uid, $_, $items{$_}, $self->{data}{content}{$_}) or do {
89            $self->rollback;
90            return;
91        };
92    }
93
94    1;
95}
96
97sub _store_crypted {
98    my ($self) = @_;
99   
100    my $addenc = $self->db->prepare_cached(
101        q{insert into ballot_enc (id, data, enckey, poll) values (?,?,?,?)}
102    );
103    my $uid = Epoll::DB::common::gen_uid();
104   
105    if (my $pollkey = $self->poll->public_key) {
106        my $symkey = map{ chr(rand(256)) } (1 .. 24);
107        my $cipher = new Crypt::CBC($symkey, 'DES_EDE3');
108        my $encryptedballot = $cipher->encrypt_hex(
109            $self->xmlout()
110        );
111        my $encsymkey = $self->poll->rsa->encrypt (
112            Message    => $symkey,
113            Key        => $self->poll->public_key,
114            Armour     => 1,
115        ) || die $self->poll->rsa->errstr();
116        $addenc->execute($uid, $encryptedballot, $encsymkey, $self->voteid);
117    } else {
118        $addenc->execute($uid, $self->xmlout(), undef, $self->voteid);
119    }
120}
121
122sub _load_crypted {
123    my ($self, $ballotid, $privkey) = @_;
124    my $sth = $self->db->prepare_cached(
125        q{select * from ballot_enc where id = ? for update}
126    );
127    $sth->execute($ballotid);
128    my $ballot = $sth->fetchrow_hashref;
129    $sth->finish;
130    if ($ballot->{enckey}) {
131        $self->_load_crypted_data($ballot->{data}, $ballot->{enckey}, $privkey);
132    } else {
133        return $ballot->{data}
134    }
135}
136
137sub _load_crypted_data {
138    my ($self, $data, $encsymkey, $privkey) = @_;
139    if ($encsymkey) {
140        my $symkey = $self->poll->rsa->decrypt (
141            Cyphertext => $encsymkey,
142            Key        => $privkey,
143            Armour     => 1,
144        ) || die $self->poll->rsa->errstr();
145        my $cipher = new Crypt::CBC($symkey, 'DES_EDE3');
146        return $self->xmlin($cipher->decrypt_hex($data));
147    } else {
148        return $self->xmlin($data);
149    }
150}
151
152sub decrypt_data {
153    my ($self, $ballotid, $data, $encsymkey, $privkey) = @_;
154    if ($self->_load_crypted_data($data, $encsymkey, $privkey) &&
155        $self->_store_clear &&
156        $self->_set_decrypted($ballotid)) {
157        $self->commit;
158        return;
159    } else {
160        $self->rollback;
161        return 1;
162    }
163}
164
165sub _set_decrypted {
166    my ($self, $ballotid) = @_;
167    my $upd = $self->db->prepare_cached(q{update ballot_enc set decrypted = true where id = ?});
168    $upd->execute($ballotid)
169}
170
171sub decrypt {
172    my ($self, $ballotid, $privkey) = @_;
173    $self->_load_crypted($ballotid, $privkey);
174    $self->_store_clear or return;
175    if ($self->_set_decrypted($ballotid)) {
176        $self->commit;
177        return;
178    } else {
179        $self->rollback;
180        return 1;
181    }
182}
183
184
185=head1 AUTHOR
186
187Thauvin Olivier
188
189=head1 LICENSE
190
191This library is free software, you can redistribute it and/or modify
192it under the same terms as Perl itself or CeCILL.
193
194=cut
195
1961;
Note: See TracBrowser for help on using the repository browser.