1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22
23 from __future__ import with_statement
24 import os
25 import sys
26 import time
27 import subprocess
28 import shutil
29 from entropy.services.skel import RemoteDatabase
30 from entropy.exceptions import *
31 from entropy.const import etpConst, etpUi, etpCache, const_setup_perms, const_set_chmod, const_setup_file
32 from entropy.output import brown, bold, blue
33 from entropy.i18n import _
34
36
37 SQL_TABLES = {
38 'entropy_base': """
39 CREATE TABLE `entropy_base` (
40 `idkey` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
41 `key` VARCHAR( 255 ) collate utf8_bin NOT NULL,
42 KEY `key` (`key`)
43 );
44 """,
45 'entropy_votes': """
46 CREATE TABLE `entropy_votes` (
47 `idvote` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
48 `idkey` INT UNSIGNED NOT NULL,
49 `userid` INT UNSIGNED NOT NULL,
50 `vdate` DATE NOT NULL,
51 `vote` TINYINT NOT NULL,
52 `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
53 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
54 );
55 """,
56 'entropy_user_scores': """
57 CREATE TABLE `entropy_user_scores` (
58 `userid` INT UNSIGNED NOT NULL PRIMARY KEY,
59 `score` INT UNSIGNED NOT NULL DEFAULT 0
60 );
61 """,
62 'entropy_downloads': """
63 CREATE TABLE `entropy_downloads` (
64 `iddownload` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
65 `idkey` INT UNSIGNED NOT NULL,
66 `ddate` DATE NOT NULL,
67 `count` INT UNSIGNED NULL DEFAULT '0',
68 KEY `idkey` (`idkey`,`ddate`),
69 KEY `idkey_2` (`idkey`),
70 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
71 );
72 """,
73 'entropy_downloads_data': """
74 CREATE TABLE `entropy_downloads_data` (
75 `iddownload` INT UNSIGNED NOT NULL,
76 `ip_address` VARCHAR(40) NULL DEFAULT '',
77 `entropy_ip_locations_id` INT UNSIGNED NULL DEFAULT 0,
78 FOREIGN KEY (`iddownload`) REFERENCES `entropy_downloads` (`iddownload`)
79 );
80 """,
81 'entropy_docs': """
82 CREATE TABLE `entropy_docs` (
83 `iddoc` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
84 `idkey` INT UNSIGNED NOT NULL,
85 `userid` INT UNSIGNED NOT NULL,
86 `username` VARCHAR( 255 ),
87 `iddoctype` TINYINT NOT NULL,
88 `ddata` TEXT NOT NULL,
89 `title` VARCHAR( 512 ),
90 `description` VARCHAR( 4000 ),
91 `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
92 KEY `idkey` (`idkey`),
93 KEY `userid` (`userid`),
94 KEY `idkey_2` (`idkey`,`userid`,`iddoctype`),
95 KEY `title` (`title`(333)),
96 KEY `description` (`description`(333)),
97 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
98 );
99 """,
100 'entropy_doctypes': """
101 CREATE TABLE `entropy_doctypes` (
102 `iddoctype` TINYINT NOT NULL PRIMARY KEY,
103 `description` TEXT NOT NULL
104 );
105 """,
106 'entropy_docs_keywords': """
107 CREATE TABLE `entropy_docs_keywords` (
108 `iddoc` INT UNSIGNED NOT NULL,
109 `keyword` VARCHAR( 100 ),
110 KEY `keyword` (`keyword`),
111 FOREIGN KEY (`iddoc`) REFERENCES `entropy_docs` (`iddoc`)
112 );
113 """,
114 'entropy_distribution_usage': """
115 CREATE TABLE `entropy_distribution_usage` (
116 `entropy_distribution_usage_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
117 `entropy_branches_id` INT NOT NULL,
118 `entropy_release_strings_id` INT NOT NULL,
119 `ts` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
120 `ip_address` VARCHAR( 15 ),
121 `entropy_ip_locations_id` INT UNSIGNED NULL DEFAULT 0,
122 `creation_date` DATETIME DEFAULT NULL,
123 `hits` INT UNSIGNED NULL DEFAULT 0,
124 FOREIGN KEY (`entropy_branches_id`) REFERENCES `entropy_branches` (`entropy_branches_id`),
125 FOREIGN KEY (`entropy_release_strings_id`) REFERENCES `entropy_release_strings` (`entropy_release_strings_id`),
126 KEY `ip_address` (`ip_address`),
127 KEY `entropy_ip_locations_id` (`entropy_ip_locations_id`)
128 );
129 """,
130 'entropy_hardware_usage': """
131 CREATE TABLE `entropy_hardware_usage` (
132 `entropy_hardware_usage_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
133 `entropy_distribution_usage_id` INT UNSIGNED NOT NULL,
134 `entropy_hardware_hash` VARCHAR ( 64 ),
135 FOREIGN KEY (`entropy_distribution_usage_id`) REFERENCES `entropy_distribution_usage` (`entropy_distribution_usage_id`)
136 );
137 """,
138
139
140
141
142
143
144
145
146 'entropy_branches': """
147 CREATE TABLE `entropy_branches` (
148 `entropy_branches_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
149 `entropy_branch` VARCHAR( 100 )
150 );
151 """,
152 'entropy_release_strings': """
153 CREATE TABLE `entropy_release_strings` (
154 `entropy_release_strings_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
155 `release_string` VARCHAR( 255 )
156 );
157 """,
158 'entropy_ip_locations': """
159 CREATE TABLE `entropy_ip_locations` (
160 `entropy_ip_locations_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
161 `ip_latitude` FLOAT( 8,5 ),
162 `ip_longitude` FLOAT( 8,5 ),
163 KEY `ip_locations_lat_lon` (`ip_latitude`,`ip_longitude`)
164 );
165 """,
166 }
167 VOTE_RANGE = etpConst['ugc_voterange']
168 VIRUS_CHECK_EXEC = '/usr/bin/clamscan'
169 VIRUS_CHECK_ARGS = []
170 gdata = None
171 YouTube = None
172 YouTubeService = None
173 entropy_docs_title_len = 512
174 entropy_docs_description_len = 4000
175 entropy_docs_keyword_len = 100
176 COMMENTS_SCORE_WEIGHT = 5
177 DOCS_SCORE_WEIGHT = 10
178 VOTES_SCORE_WEIGHT = 2
179 STATS_MAP = {
180 'installer': "installer",
181 }
182
183 '''
184 dependencies:
185 dev-python/gdata
186 '''
187 - def __init__(self, connection_data, store_path, store_url = ''):
188 import entropy.dump as dumpTools
189 import entropy.tools as entropyTools
190 from entropy.misc import EntropyGeoIP
191 self.EntropyGeoIP = EntropyGeoIP
192 self.entropyTools, self.dumpTools = entropyTools, dumpTools
193 self.store_url = store_url
194 self.FLOOD_INTERVAL = 30
195 self.DOC_TYPES = etpConst['ugc_doctypes'].copy()
196 self.UPLOADED_DOC_TYPES = [
197 self.DOC_TYPES['image'],
198 self.DOC_TYPES['generic_file']
199 ]
200 RemoteDatabase.__init__(self)
201 self.set_connection_data(connection_data)
202 self.connect()
203 self.initialize_tables()
204 self.initialize_doctypes()
205 self.setup_store_path(store_path)
206 from entropy.core import SystemSettings
207 self.__system_settings = SystemSettings()
208 self.system_name = self.__system_settings['system']['name']
209 from datetime import datetime
210 self.datetime = datetime
211 try:
212 import gdata
213 import gdata.youtube
214 import gdata.youtube.service
215 self.gdata = gdata
216 self.YouTube = gdata.youtube
217 self.YouTubeService = gdata.youtube.service
218 except ImportError:
219 pass
220
221 self.cached_results = {
222
223 'get_ugc_alldownloads': (self.get_ugc_alldownloads, [], {}, 86400),
224
225 'get_total_downloads_count': (self.get_total_downloads_count, [], {}, 7200),
226 }
227
229 return int(time.time())
230
232 for cache_item in self.cached_results:
233 fdata = self.cached_results.get(cache_item)
234 if fdata == None: return
235 func, args, kwargs, exp_time = fdata
236 key = self.get_cache_item_key(cache_item)
237 r = func(*args,**kwargs)
238 self.dumpTools.dumpobj(key, r)
239
241 return os.path.join(etpCache['ugc_srv_cache'],cache_item)
242
244 if not self.cached_results.get(cache_item): return None
245 key = self.get_cache_item_key(cache_item)
246 self.dumpTools.dumpobj(key, r)
247
249 geoip_dbpath = self.connection_data.get('geoip_dbpath','')
250 if os.path.isfile(geoip_dbpath) and os.access(geoip_dbpath,os.R_OK):
251 try:
252 geo = self.EntropyGeoIP(geoip_dbpath)
253 return geo.get_geoip_record_from_ip(ip_address)
254 except:
255 pass
256
257
259 fdata = self.cached_results.get(cache_item)
260 if fdata == None: return None
261 func, args, kwargs, exp_time = fdata
262
263 key = self.get_cache_item_key(cache_item)
264 cur_time = self.get_current_time()
265 cache_time = self.dumpTools.getobjmtime(key)
266 if (cache_time + exp_time) < cur_time:
267
268 return None
269 return self.dumpTools.loadobj(key)
270
272 path = os.path.realpath(path)
273 if not os.path.isabs(path):
274 raise PermissionDenied('PermissionDenied: %s' % (_("not a valid directory path"),))
275 if not os.path.isdir(path):
276 try:
277 os.makedirs(path)
278 except OSError, e:
279 raise PermissionDenied('PermissionDenied: %s' % (e,))
280 if etpConst['entropygid'] != None:
281 const_setup_perms(path,etpConst['entropygid'])
282 self.STORE_PATH = path
283
293
299
301 self.check_connection()
302 rows = self.execute_query('SELECT `iddoctype` FROM entropy_doctypes WHERE `iddoctype` = %s', (iddoctype,))
303 if rows:
304 return True
305 return False
306
308 self.check_connection()
309 rows = self.execute_query('SELECT `idkey` FROM entropy_base WHERE `key` = %s', (key,))
310 if rows:
311 return True
312 return False
313
315 self.check_connection()
316 rows = self.execute_query('SELECT `iddoc` FROM entropy_docs WHERE `iddoc` = %s', (iddoc,))
317 if rows:
318 return True
319 return False
320
325
332
340
347
354
361
363 entropy_ip_locations_id = 0
364 geo_data = self._get_geoip_data_from_ip_address(ip_addr)
365 if isinstance(geo_data,dict):
366 ip_lat = geo_data.get('latitude')
367 ip_long = geo_data.get('longitude')
368 if isinstance(ip_lat,float) and isinstance(ip_long,float):
369 ip_lat = round(ip_lat,5)
370 ip_long = round(ip_long,5)
371 entropy_ip_locations_id = self.get_entropy_ip_locations_id(ip_lat, ip_long)
372 if entropy_ip_locations_id == -1:
373 entropy_ip_locations_id = self.insert_entropy_ip_locations_id(ip_lat, ip_long)
374 return entropy_ip_locations_id
375
377 self.check_connection()
378 self.execute_query('UPDATE entropy_downloads SET `count` = `count`+1 WHERE `iddownload` = %s', (iddownload,))
379 if do_commit: self.commit()
380 return iddownload
381
383 entropy_ip_locations_id = self.handle_entropy_ip_locations_id(ip_addr)
384 mydata = [(x,ip_addr,entropy_ip_locations_id,) for x in iddownloads]
385 self.execute_many('INSERT INTO entropy_downloads_data VALUES (%s,%s,%s)', mydata)
386 if do_commit: self.commit()
387
389 mytime = time.time()
390 mydate = self.datetime.fromtimestamp(mytime)
391 mydate = self.datetime(mydate.year,mydate.month,mydate.day)
392 return mydate
393
395 mytime = time.time()
396 mydate = self.datetime.fromtimestamp(mytime)
397 mydate = self.datetime(mydate.year,mydate.month,mydate.day,mydate.hour,mydate.minute,mydate.second)
398 return mydate
399
401 self.check_connection()
402 idkey = self.handle_pkgkey(key)
403 self.execute_query('SELECT `iddownload` FROM entropy_downloads WHERE `idkey` = %s AND `ddate` = %s', (idkey,ddate,))
404 data = self.fetchone()
405 if data:
406 return data['iddownload']
407 return -1
408
410 self.check_connection()
411 self.execute_query('SELECT `idkey` FROM entropy_base WHERE `key` = %s', (key,))
412 data = self.fetchone()
413 if data:
414 return data['idkey']
415 return -1
416
418 self.check_connection()
419 self.execute_query('SELECT `iddoctype` FROM entropy_docs WHERE `iddoc` = %s', (iddoc,))
420 data = self.fetchone()
421 if data:
422 return data['iddoctype']
423 return -1
424
426 self.check_connection()
427 self.execute_query('SELECT `entropy_branches_id` FROM entropy_branches WHERE `entropy_branch` = %s', (branch,))
428 data = self.fetchone()
429 if data:
430 return data['entropy_branches_id']
431 return -1
432
434 self.check_connection()
435 self.execute_query('SELECT `entropy_release_strings_id` FROM entropy_release_strings WHERE `release_string` = %s', (release_string,))
436 data = self.fetchone()
437 if data:
438 return data['entropy_release_strings_id']
439 return -1
440
442 self.check_connection()
443 self.execute_query("""
444 SELECT `entropy_ip_locations_id` FROM
445 entropy_ip_locations WHERE
446 `ip_latitude` = %s AND `ip_longitude` = %s""", (ip_latitude,ip_longitude,))
447 data = self.fetchone()
448 if data:
449 return data['entropy_ip_locations_id']
450 return -1
451
457
470
472 self.execute_query('SELECT `keyword` FROM entropy_docs_keywords WHERE `iddoc` = %s order by `keyword`', (iddoc,))
473 return [x.get('keyword') for x in self.fetchall() if x.get('keyword')]
474
485
496
504
534
536 self.check_connection()
537 self.execute_query("""
538 SELECT avg(entropy_votes.`vote`) as avg_vote FROM entropy_votes,entropy_base WHERE
539 entropy_base.`key` = %s AND
540 entropy_base.idkey = entropy_votes.idkey""", (pkgkey,))
541 data = self.fetchone() or {}
542 avg_vote = data.get('avg_vote')
543 if not avg_vote:
544 return 0.0
545 return avg_vote
546
548
549
550 cache_item = 'get_ugc_allvotes'
551 cached = self.get_cached_result(cache_item)
552 if cached != None:
553 return cached
554
555 self.check_connection()
556 self.execute_query("""
557 SELECT entropy_base.`key` as `vkey`,avg(entropy_votes.vote) as `avg_vote` FROM
558 entropy_votes,entropy_base WHERE
559 entropy_votes.`idkey` = entropy_base.`idkey` GROUP BY entropy_base.`key`""")
560 vote_data = dict( ((x['vkey'], x['avg_vote'],) for x in self.fetchall()) )
561
562
563 self.cache_result(cache_item, vote_data)
564 return vote_data
565
567 self.check_connection()
568
569 self.execute_query("""
570 SELECT SQL_CACHE sum(entropy_downloads.`count`) as `tot_downloads` FROM
571 entropy_downloads,entropy_base WHERE entropy_base.key = %s AND
572 entropy_base.idkey = entropy_downloads.idkey""", (pkgkey,))
573
574 data = self.fetchone() or {}
575 downloads = data.get('tot_downloads')
576 if not downloads:
577 return 0
578 return downloads
579
581
582 cache_item = 'get_ugc_alldownloads'
583 cached = self.get_cached_result(cache_item)
584 if cached != None: return cached
585
586 self.check_connection()
587 self.execute_query("""
588 SELECT SQL_CACHE entropy_base.key as vkey, tot_downloads from entropy_base,
589 (SELECT idkey as idp1, sum(entropy_downloads.`count`) AS `tot_downloads` FROM
590 entropy_downloads GROUP BY entropy_downloads.`idkey`) as tmp where idkey = tmp.idp1;
591 """)
592 down_data = dict( ((x['vkey'], x['tot_downloads'],) for x in self.fetchall()) )
593
594
595 self.cache_result(cache_item, down_data)
596 return down_data
597
603
612
614 self.check_connection()
615 self.execute_query('SELECT count(`iddoc`) as comments FROM entropy_docs WHERE `iddoctype` != %s', (self.DOC_TYPES['comments'],))
616 data = self.fetchone() or {}
617 comments = data.get('comments')
618 if not comments:
619 return 0
620 return comments
621
623 self.check_connection()
624 self.execute_query('SELECT count(`idvote`) as votes FROM entropy_votes')
625 data = self.fetchone() or {}
626 votes = data.get('votes')
627 if not votes:
628 return 0
629 return votes
630
632
633
634 cache_item = 'get_total_downloads_count'
635 cached = self.get_cached_result(cache_item)
636 if cached != None: return cached
637
638 self.check_connection()
639 self.execute_query('SELECT SQL_CACHE sum(entropy_downloads.`count`) as downloads FROM entropy_downloads')
640 data = self.fetchone() or {}
641 downloads = data.get('downloads', 0)
642 if not downloads:
643 return 0
644 result = int(downloads)
645
646
647 self.cache_result(cache_item, result)
648 return result
649
651 self.check_connection()
652 self.execute_query('SET @row = 0')
653 self.execute_query("""
654 SELECT Row, col_a FROM (SELECT @row := @row + 1 AS Row, userid AS col_a FROM
655 entropy_user_scores ORDER BY score DESC) As derived1 WHERE col_a = %s""", (userid,))
656 data = self.fetchone() or {}
657 ranking = data.get('Row', 0)
658 if not ranking:
659 return 0
660 return ranking
661
663
664
665 cache_item = 'get_users_scored_count'
666 cached = self.get_cached_result(cache_item)
667 if cached != None:
668 return cached
669
670 self.check_connection()
671 self.execute_query('SELECT SQL_CACHE count(`userid`) as mycount FROM entropy_user_scores')
672 data = self.fetchone() or {}
673 count = data.get('mycount', 0)
674 if not count:
675 return 0
676
677
678 self.cache_result(cache_item, count)
679 return count
680
682 self.check_connection()
683 rows = self.execute_query('SELECT `userid` FROM entropy_user_scores WHERE `userid` = %s', (userid,))
684 if rows:
685 return True
686 return False
687
695
705
714
716 self.check_connection()
717 limit_string = ''
718 if count:
719 limit_string += ' LIMIT %s,%s' % (offset,count,)
720 self.execute_query('SELECT SQL_CALC_FOUND_ROWS *, userid, score FROM entropy_user_scores ORDER BY score DESC' + limit_string)
721 data = self.fetchall()
722
723 self.execute_query('SELECT FOUND_ROWS() as count')
724 rdata = self.fetchone() or {}
725 found_rows = rdata.get('count', 0)
726 if found_rows is None:
727 found_rows = 0
728
729 return found_rows, data
730
732 self.check_connection()
733 self.execute_query('SELECT avg(`vote`) as vote_avg FROM entropy_votes WHERE `userid` = %s', (userid,))
734 data = self.fetchone() or {}
735 vote_avg = data.get('vote_avg', 0.0)
736 if not vote_avg:
737 return 0.0
738 return round(float(vote_avg), 2)
739
741 self.check_connection()
742 self.execute_query("""
743 SELECT * FROM entropy_docs,entropy_base WHERE
744 entropy_docs.`userid` = %s AND
745 entropy_base.idkey = entropy_docs.idkey ORDER BY entropy_base.`key`""", (userid,))
746 return self.fetchall()
747
750
753
758
760 self.check_connection()
761 self.execute_query('SELECT * FROM entropy_docs WHERE `userid` = %s AND `iddoctype` '+doctype_sql_cmp+' %s', (userid,doctype,))
762 return self.fetchall()
763
765 self.check_connection()
766 self.execute_query('SELECT count(`iddoc`) as docs FROM entropy_docs WHERE `userid` = %s AND `iddoctype` '+doctype_sql_cmp+' %s', (userid,doctype,))
767 data = self.fetchone() or {}
768 docs = data.get('docs', 0)
769 if docs is None:
770 docs = 0
771 return docs
772
775
778
781
784
787
789 self.check_connection()
790 self.execute_query('SELECT count(`idvote`) as votes FROM entropy_votes WHERE `userid` = %s', (userid,))
791 data = self.fetchone() or {}
792 votes = data.get('votes', 0)
793 if votes is None:
794 votes = 0
795 return votes
796
810
819
820 - def search_pkgkey_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
821 self.check_connection()
822
823 if iddoctypes == None:
824 iddoctypes = [self.DOC_TYPES[x] for x in self.DOC_TYPES]
825 iddoctypes = "("+', '.join([str(self.DOC_TYPES[x]) for x in self.DOC_TYPES])+")"
826 myterm = "%"+pkgkey_string+"%"
827
828 search_params = [myterm,results_offset,results_limit]
829
830 order_by_string = ''
831 if order_by == "key":
832 order_by_string = 'ORDER BY entropy_base.`key`'
833 elif order_by == "username":
834 order_by_string = 'ORDER BY entropy_docs.`username`'
835 elif order_by == "vote":
836 order_by_string = 'ORDER BY avg_vote DESC'
837 elif order_by == "downloads":
838 order_by_string = 'ORDER BY tot_downloads DESC'
839
840 self.execute_query("""
841 SELECT SQL_CALC_FOUND_ROWS *, avg(entropy_votes.`vote`) as avg_vote,
842 sum(entropy_downloads.`count`) as `tot_downloads`,
843 entropy_user_scores.`score` as `score` FROM
844 entropy_docs,entropy_base,entropy_votes,entropy_downloads,entropy_user_scores WHERE
845 entropy_base.`key` LIKE %s AND
846 entropy_docs.`iddoctype` IN """+iddoctypes+""" AND
847 entropy_docs.`idkey` = entropy_base.`idkey` AND
848 entropy_votes.`idkey` = entropy_base.`idkey` AND
849 entropy_downloads.`idkey` = entropy_base.`idkey` AND
850 entropy_docs.`userid` = entropy_user_scores.`userid`
851 GROUP BY entropy_docs.`iddoc` """+order_by_string+""" LIMIT %s,%s""", search_params)
852
853 results = self.fetchall()
854 self.execute_query('SELECT FOUND_ROWS() as count')
855 data = self.fetchone() or {}
856 count = data.get('count', 0)
857 if count is None:
858 count = 0
859 return results, count
860
861 - def search_username_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
862 self.check_connection()
863
864 if iddoctypes == None:
865 iddoctypes = [self.DOC_TYPES[x] for x in self.DOC_TYPES]
866 iddoctypes = "("+', '.join([str(self.DOC_TYPES[x]) for x in self.DOC_TYPES])+")"
867 myterm = "%"+pkgkey_string+"%"
868
869 search_params = [myterm,results_offset,results_limit]
870
871 order_by_string = ''
872 if order_by == "key":
873 order_by_string = 'ORDER BY entropy_base.`key`'
874 elif order_by == "username":
875 order_by_string = 'ORDER BY entropy_docs.`username`'
876 elif order_by == "vote":
877 order_by_string = 'ORDER BY avg_vote DESC'
878 elif order_by == "downloads":
879 order_by_string = 'ORDER BY tot_downloads DESC'
880
881 self.execute_query("""
882 SELECT SQL_CALC_FOUND_ROWS *, avg(entropy_votes.`vote`) as avg_vote,
883 sum(entropy_downloads.`count`) as `tot_downloads`,
884 entropy_user_scores.`score` as `score` FROM
885 entropy_docs,entropy_base,entropy_votes,entropy_downloads,entropy_user_scores WHERE
886 entropy_docs.`username` LIKE %s AND entropy_docs.`iddoctype` IN """+iddoctypes+""" AND
887 entropy_docs.`idkey` = entropy_base.`idkey` AND
888 entropy_votes.`idkey` = entropy_base.`idkey` AND
889 entropy_downloads.`idkey` = entropy_base.`idkey` AND
890 entropy_docs.`userid` = entropy_user_scores.`userid`
891 GROUP BY entropy_docs.`iddoc` """+order_by_string+""" LIMIT %s,%s""", search_params)
892
893 results = self.fetchall()
894 self.execute_query('SELECT FOUND_ROWS() as count')
895 data = self.fetchone() or {}
896 count = data.get('count', 0)
897 if count is None:
898 count = 0
899 return results, count
900
901 - def search_content_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
902 self.check_connection()
903
904 if iddoctypes == None:
905 iddoctypes = [self.DOC_TYPES[x] for x in self.DOC_TYPES]
906 iddoctypes = "("+', '.join([str(self.DOC_TYPES[x]) for x in self.DOC_TYPES])+")"
907 myterm = "%"+pkgkey_string+"%"
908 search_params = [myterm,myterm,myterm,results_offset,results_limit]
909
910 order_by_string = ''
911 if order_by == "key":
912 order_by_string = 'ORDER BY entropy_base.`key`'
913 elif order_by == "username":
914 order_by_string = 'ORDER BY entropy_docs.`username`'
915 elif order_by == "vote":
916 order_by_string = 'ORDER BY avg_vote DESC'
917 elif order_by == "downloads":
918 order_by_string = 'ORDER BY tot_downloads DESC'
919
920 self.execute_query("""
921 SELECT SQL_CALC_FOUND_ROWS *, avg(entropy_votes.`vote`) as avg_vote,
922 sum(entropy_downloads.`count`) as `tot_downloads`,
923 entropy_user_scores.`score` as `score` FROM
924 entropy_docs,entropy_base,entropy_votes,entropy_downloads,entropy_user_scores WHERE
925 (entropy_docs.`title` LIKE %s OR entropy_docs.`description` LIKE %s OR entropy_docs.`ddata` LIKE %s) AND
926 entropy_docs.`iddoctype` IN """+iddoctypes+""" AND
927 entropy_docs.`idkey` = entropy_base.`idkey` AND
928 entropy_votes.`idkey` = entropy_base.`idkey` AND
929 entropy_downloads.`idkey` = entropy_base.`idkey` AND
930 entropy_docs.`userid` = entropy_user_scores.`userid`
931 GROUP BY entropy_docs.`iddoc` """+order_by_string+""" LIMIT %s,%s""", search_params)
932
933 results = self.fetchall()
934 self.execute_query('SELECT FOUND_ROWS() as count')
935 data = self.fetchone() or {}
936 count = data.get('count', 0)
937 if count is None:
938 count = 0
939 return results, count
940
941 - def search_keyword_items(self, keyword_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
942 self.check_connection()
943
944 if iddoctypes == None:
945 iddoctypes = [self.DOC_TYPES[x] for x in self.DOC_TYPES]
946 iddoctypes = "("+', '.join([str(self.DOC_TYPES[x]) for x in self.DOC_TYPES])+")"
947 myterm = "%"+keyword_string+"%"
948
949 search_params = [myterm,results_offset,results_limit]
950
951 order_by_string = ''
952 if order_by == "key":
953 order_by_string = 'ORDER BY entropy_base.`key`'
954 elif order_by == "username":
955 order_by_string = 'ORDER BY entropy_docs.`username`'
956 elif order_by == "vote":
957 order_by_string = 'ORDER BY avg_vote DESC'
958 elif order_by == "downloads":
959 order_by_string = 'ORDER BY tot_downloads DESC'
960
961 self.execute_query("""
962 SELECT SQL_CALC_FOUND_ROWS *, avg(entropy_votes.`vote`) as avg_vote,
963 sum(entropy_downloads.`count`) as `tot_downloads`,
964 entropy_user_scores.`score` as `score` FROM
965 entropy_docs,entropy_base,entropy_docs_keywords,entropy_votes,entropy_downloads,entropy_user_scores WHERE
966 entropy_docs_keywords.`keyword` LIKE %s AND
967 entropy_docs.`iddoctype` IN """+iddoctypes+""" AND
968 entropy_docs.`idkey` = entropy_base.`idkey` AND
969 entropy_docs_keywords.`iddoc` = entropy_docs.`iddoc` AND
970 entropy_votes.`idkey` = entropy_base.`idkey` AND
971 entropy_downloads.`idkey` = entropy_base.`idkey` AND
972 entropy_docs.`userid` = entropy_user_scores.`userid`
973 GROUP BY entropy_docs.`iddoc` """+order_by_string+""" LIMIT %s,%s""", search_params)
974
975 results = self.fetchall()
976 self.execute_query('SELECT FOUND_ROWS() as count')
977 data = self.fetchone() or {}
978 count = data.get('count', 0)
979 if count is None:
980 count = 0
981 return results, count
982
983 - def search_iddoc_item(self, iddoc_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
984 self.check_connection()
985
986 if iddoctypes == None:
987 iddoctypes = [self.DOC_TYPES[x] for x in self.DOC_TYPES]
988 iddoctypes = "("+', '.join([str(self.DOC_TYPES[x]) for x in self.DOC_TYPES])+")"
989 try:
990 myterm = int(iddoc_string)
991 except ValueError:
992 return [], 0
993
994 search_params = [myterm,results_offset,results_limit]
995
996 order_by_string = ''
997 if order_by == "key":
998 order_by_string = 'ORDER BY entropy_base.`key`'
999 elif order_by == "username":
1000 order_by_string = 'ORDER BY entropy_docs.`username`'
1001 elif order_by == "vote":
1002 order_by_string = 'ORDER BY avg_vote DESC'
1003 elif order_by == "downloads":
1004 order_by_string = 'ORDER BY tot_downloads DESC'
1005
1006 self.execute_query("""
1007 SELECT SQL_CALC_FOUND_ROWS *, avg(entropy_votes.`vote`) as avg_vote,
1008 sum(entropy_downloads.`count`) as `tot_downloads`,
1009 entropy_user_scores.`score` as `score` FROM
1010 entropy_docs,entropy_base,entropy_votes,entropy_downloads,entropy_user_scores WHERE
1011 entropy_docs.`iddoc` = %s AND
1012 entropy_docs.`iddoctype` IN """+iddoctypes+""" AND
1013 entropy_docs.`idkey` = entropy_base.`idkey` AND
1014 entropy_votes.`idkey` = entropy_base.`idkey` AND
1015 entropy_downloads.`idkey` = entropy_base.`idkey` AND
1016 entropy_docs.`userid` = entropy_user_scores.`userid`
1017 GROUP BY entropy_docs.`iddoc` """+order_by_string+""" LIMIT %s,%s""", search_params)
1018
1019 results = self.fetchall()
1020 self.execute_query('SELECT FOUND_ROWS() as count')
1021 data = self.fetchone() or {}
1022 count = data.get('count', 0)
1023 if count is None:
1024 count = 0
1025 return results, count
1026
1032
1034 self.check_connection()
1035 self.execute_query('SELECT max(`ts`) as ts FROM entropy_docs WHERE `userid` = %s', (userid,))
1036 data = self.fetchone()
1037 if not data:
1038 return False
1039 elif not data.has_key('ts'):
1040 return False
1041 elif data['ts'] == None:
1042 return False
1043 delta = self.datetime.fromtimestamp(time.time()) - data['ts']
1044 if (delta.days == 0) and (delta.seconds <= self.FLOOD_INTERVAL):
1045 return True
1046 return False
1047
1048 - def insert_generic_doc(self, idkey, userid, username, doc_type, data, title, description, keywords, do_commit = False):
1049 self.check_connection()
1050
1051 title = title[:self.entropy_docs_title_len]
1052 description = description[:self.entropy_docs_description_len]
1053
1054
1055 flood_risk = self.insert_flood_control_check(userid)
1056 if flood_risk:
1057 return 'flooding detected'
1058
1059 self.execute_query('INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)',(
1060 None,
1061 idkey,
1062 userid,
1063 username,
1064 doc_type,
1065 data,
1066 title,
1067 description,
1068 None,
1069 )
1070 )
1071 if do_commit:
1072 self.commit()
1073 iddoc = self.lastrowid()
1074 self.insert_keywords(iddoc, keywords)
1075 self.update_user_score(userid)
1076 return iddoc
1077
1079 keywords = keywords.split(",")
1080 clean_keys = []
1081 for key in keywords:
1082 try:
1083 key = key.strip().split()[0]
1084 except IndexError:
1085 continue
1086 if not key: continue
1087 if not key.isalnum(): continue
1088 key = key[:self.entropy_docs_keyword_len]
1089 if key in clean_keys: continue
1090 clean_keys.append(key)
1091
1092 if not clean_keys:
1093 return
1094
1095 mydata = []
1096 for key in clean_keys:
1097 mydata.append((iddoc, key,))
1098
1099 self.execute_many('INSERT INTO entropy_docs_keywords VALUES (%s,%s)', mydata)
1100
1102 self.execute_query('DELETE FROM entropy_docs_keywords WHERE `iddoc` = %s',(iddoc,))
1103
1114
1132
1145
1146
1147 - def do_vote(self, pkgkey, userid, vote, do_commit = False):
1148 self.check_connection()
1149 idkey = self.handle_pkgkey(pkgkey)
1150 vote = int(vote)
1151 if vote not in self.VOTE_RANGE:
1152 vote = 3
1153 mydate = self.get_date()
1154 if self.has_user_already_voted(pkgkey, userid):
1155 return False
1156 self.execute_query('INSERT INTO entropy_votes VALUES (%s,%s,%s,%s,%s,%s)',(
1157 None,
1158 idkey,
1159 userid,
1160 mydate,
1161 vote,
1162 None,
1163 )
1164 )
1165 if do_commit:
1166 self.commit()
1167 self.update_user_score(userid)
1168 return True
1169
1171 self.check_connection()
1172 idkey = self.handle_pkgkey(pkgkey)
1173 self.execute_query('SELECT `idvote` FROM entropy_votes WHERE `idkey` = %s AND `userid` = %s', (idkey,userid,))
1174 data = self.fetchone()
1175 if data:
1176 return True
1177 return False
1178
1179
1180 - def do_downloads(self, pkgkeys, ip_addr = None, do_commit = False):
1181 self.check_connection()
1182 mydate = self.get_date()
1183 iddownloads = set()
1184 for pkgkey in pkgkeys:
1185 iddownload = self.get_iddownload(pkgkey, mydate)
1186 if iddownload == -1:
1187 iddownload = self.insert_download(pkgkey, mydate, count = 1)
1188 else:
1189 self.update_download(iddownload)
1190 if (iddownload > 0) and isinstance(ip_addr,basestring):
1191 iddownloads.add(iddownload)
1192
1193 if iddownloads:
1194 self.store_download_data(iddownloads, ip_addr)
1195 if do_commit:
1196 self.commit()
1197 return True
1198
1199 - def do_download_stats(self, branch, release_string, hw_hash, pkgkeys,
1200 ip_addr, do_commit = False):
1201
1202 self.check_connection()
1203 branch_id = self.get_entropy_branches_id(branch)
1204 if branch_id == -1:
1205 branch_id = self.insert_entropy_branch(branch)
1206
1207 rel_strings_id = self.get_entropy_release_strings_id(release_string)
1208 if rel_strings_id == -1:
1209 rel_strings_id = self.insert_entropy_release_string(release_string)
1210
1211 self.do_downloads(pkgkeys, ip_addr = ip_addr)
1212
1213 entropy_distribution_usage_id = self.is_user_ip_available_in_entropy_distribution_usage(ip_addr)
1214
1215 hits = 1
1216 if self.STATS_MAP['installer'] in pkgkeys:
1217 hits = 0
1218 if entropy_distribution_usage_id == -1:
1219 entropy_ip_locations_id = self.handle_entropy_ip_locations_id(ip_addr)
1220 self.execute_query('INSERT INTO entropy_distribution_usage VALUES (%s,%s,%s,%s,%s,%s,%s,%s)',(
1221 None,
1222 branch_id,
1223 rel_strings_id,
1224 None,
1225 ip_addr,
1226 entropy_ip_locations_id,
1227 self.get_datetime(),
1228 hits,
1229 )
1230 )
1231 entropy_distribution_usage_id = self.lastrowid()
1232 else:
1233 self.execute_query("""
1234 UPDATE entropy_distribution_usage SET `entropy_branches_id` = %s,
1235 `entropy_release_strings_id` = %s,
1236 `hits` = `hits`+%s
1237 WHERE `entropy_distribution_usage_id` = %s
1238 """,(
1239 branch_id,
1240 rel_strings_id,
1241 hits,
1242 entropy_distribution_usage_id,
1243 )
1244 )
1245
1246
1247 if hw_hash and not \
1248 self.is_entropy_hardware_usage_stats_available(entropy_distribution_usage_id):
1249
1250 self.do_entropy_hardware_usage_stats(entropy_distribution_usage_id,
1251 hw_hash)
1252
1253 if do_commit: self.commit()
1254 return True
1255
1257
1258 self.execute_query('INSERT INTO entropy_hardware_usage VALUES (%s,%s,%s)', (
1259 None,
1260 entropy_distribution_usage_id,
1261 hw_hash,
1262 )
1263 )
1264
1266 self.check_connection()
1267 self.execute_query('SELECT entropy_hardware_usage_id FROM entropy_hardware_usage WHERE `entropy_distribution_usage_id` = %s',(entropy_distribution_usage_id,))
1268 data = self.fetchone()
1269 if data:
1270 return True
1271 return False
1272
1274 self.check_connection()
1275 self.execute_query('SELECT entropy_distribution_usage_id FROM entropy_distribution_usage WHERE `ip_address` = %s',(ip_address,))
1276 data = self.fetchone() or {}
1277 myid = data.get('entropy_distribution_usage_id')
1278 if myid is None:
1279 return -1
1280 return myid
1281
1282 - def insert_document(self, pkgkey, userid, username, text, title,
1283 description, keywords, doc_type = None, do_commit = False):
1284 self.check_connection()
1285 idkey = self.handle_pkgkey(pkgkey)
1286 if doc_type == None: doc_type = self.DOC_TYPES['bbcode_doc']
1287 iddoc = self.insert_generic_doc(idkey, userid, username, doc_type,
1288 text, title, description, keywords)
1289 if isinstance(iddoc, basestring):
1290 return False, iddoc
1291 if do_commit:
1292 self.commit()
1293 return True, iddoc
1294
1295 - def edit_document(self, iddoc, new_document, new_title, new_keywords, do_commit = False):
1314
1327
1329
1330 if not os.access(filepath,os.R_OK):
1331 return False,None
1332
1333 args = [self.VIRUS_CHECK_EXEC]
1334 args += self.VIRUS_CHECK_ARGS
1335 args += [filepath]
1336 f = open("/dev/null","w")
1337 p = subprocess.Popen(args, stdout = f, stderr = f)
1338 rc = p.wait()
1339 f.close()
1340 if rc == 1:
1341 return True, None
1342 return False, None
1343
1344 - def insert_generic_file(self, pkgkey, userid, username, file_path,
1345 file_name, doc_type, title, description, keywords):
1346 self.check_connection()
1347 file_path = os.path.realpath(file_path)
1348
1349
1350 virus_found, virus_type = self.scan_for_viruses(file_path)
1351 if virus_found:
1352 os.remove(file_path)
1353 return False, None
1354
1355
1356 flood_risk = self.insert_flood_control_check(userid)
1357 if flood_risk: return False, 'flooding detected'
1358
1359
1360 if doc_type == self.DOC_TYPES['image']:
1361 valid = False
1362 if os.path.isfile(file_path) and os.access(file_path,os.R_OK):
1363 valid = self.entropyTools.is_supported_image_file(file_path)
1364 if not valid:
1365 return False, 'not a valid image'
1366
1367 dest_path = os.path.join(self.STORE_PATH,file_name)
1368
1369
1370 dest_dir = os.path.dirname(dest_path)
1371 if not os.path.isdir(dest_dir):
1372 try:
1373 os.makedirs(dest_dir)
1374 except OSError, e:
1375 raise PermissionDenied('PermissionDenied: %s' % (e,))
1376 if etpConst['entropygid'] != None:
1377 const_setup_perms(dest_dir,etpConst['entropygid'])
1378
1379 orig_dest_path = dest_path
1380 dcount = 0
1381 while os.path.isfile(dest_path):
1382 dcount += 1
1383 dest_path_name = "%s_%s" % (dcount,os.path.basename(orig_dest_path),)
1384 dest_path = os.path.join(os.path.dirname(orig_dest_path),dest_path_name)
1385
1386 if os.path.dirname(file_path) != dest_dir:
1387 try:
1388 os.rename(file_path, dest_path)
1389 except OSError:
1390
1391 shutil.move(file_path, dest_path)
1392 if etpConst['entropygid'] != None:
1393 try:
1394 const_setup_file(dest_path, etpConst['entropygid'], 0664)
1395 except OSError:
1396 pass
1397
1398 try:
1399 const_set_chmod(dest_path,0664)
1400 except OSError:
1401 pass
1402
1403 title = title[:self.entropy_docs_title_len]
1404 description = description[:self.entropy_docs_description_len]
1405
1406
1407 idkey = self.handle_pkgkey(pkgkey)
1408 self.execute_query('INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)',(
1409 None,
1410 idkey,
1411 userid,
1412 username,
1413 doc_type,
1414 file_name,
1415 title,
1416 description,
1417 None,
1418 )
1419 )
1420 iddoc = self.lastrowid()
1421 self.insert_keywords(iddoc, keywords)
1422 store_url = os.path.basename(dest_path)
1423 if self.store_url:
1424 store_url = os.path.join(self.store_url,store_url)
1425 self.update_user_score(userid)
1426 return True, (iddoc, store_url)
1427
1428 - def insert_image(self, pkgkey, userid, username, image_path, file_name,
1429 title, description, keywords):
1430 return self.insert_generic_file(pkgkey, userid, username, image_path,
1431 file_name, self.DOC_TYPES['image'], title, description, keywords)
1432
1433 - def insert_file(self, pkgkey, userid, username, file_path, file_name, title,
1434 description, keywords):
1435 return self.insert_generic_file(pkgkey, userid, username, file_path,
1436 file_name, self.DOC_TYPES['generic_file'], title, description,
1437 keywords)
1438
1441
1444
1446 self.check_connection()
1447
1448 userid = self.get_iddoc_userid(iddoc)
1449 self.execute_query('SELECT `ddata` FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1450 iddoc,
1451 doc_type,
1452 )
1453 )
1454 data = self.fetchone() or {}
1455 mypath = data.get('ddata')
1456 if not isinstance(mypath, basestring) and (mypath is not None):
1457 mypath = mypath.tostring()
1458 if mypath is not None:
1459 mypath = os.path.join(self.STORE_PATH,mypath)
1460 if os.path.isfile(mypath) and os.access(mypath,os.W_OK):
1461 os.remove(mypath)
1462
1463 self.remove_keywords(iddoc)
1464 self.execute_query('DELETE FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1465 iddoc,
1466 doc_type,
1467 )
1468 )
1469 if userid:
1470 self.update_user_score(userid)
1471 return True, (iddoc, None)
1472
1473 - def insert_youtube_video(self, pkgkey, userid, username, video_path, file_name, title, description, keywords):
1474 self.check_connection()
1475 if not self.gdata:
1476 return False, None
1477
1478 idkey = self.handle_pkgkey(pkgkey)
1479 video_path = os.path.realpath(video_path)
1480 if not (os.access(video_path,os.R_OK) and os.path.isfile(video_path)):
1481 return False
1482 virus_found, virus_type = self.scan_for_viruses(video_path)
1483 if virus_found:
1484 os.remove(video_path)
1485 return False, None
1486
1487 new_video_path = video_path
1488 if isinstance(file_name,basestring):
1489
1490 new_video_path = os.path.join(os.path.dirname(video_path),os.path.basename(file_name))
1491 scount = 0
1492 while os.path.lexists(new_video_path):
1493 scount += 1
1494 bpath = "%s.%s" % (unicode(scount),os.path.basename(file_name),)
1495 new_video_path = os.path.join(os.path.dirname(video_path),bpath)
1496 shutil.move(video_path,new_video_path)
1497
1498 yt_service = self.get_youtube_service()
1499 if yt_service == None:
1500 return False, None
1501
1502 mykeywords = ', '.join([x.strip().strip(',') for x in \
1503 keywords.split() + ["sabayon"] if (x.strip() and x.strip(",") and \
1504 (len(x.strip()) > 4))])
1505 gd_keywords = self.gdata.media.Keywords(text = mykeywords)
1506
1507 mydescription = "%s: %s" % (pkgkey,description,)
1508 mytitle = "%s: %s" % (self.system_name,title,)
1509 my_media_group = self.gdata.media.Group(
1510 title = self.gdata.media.Title(text = mytitle),
1511 description = self.gdata.media.Description(
1512 description_type = 'plain',
1513 text = mydescription
1514 ),
1515 keywords = gd_keywords,
1516 category = self.gdata.media.Category(
1517 text = 'Tech',
1518 scheme = 'http://gdata.youtube.com/schemas/2007/categories.cat',
1519 label = 'Tech'
1520 ),
1521 player = None
1522 )
1523 video_entry = self.gdata.youtube.YouTubeVideoEntry(media = my_media_group)
1524 new_entry = yt_service.InsertVideoEntry(video_entry, new_video_path)
1525 if not isinstance(new_entry, self.gdata.youtube.YouTubeVideoEntry):
1526 return False, None
1527 video_url = new_entry.GetSwfUrl()
1528 video_id = os.path.basename(video_url)
1529
1530 iddoc = self.insert_generic_doc(idkey, userid, username,
1531 self.DOC_TYPES['youtube_video'], video_id, title, description,
1532 keywords)
1533 if isinstance(iddoc,basestring):
1534 return False, (iddoc, None,)
1535 return True, (iddoc, video_id,)
1536
1556
1557 self.execute_query('SELECT `ddata` FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1558 iddoc,
1559 self.DOC_TYPES['youtube_video'],
1560 )
1561 )
1562 data = self.fetchone()
1563 if data is None:
1564 do_remove()
1565 return False, None
1566 elif not data.has_key('ddata'):
1567 do_remove()
1568 return False, None
1569
1570 video_id = data.get('ddata')
1571 try:
1572 video_entry = yt_service.GetYouTubeVideoEntry(video_id = video_id)
1573 deleted = yt_service.DeleteVideoEntry(video_entry)
1574 except:
1575 deleted = True
1576
1577 if deleted:
1578 do_remove()
1579 if userid: self.update_user_score(userid)
1580 return deleted, (iddoc, video_id,)
1581
1583 self.check_connection()
1584 if not self.gdata:
1585 return None
1586 keywords = ['google_email', 'google_password']
1587 for keyword in keywords:
1588 if not self.connection_data.has_key(keyword):
1589 return None
1590
1591 srv = self.YouTubeService.YouTubeService()
1592 srv.email = self.connection_data['google_email']
1593 srv.password = self.connection_data['google_password']
1594 if self.connection_data.has_key('google_developer_key'):
1595 srv.developer_key = self.connection_data['google_developer_key']
1596 if self.connection_data.has_key('google_client_id'):
1597 srv.client_id = self.connection_data['google_client_id']
1598 srv.source = 'Entropy'
1599 srv.ProgrammaticLogin()
1600 return srv
1601
1603
1604 import socket
1605 import entropy.dump as dumpTools
1606 import entropy.tools as entropyTools
1607 import zlib
1608 import select
1609 - def __init__(self, OutputInterface, ClientCommandsClass, quiet = False, show_progress = True, output_header = '', ssl = False, socket_timeout = 25):
1610
1611
1612 if not hasattr(OutputInterface,'updateProgress'):
1613 mytxt = _("OutputInterface does not have an updateProgress method")
1614 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
1615 elif not callable(OutputInterface.updateProgress):
1616 mytxt = _("OutputInterface does not have an updateProgress method")
1617 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
1618
1619 from entropy.client.services.ugc.commands import Base
1620 if not issubclass(ClientCommandsClass, (Base,)):
1621 mytxt = _("A valid entropy.client.services.ugc.commands.Base interface is needed")
1622 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (ClientCommandsClass,mytxt,))
1623
1624 self.ssl_mod = None
1625 self.setup_ssl(ssl)
1626
1627 self.answers = etpConst['socket_service']['answers']
1628 self.Output = OutputInterface
1629 self.sock_conn = None
1630 self.real_sock_conn = None
1631 self.hostname = None
1632 self.hostport = None
1633 self.buffered_data = ''
1634 self.buffer_length = None
1635 self.quiet = quiet
1636 self.show_progress = show_progress
1637 self.output_header = output_header
1638 self.CmdInterface = ClientCommandsClass(self.Output, self)
1639 self.CmdInterface.output_header = self.output_header
1640 self.socket_timeout = socket_timeout
1641 self.socket.setdefaulttimeout(self.socket_timeout)
1642
1643
1645
1646 self.SSL = {}
1647 self.SSL_exceptions = {
1648 'WantReadError': None,
1649 'WantWriteError': None,
1650 'WantX509LookupError': None,
1651 'ZeroReturnError': None,
1652 'Error': None,
1653 'SysCallError': None
1654 }
1655 self.ssl = ssl
1656 self.pyopenssl = True
1657 self.context = None
1658
1659 '''
1660 self.server_cert = server_cert
1661 self.server_ca_cert = server_ca_cert
1662 self.ssl_pkey = None
1663 self.ssl_cert = None
1664 self.ssl_CN = 'Entropy Repository Service Client'
1665 self.ssl_digest = 'md5'
1666 self.ssl_serial = 1
1667 self.ssl_not_before = 0
1668 self.ssl_not_after = 60*60*24*1 # 1 day
1669 '''
1670
1671 if self.ssl:
1672
1673 if "--nopyopenssl" in sys.argv:
1674 self.pyopenssl = False
1675 else:
1676 try:
1677 from OpenSSL import SSL, crypto
1678 except ImportError:
1679 self.pyopenssl = False
1680
1681
1682 try:
1683 import ssl as ssl_mod
1684 self.ssl_mod = ssl_mod
1685 except ImportError:
1686 pass
1687
1688 '''
1689 if not (self.server_cert and self.server_ca_cert):
1690 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),)
1691 if not (os.path.isfile(self.server_cert) and \
1692 os.access(self.server_cert,os.R_OK) and \
1693 os.path.isfile(self.server_ca_cert) and \
1694 os.access(self.server_ca_cert,os.R_OK)) and self.pyopenssl:
1695 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),self.server_cert,))
1696 '''
1697
1698 if self.pyopenssl:
1699
1700 self.SSL_exceptions['WantReadError'] = SSL.WantReadError
1701 self.SSL_exceptions['WantWriteError'] = SSL.WantWriteError
1702 self.SSL_exceptions['WantX509LookupError'] = SSL.WantX509LookupError
1703 self.SSL_exceptions['ZeroReturnError'] = SSL.ZeroReturnError
1704 self.SSL_exceptions['Error'] = SSL.Error
1705 self.SSL_exceptions['SysCallError'] = SSL.SysCallError
1706 self.SSL['m'] = SSL
1707 self.SSL['crypto'] = crypto
1708
1709
1710 self.context = self.SSL['m'].Context(self.SSL['m'].SSLv23_METHOD)
1711
1712
1713
1714 '''
1715 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1716 self.context.use_privatekey(self.ssl_pkey)
1717 self.context.use_certificate_file(self.server_cert)
1718 self.context.load_verify_locations(self.server_ca_cert)
1719 self.context.load_client_ca(self.server_cert)
1720 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1721 self.ssl_cert = self.create_ssl_certificate(self.ssl_pkey)
1722 self.context.use_privatekey(self.ssl_pkey)
1723 self.context.use_certificate(self.ssl_cert)
1724 self.context.load_client_ca(self.server_cert)
1725 '''
1726
1727 else:
1728 self.ssl = False
1729 self.pyopenssl = False
1730
1731
1733 if not self.pyopenssl:
1734 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1735
1736 '''
1737 # this function should do the authentication checking to see that
1738 # the client is who they say they are.
1739 def verify_ssl_cb(self, conn, cert, errnum, depth, ok):
1740 self.check_pyopenssl()
1741 #print 'Got certificate: %s' % cert.get_subject()
1742 #print repr(ok),repr(cert),repr(errnum),repr(depth)
1743 return ok
1744
1745
1746 def create_ssl_key_pair(self, keytype, bits):
1747 if not self.pyopenssl:
1748 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1749 pkey = self.SSL['crypto'].PKey()
1750 pkey.generate_key(keytype, bits)
1751 return pkey
1752
1753 def create_ssl_certificate(self, pkey):
1754 self.check_pyopenssl()
1755 myreq = self.create_ssl_certificate_request(pkey, CN = self.ssl_CN)
1756 cert = self.SSL['crypto'].X509()
1757 cert.set_serial_number(self.ssl_serial)
1758 cert.gmtime_adj_notBefore(self.ssl_not_before)
1759 cert.gmtime_adj_notAfter(self.ssl_not_after)
1760 cert.set_issuer(myreq.get_subject())
1761 cert.set_subject(myreq.get_subject())
1762 cert.set_pubkey(myreq.get_pubkey())
1763 cert.sign(pkey, self.ssl_digest)
1764 return cert
1765
1766 def create_ssl_certificate_request(self, pkey, **name):
1767 self.check_pyopenssl()
1768 req = self.SSL['crypto'].X509Req()
1769 subj = req.get_subject()
1770 for (key,value) in name.items():
1771 setattr(subj, key, value)
1772 req.set_pubkey(pkey)
1773 req.sign(pkey, self.ssl_digest)
1774
1775 return req
1776 '''
1777
1779
1780 if gzipped:
1781 data = self.zlib.decompress(data)
1782 obj = self.dumpTools.unserialize_string(data)
1783
1784 return obj
1785
1787 return str(len(data))+self.answers['eos']+data
1788
1790 self.check_socket_connection()
1791 if hasattr(self.sock_conn,'settimeout'):
1792 self.sock_conn.settimeout(self.socket_timeout)
1793 data = self.append_eos(data)
1794 try:
1795
1796 encode_done = False
1797 mydata = data[:]
1798 while 1:
1799 try:
1800 if self.ssl and not self.pyopenssl:
1801 sent = self.sock_conn.write(mydata)
1802 else:
1803 sent = self.sock_conn.send(mydata)
1804 if sent == len(mydata):
1805 break
1806 mydata = mydata[sent:]
1807 except (self.SSL_exceptions['WantWriteError'],
1808 self.SSL_exceptions['WantReadError'],):
1809 time.sleep(0.2)
1810 continue
1811 except UnicodeEncodeError, e:
1812 if encode_done:
1813 raise
1814 mydata = mydata.encode('utf-8')
1815 encode_done = True
1816 continue
1817
1818 except self.SSL_exceptions['Error'], e:
1819 self.disconnect()
1820 raise SSLError('SSLError: %s' % (e,))
1821 except self.socket.sslerror, e:
1822 self.disconnect()
1823 raise SSLError('SSL Socket error: %s' % (e,))
1824 except:
1825 self.disconnect()
1826 raise
1827
1829 self.check_socket_connection()
1830 try:
1831 self.transmit("%s end" % (session_id,))
1832
1833 data = self.receive()
1834 except self.socket.error, e:
1835 if etpUi['debug']:
1836 self.entropyTools.print_traceback()
1837 import pdb
1838 pdb.set_trace()
1839 if e[0] == 32:
1840 return None
1841 raise
1842 except SSLError:
1843 raise
1844 return data
1845
1852
1854 self.check_socket_connection()
1855 self.socket.setdefaulttimeout(self.socket_timeout)
1856 self.transmit('alive %s' % (session,))
1857 data = self.receive()
1858 if data == self.answers['ok']:
1859 return True
1860 return False
1861
1863
1864 self.check_socket_connection()
1865 if hasattr(self.sock_conn,'settimeout'):
1866 self.sock_conn.settimeout(self.socket_timeout)
1867 self.ssl_prepending = True
1868
1869 def do_receive():
1870 data = ''
1871 if self.ssl and not self.pyopenssl:
1872 data = self.sock_conn.read(1024)
1873 elif self.ssl:
1874 if self.ssl_prepending:
1875 data = self.sock_conn.recv(1024)
1876 self.ssl_prepending = False
1877 while self.sock_conn.pending():
1878 data += self.sock_conn.recv(1024)
1879 else:
1880 data = self.sock_conn.recv(1024)
1881 return data
1882
1883 myeos = self.answers['eos']
1884 ssl_error_loop_count = 0
1885 while 1:
1886
1887 try:
1888
1889 data = do_receive()
1890 if self.buffer_length == None:
1891 self.buffered_data = ''
1892 if (data == '') or (data == self.answers['cl']):
1893
1894
1895 if not self.quiet:
1896 mytxt = _("command not supported. receive aborted")
1897 self.Output.updateProgress(
1898 "[%s:%s] %s" % (
1899 brown(self.hostname),
1900 bold(str(self.hostport)),
1901 blue(mytxt),
1902 ),
1903 importance = 1,
1904 type = "warning",
1905 header = self.output_header
1906 )
1907 return None
1908 elif len(data) < len(myeos):
1909 if not self.quiet:
1910 mytxt = _("malformed EOS. receive aborted")
1911 self.Output.updateProgress(
1912 "[%s:%s] %s" % (
1913 brown(self.hostname),
1914 bold(str(self.hostport)),
1915 blue(mytxt),
1916 ),
1917 importance = 1,
1918 type = "warning",
1919 header = self.output_header
1920 )
1921 if etpUi['debug']:
1922 self.entropyTools.print_traceback()
1923 import pdb
1924 pdb.set_trace()
1925 return None
1926 mystrlen = data.split(myeos)[0]
1927 self.buffer_length = int(mystrlen)
1928 data = data[len(mystrlen)+1:]
1929 self.buffer_length -= len(data)
1930 self.buffered_data = data
1931 else:
1932 self.buffer_length -= len(data)
1933 self.buffered_data += data
1934
1935 while self.buffer_length > 0:
1936 x = do_receive()
1937 if self.ssl and self.pyopenssl and not x:
1938 self.ssl_prepending = True
1939 self.buffer_length -= len(x)
1940 self.buffered_data += x
1941 self.buffer_length = None
1942 break
1943
1944 except ValueError, e:
1945 if not self.quiet:
1946 mytxt = _("malformed data. receive aborted")
1947 self.Output.updateProgress(
1948 "[%s:%s] %s: %s" % (
1949 brown(self.hostname),
1950 bold(str(self.hostport)),
1951 blue(mytxt),
1952 e,
1953 ),
1954 importance = 1,
1955 type = "warning",
1956 header = self.output_header
1957 )
1958 return None
1959 except self.socket.timeout, e:
1960 if not self.quiet:
1961 mytxt = _("connection timed out while receiving data")
1962 self.Output.updateProgress(
1963 "[%s:%s] %s: %s" % (
1964 brown(self.hostname),
1965 bold(str(self.hostport)),
1966 blue(mytxt),
1967 e,
1968 ),
1969 importance = 1,
1970 type = "warning",
1971 header = self.output_header
1972 )
1973 return None
1974 except self.socket.error, e:
1975 if not self.quiet:
1976 mytxt = _("connection error while receiving data")
1977 self.Output.updateProgress(
1978 "[%s:%s] %s: %s" % (
1979 brown(self.hostname),
1980 bold(str(self.hostport)),
1981 blue(mytxt),
1982 e,
1983 ),
1984 importance = 1,
1985 type = "warning",
1986 header = self.output_header
1987 )
1988 return None
1989 except (self.SSL_exceptions['WantReadError'],self.SSL_exceptions['WantX509LookupError'],), e:
1990 ssl_error_loop_count += 1
1991 if ssl_error_loop_count > 3000000:
1992 if not self.quiet:
1993 mytxt = _("too many WantReadError error while receiving data")
1994 self.Output.updateProgress(
1995 "[%s:%s] %s: %s" % (
1996 brown(self.hostname),
1997 bold(str(self.hostport)),
1998 blue(mytxt),
1999 e,
2000 ),
2001 importance = 1,
2002 type = "warning",
2003 header = self.output_header
2004 )
2005 return None
2006 continue
2007 except self.SSL_exceptions['ZeroReturnError']:
2008 break
2009 except self.SSL_exceptions['SysCallError'], e:
2010 if not self.quiet:
2011 mytxt = _("syscall error while receiving data")
2012 self.Output.updateProgress(
2013 "[%s:%s] %s: %s" % (
2014 brown(self.hostname),
2015 bold(str(self.hostport)),
2016 blue(mytxt),
2017 e,
2018 ),
2019 importance = 1,
2020 type = "warning",
2021 header = self.output_header
2022 )
2023 return None
2024
2025 return self.buffered_data
2026
2028 if not self.quiet:
2029 mytxt = _("Reconnecting to socket")
2030 self.Output.updateProgress(
2031 "[%s:%s] %s" % (
2032 brown(unicode(self.hostname)),
2033 bold(unicode(self.hostport)),
2034 blue(mytxt),
2035 ),
2036 importance = 1,
2037 type = "info",
2038 header = self.output_header
2039 )
2040 self.connect(self.hostname,self.hostport)
2041
2043 if not self.sock_conn:
2044 raise ConnectionError("ConnectionError: %s" % (_("Not connected to host"),))
2045
2047
2048 if self.ssl:
2049 self.real_sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2050 if hasattr(self.real_sock_conn,'settimeout'):
2051 self.real_sock_conn.settimeout(self.socket_timeout)
2052 if self.pyopenssl:
2053 self.sock_conn = self.SSL['m'].Connection(self.context, self.real_sock_conn)
2054 else:
2055 self.sock_conn = self.real_sock_conn
2056 else:
2057 self.sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2058 if hasattr(self.sock_conn,'settimeout'):
2059 self.sock_conn.settimeout(self.socket_timeout)
2060 self.real_sock_conn = self.sock_conn
2061
2062 self.hostname = host
2063 self.hostport = port
2064
2065 try:
2066 self.sock_conn.connect((self.hostname, self.hostport))
2067 if self.ssl and not self.pyopenssl:
2068 if self.ssl_mod is not None:
2069 self.sock_conn = self.ssl_mod.wrap_socket(self.real_sock_conn)
2070 else:
2071 self.sock_conn = self.socket.ssl(self.real_sock_conn)
2072
2073 if not self.quiet:
2074 mytxt = _("Warning: you are using an emergency SSL interface, SSL certificate can't be verified. Please install dev-python/pyopenssl")
2075 self.Output.updateProgress(
2076 "[%s:%s] %s" % (
2077 brown(str(self.hostname)),
2078 bold(str(self.hostport)),
2079 blue(mytxt),
2080 ),
2081 importance = 1,
2082 type = "warning",
2083 header = self.output_header
2084 )
2085 mytxt = _("Service issuer")
2086 self.Output.updateProgress(
2087 "[%s:%s] %s: %s" % (
2088 brown(str(self.hostname)),
2089 bold(str(self.hostport)),
2090 blue(mytxt),
2091 self.sock_conn.issuer()
2092 ),
2093 importance = 1,
2094 type = "warning",
2095 header = self.output_header
2096 )
2097 except self.socket.error, e:
2098 if e[0] == 111:
2099 mytxt = "%s: %s, %s: %s" % (_("Cannot connect to"),host,_("on port"),port,)
2100 raise ConnectionError("ConnectionError: %s" % (mytxt,))
2101 else:
2102 raise
2103
2104 if not self.quiet:
2105 mytxt = _("Successfully connected to host")
2106 self.Output.updateProgress(
2107 "[%s:%s] %s" % (
2108 brown(self.hostname),
2109 bold(str(self.hostport)),
2110 blue(mytxt),
2111 ),
2112 importance = 1,
2113 type = "info",
2114 header = self.output_header
2115 )
2116
2118 if not self.real_sock_conn:
2119 return True
2120 if self.ssl and self.pyopenssl:
2121 self.sock_conn.shutdown()
2122 self.sock_conn.close()
2123 elif self.ssl and not self.pyopenssl:
2124 try:
2125 self.real_sock_conn.shutdown(self.socket.SHUT_RDWR)
2126 except self.socket.error:
2127 pass
2128 del self.sock_conn
2129 self.sock_conn = None
2130 try:
2131 self.real_sock_conn.close()
2132 except self.socket.error:
2133 pass
2134 if not self.quiet:
2135 mytxt = _("Successfully disconnected from host")
2136 self.Output.updateProgress(
2137 "[%s:%s] %s" % (
2138 brown(self.hostname),
2139 bold(str(self.hostport)),
2140 blue(mytxt),
2141 ),
2142 importance = 1,
2143 type = "info",
2144 header = self.output_header
2145 )
2146 self.real_sock_conn = None
2147
2148
2149
2150