1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Services UGC Base Interface}.
10
11 """
12
13 from __future__ import with_statement
14 import os
15 import sys
16 import select
17 import time
18 import subprocess
19 import shutil
20 from entropy.services.skel import RemoteDatabase
21 from entropy.exceptions import *
22 from entropy.const import etpConst, etpUi, etpCache, const_setup_perms, \
23 const_set_chmod, const_setup_file
24 from entropy.output import brown, bold, blue
25 from entropy.i18n import _
26
28
29 SQL_TABLES = {
30 'entropy_base': """
31 CREATE TABLE `entropy_base` (
32 `idkey` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
33 `key` VARCHAR( 255 ) collate utf8_bin NOT NULL,
34 KEY `key` (`key`)
35 );
36 """,
37 'entropy_votes': """
38 CREATE TABLE `entropy_votes` (
39 `idvote` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
40 `idkey` INT UNSIGNED NOT NULL,
41 `userid` INT UNSIGNED NOT NULL,
42 `vdate` DATE NOT NULL,
43 `vote` TINYINT NOT NULL,
44 `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
45 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
46 );
47 """,
48 'entropy_user_scores': """
49 CREATE TABLE `entropy_user_scores` (
50 `userid` INT UNSIGNED NOT NULL PRIMARY KEY,
51 `score` INT UNSIGNED NOT NULL DEFAULT 0
52 );
53 """,
54 'entropy_downloads': """
55 CREATE TABLE `entropy_downloads` (
56 `iddownload` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
57 `idkey` INT UNSIGNED NOT NULL,
58 `ddate` DATE NOT NULL,
59 `count` INT UNSIGNED NULL DEFAULT '0',
60 KEY `idkey` (`idkey`,`ddate`),
61 KEY `idkey_2` (`idkey`),
62 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
63 );
64 """,
65 'entropy_downloads_data': """
66 CREATE TABLE `entropy_downloads_data` (
67 `iddownload` INT UNSIGNED NOT NULL,
68 `ip_address` VARCHAR(40) NULL DEFAULT '',
69 `entropy_ip_locations_id` INT UNSIGNED NULL DEFAULT 0,
70 FOREIGN KEY (`iddownload`) REFERENCES `entropy_downloads` (`iddownload`)
71 );
72 """,
73 'entropy_docs': """
74 CREATE TABLE `entropy_docs` (
75 `iddoc` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
76 `idkey` INT UNSIGNED NOT NULL,
77 `userid` INT UNSIGNED NOT NULL,
78 `username` VARCHAR( 255 ),
79 `iddoctype` TINYINT NOT NULL,
80 `ddata` TEXT NOT NULL,
81 `title` VARCHAR( 512 ),
82 `description` VARCHAR( 4000 ),
83 `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
84 KEY `idkey` (`idkey`),
85 KEY `userid` (`userid`),
86 KEY `idkey_2` (`idkey`,`userid`,`iddoctype`),
87 KEY `title` (`title`(333)),
88 KEY `description` (`description`(333)),
89 FOREIGN KEY (`idkey`) REFERENCES `entropy_base` (`idkey`)
90 );
91 """,
92 'entropy_doctypes': """
93 CREATE TABLE `entropy_doctypes` (
94 `iddoctype` TINYINT NOT NULL PRIMARY KEY,
95 `description` TEXT NOT NULL
96 );
97 """,
98 'entropy_docs_keywords': """
99 CREATE TABLE `entropy_docs_keywords` (
100 `iddoc` INT UNSIGNED NOT NULL,
101 `keyword` VARCHAR( 100 ),
102 KEY `keyword` (`keyword`),
103 FOREIGN KEY (`iddoc`) REFERENCES `entropy_docs` (`iddoc`)
104 );
105 """,
106 'entropy_distribution_usage': """
107 CREATE TABLE `entropy_distribution_usage` (
108 `entropy_distribution_usage_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
109 `entropy_branches_id` INT NOT NULL,
110 `entropy_release_strings_id` INT NOT NULL,
111 `ts` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
112 `ip_address` VARCHAR( 15 ),
113 `entropy_ip_locations_id` INT UNSIGNED NULL DEFAULT 0,
114 `creation_date` DATETIME DEFAULT NULL,
115 `hits` INT UNSIGNED NULL DEFAULT 0,
116 FOREIGN KEY (`entropy_branches_id`) REFERENCES `entropy_branches` (`entropy_branches_id`),
117 FOREIGN KEY (`entropy_release_strings_id`) REFERENCES `entropy_release_strings` (`entropy_release_strings_id`),
118 KEY `ip_address` (`ip_address`),
119 KEY `entropy_ip_locations_id` (`entropy_ip_locations_id`)
120 );
121 """,
122 'entropy_hardware_usage': """
123 CREATE TABLE `entropy_hardware_usage` (
124 `entropy_hardware_usage_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
125 `entropy_distribution_usage_id` INT UNSIGNED NOT NULL,
126 `entropy_hardware_hash` VARCHAR ( 64 ),
127 FOREIGN KEY (`entropy_distribution_usage_id`) REFERENCES `entropy_distribution_usage` (`entropy_distribution_usage_id`)
128 );
129 """,
130
131
132
133
134
135
136
137
138 'entropy_branches': """
139 CREATE TABLE `entropy_branches` (
140 `entropy_branches_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
141 `entropy_branch` VARCHAR( 100 )
142 );
143 """,
144 'entropy_release_strings': """
145 CREATE TABLE `entropy_release_strings` (
146 `entropy_release_strings_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
147 `release_string` VARCHAR( 255 )
148 );
149 """,
150 'entropy_ip_locations': """
151 CREATE TABLE `entropy_ip_locations` (
152 `entropy_ip_locations_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
153 `ip_latitude` FLOAT( 8,5 ),
154 `ip_longitude` FLOAT( 8,5 ),
155 KEY `ip_locations_lat_lon` (`ip_latitude`,`ip_longitude`)
156 );
157 """,
158 }
159 VOTE_RANGE = etpConst['ugc_voterange']
160 VIRUS_CHECK_EXEC = '/usr/bin/clamscan'
161 VIRUS_CHECK_ARGS = []
162 gdata = None
163 YouTube = None
164 YouTubeService = None
165 entropy_docs_title_len = 512
166 entropy_docs_description_len = 4000
167 entropy_docs_keyword_len = 100
168 COMMENTS_SCORE_WEIGHT = 5
169 DOCS_SCORE_WEIGHT = 10
170 VOTES_SCORE_WEIGHT = 2
171 STATS_MAP = {
172 'installer': "installer",
173 }
174
175 '''
176 dependencies:
177 dev-python/gdata
178 '''
179 - def __init__(self, connection_data, store_path, store_url = ''):
180 import entropy.dump as dumpTools
181 import entropy.tools as entropyTools
182 from entropy.misc import EntropyGeoIP
183 self.EntropyGeoIP = EntropyGeoIP
184 self.entropyTools, self.dumpTools = entropyTools, dumpTools
185 self.store_url = store_url
186 self.FLOOD_INTERVAL = 30
187 self.DOC_TYPES = etpConst['ugc_doctypes'].copy()
188 self.UPLOADED_DOC_TYPES = [
189 self.DOC_TYPES['image'],
190 self.DOC_TYPES['generic_file']
191 ]
192 RemoteDatabase.__init__(self)
193 self.set_connection_data(connection_data)
194 self.connect()
195 self.initialize_tables()
196 self.initialize_doctypes()
197 self.setup_store_path(store_path)
198 from entropy.core.settings.base import SystemSettings
199 self.__system_settings = SystemSettings()
200 self.system_name = self.__system_settings['system']['name']
201 from datetime import datetime
202 self.datetime = datetime
203 try:
204 import gdata
205 import gdata.youtube
206 import gdata.youtube.service
207 self.gdata = gdata
208 self.YouTube = gdata.youtube
209 self.YouTubeService = gdata.youtube.service
210 except ImportError:
211 pass
212
213 self.cached_results = {
214
215 'get_ugc_alldownloads': (self.get_ugc_alldownloads, [], {}, 86400),
216
217 'get_total_downloads_count': (self.get_total_downloads_count, [], {}, 7200),
218 }
219
221 return int(time.time())
222
224 for cache_item in self.cached_results:
225 fdata = self.cached_results.get(cache_item)
226 if fdata == None: return
227 func, args, kwargs, exp_time = fdata
228 key = self.get_cache_item_key(cache_item)
229 r = func(*args,**kwargs)
230 self.dumpTools.dumpobj(key, r)
231
233 return os.path.join(etpCache['ugc_srv_cache'],cache_item)
234
236 if not self.cached_results.get(cache_item): return None
237 key = self.get_cache_item_key(cache_item)
238 self.dumpTools.dumpobj(key, r)
239
241 geoip_dbpath = self.connection_data.get('geoip_dbpath','')
242 if os.path.isfile(geoip_dbpath) and os.access(geoip_dbpath,os.R_OK):
243 try:
244 geo = self.EntropyGeoIP(geoip_dbpath)
245 return geo.get_geoip_record_from_ip(ip_address)
246 except:
247 pass
248
249
251 fdata = self.cached_results.get(cache_item)
252 if fdata == None: return None
253 func, args, kwargs, exp_time = fdata
254
255 key = self.get_cache_item_key(cache_item)
256 cur_time = self.get_current_time()
257 cache_time = self.dumpTools.getobjmtime(key)
258 if (cache_time + exp_time) < cur_time:
259
260 return None
261 return self.dumpTools.loadobj(key)
262
264 path = os.path.realpath(path)
265 if not os.path.isabs(path):
266 raise PermissionDenied('PermissionDenied: %s' % (_("not a valid directory path"),))
267 if not os.path.isdir(path):
268 try:
269 os.makedirs(path)
270 except OSError, e:
271 raise PermissionDenied('PermissionDenied: %s' % (e,))
272 if etpConst['entropygid'] != None:
273 const_setup_perms(path,etpConst['entropygid'])
274 self.STORE_PATH = path
275
285
291
293 self.check_connection()
294 rows = self.execute_query('SELECT `iddoctype` FROM entropy_doctypes WHERE `iddoctype` = %s', (iddoctype,))
295 if rows:
296 return True
297 return False
298
300 self.check_connection()
301 rows = self.execute_query('SELECT `idkey` FROM entropy_base WHERE `key` = %s', (key,))
302 if rows:
303 return True
304 return False
305
307 self.check_connection()
308 rows = self.execute_query('SELECT `iddoc` FROM entropy_docs WHERE `iddoc` = %s', (iddoc,))
309 if rows:
310 return True
311 return False
312
317
324
332
339
346
353
355 entropy_ip_locations_id = 0
356 geo_data = self._get_geoip_data_from_ip_address(ip_addr)
357 if isinstance(geo_data,dict):
358 ip_lat = geo_data.get('latitude')
359 ip_long = geo_data.get('longitude')
360 if isinstance(ip_lat,float) and isinstance(ip_long,float):
361 ip_lat = round(ip_lat,5)
362 ip_long = round(ip_long,5)
363 entropy_ip_locations_id = self.get_entropy_ip_locations_id(ip_lat, ip_long)
364 if entropy_ip_locations_id == -1:
365 entropy_ip_locations_id = self.insert_entropy_ip_locations_id(ip_lat, ip_long)
366 return entropy_ip_locations_id
367
369 self.check_connection()
370 self.execute_query('UPDATE entropy_downloads SET `count` = `count`+1 WHERE `iddownload` = %s', (iddownload,))
371 if do_commit: self.commit()
372 return iddownload
373
375 entropy_ip_locations_id = self.handle_entropy_ip_locations_id(ip_addr)
376 mydata = [(x,ip_addr,entropy_ip_locations_id,) for x in iddownloads]
377 self.execute_many('INSERT INTO entropy_downloads_data VALUES (%s,%s,%s)', mydata)
378 if do_commit: self.commit()
379
381 mytime = time.time()
382 mydate = self.datetime.fromtimestamp(mytime)
383 mydate = self.datetime(mydate.year,mydate.month,mydate.day)
384 return mydate
385
387 mytime = time.time()
388 mydate = self.datetime.fromtimestamp(mytime)
389 mydate = self.datetime(mydate.year,mydate.month,mydate.day,mydate.hour,mydate.minute,mydate.second)
390 return mydate
391
393 self.check_connection()
394 idkey = self.handle_pkgkey(key)
395 self.execute_query('SELECT `iddownload` FROM entropy_downloads WHERE `idkey` = %s AND `ddate` = %s', (idkey,ddate,))
396 data = self.fetchone()
397 if data:
398 return data['iddownload']
399 return -1
400
402 self.check_connection()
403 self.execute_query('SELECT `idkey` FROM entropy_base WHERE `key` = %s', (key,))
404 data = self.fetchone()
405 if data:
406 return data['idkey']
407 return -1
408
410 self.check_connection()
411 self.execute_query('SELECT `iddoctype` FROM entropy_docs WHERE `iddoc` = %s', (iddoc,))
412 data = self.fetchone()
413 if data:
414 return data['iddoctype']
415 return -1
416
418 self.check_connection()
419 self.execute_query('SELECT `entropy_branches_id` FROM entropy_branches WHERE `entropy_branch` = %s', (branch,))
420 data = self.fetchone()
421 if data:
422 return data['entropy_branches_id']
423 return -1
424
426 self.check_connection()
427 self.execute_query('SELECT `entropy_release_strings_id` FROM entropy_release_strings WHERE `release_string` = %s', (release_string,))
428 data = self.fetchone()
429 if data:
430 return data['entropy_release_strings_id']
431 return -1
432
434 self.check_connection()
435 self.execute_query("""
436 SELECT `entropy_ip_locations_id` FROM
437 entropy_ip_locations WHERE
438 `ip_latitude` = %s AND `ip_longitude` = %s""", (ip_latitude,ip_longitude,))
439 data = self.fetchone()
440 if data:
441 return data['entropy_ip_locations_id']
442 return -1
443
449
462
464 self.execute_query('SELECT `keyword` FROM entropy_docs_keywords WHERE `iddoc` = %s order by `keyword`', (iddoc,))
465 return [x.get('keyword') for x in self.fetchall() if x.get('keyword')]
466
476
487
495
525
527 self.check_connection()
528 self.execute_query("""
529 SELECT avg(entropy_votes.`vote`) as avg_vote FROM entropy_votes,entropy_base WHERE
530 entropy_base.`key` = %s AND
531 entropy_base.idkey = entropy_votes.idkey""", (pkgkey,))
532 data = self.fetchone() or {}
533 avg_vote = data.get('avg_vote')
534 if not avg_vote:
535 return 0.0
536 return avg_vote
537
539
540
541 cache_item = 'get_ugc_allvotes'
542 cached = self.get_cached_result(cache_item)
543 if cached != None:
544 return cached
545
546 self.check_connection()
547 self.execute_query("""
548 SELECT entropy_base.`key` as `vkey`,avg(entropy_votes.vote) as `avg_vote` FROM
549 entropy_votes,entropy_base WHERE
550 entropy_votes.`idkey` = entropy_base.`idkey` GROUP BY entropy_base.`key`""")
551 vote_data = dict( ((x['vkey'], x['avg_vote'],) for x in self.fetchall()) )
552
553
554 self.cache_result(cache_item, vote_data)
555 return vote_data
556
558 self.check_connection()
559
560 self.execute_query("""
561 SELECT SQL_CACHE sum(entropy_downloads.`count`) as `tot_downloads` FROM
562 entropy_downloads,entropy_base WHERE entropy_base.key = %s AND
563 entropy_base.idkey = entropy_downloads.idkey""", (pkgkey,))
564
565 data = self.fetchone() or {}
566 downloads = data.get('tot_downloads')
567 if not downloads:
568 return 0
569 return downloads
570
572
573 cache_item = 'get_ugc_alldownloads'
574 cached = self.get_cached_result(cache_item)
575 if cached != None: return cached
576
577 self.check_connection()
578 self.execute_query("""
579 SELECT SQL_CACHE entropy_base.key as vkey, tot_downloads from entropy_base,
580 (SELECT idkey as idp1, sum(entropy_downloads.`count`) AS `tot_downloads` FROM
581 entropy_downloads GROUP BY entropy_downloads.`idkey`) as tmp where idkey = tmp.idp1;
582 """)
583 down_data = dict( ((x['vkey'], x['tot_downloads'],) for x in self.fetchall()) )
584
585
586 self.cache_result(cache_item, down_data)
587 return down_data
588
594
603
605 self.check_connection()
606 self.execute_query('SELECT count(`iddoc`) as comments FROM entropy_docs WHERE `iddoctype` != %s', (self.DOC_TYPES['comments'],))
607 data = self.fetchone() or {}
608 comments = data.get('comments')
609 if not comments:
610 return 0
611 return comments
612
614 self.check_connection()
615 self.execute_query('SELECT count(`idvote`) as votes FROM entropy_votes')
616 data = self.fetchone() or {}
617 votes = data.get('votes')
618 if not votes:
619 return 0
620 return votes
621
623
624
625 cache_item = 'get_total_downloads_count'
626 cached = self.get_cached_result(cache_item)
627 if cached != None: return cached
628
629 self.check_connection()
630 self.execute_query('SELECT SQL_CACHE sum(entropy_downloads.`count`) as downloads FROM entropy_downloads')
631 data = self.fetchone() or {}
632 downloads = data.get('downloads', 0)
633 if not downloads:
634 return 0
635 result = int(downloads)
636
637
638 self.cache_result(cache_item, result)
639 return result
640
642 self.check_connection()
643 self.execute_query('SET @row = 0')
644 self.execute_query("""
645 SELECT Row, col_a FROM (SELECT @row := @row + 1 AS Row, userid AS col_a FROM
646 entropy_user_scores ORDER BY score DESC) As derived1 WHERE col_a = %s""", (userid,))
647 data = self.fetchone() or {}
648 ranking = data.get('Row', 0)
649 if not ranking:
650 return 0
651 return ranking
652
654
655
656 cache_item = 'get_users_scored_count'
657 cached = self.get_cached_result(cache_item)
658 if cached != None:
659 return cached
660
661 self.check_connection()
662 self.execute_query('SELECT SQL_CACHE count(`userid`) as mycount FROM entropy_user_scores')
663 data = self.fetchone() or {}
664 count = data.get('mycount', 0)
665 if not count:
666 return 0
667
668
669 self.cache_result(cache_item, count)
670 return count
671
673 self.check_connection()
674 rows = self.execute_query('SELECT `userid` FROM entropy_user_scores WHERE `userid` = %s', (userid,))
675 if rows:
676 return True
677 return False
678
686
696
705
707 self.check_connection()
708 limit_string = ''
709 if count:
710 limit_string += ' LIMIT %s,%s' % (offset,count,)
711 self.execute_query('SELECT SQL_CALC_FOUND_ROWS *, userid, score FROM entropy_user_scores ORDER BY score DESC' + limit_string)
712 data = self.fetchall()
713
714 self.execute_query('SELECT FOUND_ROWS() as count')
715 rdata = self.fetchone() or {}
716 found_rows = rdata.get('count', 0)
717 if found_rows is None:
718 found_rows = 0
719
720 return found_rows, data
721
723 self.check_connection()
724 self.execute_query('SELECT avg(`vote`) as vote_avg FROM entropy_votes WHERE `userid` = %s', (userid,))
725 data = self.fetchone() or {}
726 vote_avg = data.get('vote_avg', 0.0)
727 if not vote_avg:
728 return 0.0
729 return round(float(vote_avg), 2)
730
732 self.check_connection()
733 self.execute_query("""
734 SELECT * FROM entropy_docs,entropy_base WHERE
735 entropy_docs.`userid` = %s AND
736 entropy_base.idkey = entropy_docs.idkey ORDER BY entropy_base.`key`""", (userid,))
737 return self.fetchall()
738
741
744
749
751 self.check_connection()
752 self.execute_query('SELECT * FROM entropy_docs WHERE `userid` = %s AND `iddoctype` '+doctype_sql_cmp+' %s', (userid,doctype,))
753 return self.fetchall()
754
756 self.check_connection()
757 self.execute_query('SELECT count(`iddoc`) as docs FROM entropy_docs WHERE `userid` = %s AND `iddoctype` '+doctype_sql_cmp+' %s', (userid,doctype,))
758 data = self.fetchone() or {}
759 docs = data.get('docs', 0)
760 if docs is None:
761 docs = 0
762 return docs
763
766
769
772
775
778
780 self.check_connection()
781 self.execute_query('SELECT count(`idvote`) as votes FROM entropy_votes WHERE `userid` = %s', (userid,))
782 data = self.fetchone() or {}
783 votes = data.get('votes', 0)
784 if votes is None:
785 votes = 0
786 return votes
787
801
810
811 - def search_pkgkey_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
812 self.check_connection()
813
814 if iddoctypes is None:
815 iddoctypes = self.DOC_TYPES.values()
816
817 if len(iddoctypes) == 1:
818 iddoctypes_str = " = %s" % (iddoctypes[0],)
819 else:
820 iddoctypes_str = "IN ("+', '.join([str(x) for x in iddoctypes])+")"
821
822 myterm = "%"+pkgkey_string+"%"
823
824 search_params = [myterm,results_offset,results_limit]
825
826 order_by_string = ''
827 if order_by == "key":
828 order_by_string = 'ORDER BY entropy_base.`key`'
829 elif order_by == "username":
830 order_by_string = 'ORDER BY entropy_docs.`username`'
831 elif order_by == "vote":
832 order_by_string = 'ORDER BY avg_vote DESC'
833 elif order_by == "downloads":
834 order_by_string = 'ORDER BY tot_downloads DESC'
835
836 self.execute_query("""
837 SELECT
838 SQL_CALC_FOUND_ROWS entropy_base.`key`,
839 entropy_docs.*,
840 entropy_downloads.iddownload,
841 entropy_downloads.ddate,
842 entropy_votes.idvote,
843 entropy_votes.vdate,
844 entropy_votes.vote,
845 avg(entropy_votes.vote) as avg_vote,
846 sum(entropy_downloads.`count`) as tot_downloads,
847 entropy_user_scores.score as `score`
848 FROM
849 entropy_base
850 LEFT JOIN entropy_votes ON entropy_base.idkey = entropy_votes.idkey
851 LEFT JOIN entropy_docs ON entropy_base.idkey = entropy_docs.idkey
852 LEFT JOIN entropy_docs as ed ON entropy_base.idkey = ed.idkey
853 LEFT JOIN entropy_user_scores on entropy_docs.userid = entropy_user_scores.userid
854 LEFT JOIN entropy_downloads on entropy_base.idkey = entropy_downloads.idkey
855 WHERE
856 entropy_base.`key` LIKE %s AND
857 entropy_docs.iddoctype """+iddoctypes_str+"""
858 GROUP BY entropy_docs.`iddoc`
859 """+order_by_string+"""
860 LIMIT %s,%s
861 """, search_params)
862
863 results = self.fetchall()
864 for item in results:
865 if item['avg_vote'] is None:
866 item['avg_vote'] = 0.0
867
868 self.execute_query('SELECT FOUND_ROWS() as count')
869 data = self.fetchone() or {}
870 count = data.get('count', 0)
871 if count is None:
872 count = 0
873 return results, count
874
875 - def search_username_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
876 self.check_connection()
877
878 if iddoctypes is None:
879 iddoctypes = self.DOC_TYPES.values()
880
881 if len(iddoctypes) == 1:
882 iddoctypes_str = " = %s" % (iddoctypes[0],)
883 else:
884 iddoctypes_str = "IN ("+', '.join([str(x) for x in iddoctypes])+")"
885
886 myterm = "%"+pkgkey_string+"%"
887
888 search_params = [myterm,results_offset,results_limit]
889
890 order_by_string = ''
891 if order_by == "key":
892 order_by_string = 'ORDER BY entropy_base.`key`'
893 elif order_by == "username":
894 order_by_string = 'ORDER BY entropy_docs.`username`'
895 elif order_by == "vote":
896 order_by_string = 'ORDER BY avg_vote DESC'
897 elif order_by == "downloads":
898 order_by_string = 'ORDER BY tot_downloads DESC'
899
900 self.execute_query("""
901 SELECT
902 SQL_CALC_FOUND_ROWS entropy_base.`key`,
903 entropy_docs.*,
904 entropy_downloads.iddownload,
905 entropy_downloads.ddate,
906 entropy_votes.idvote,
907 entropy_votes.vdate,
908 entropy_votes.vote,
909 avg(entropy_votes.vote) as avg_vote,
910 sum(entropy_downloads.`count`) as tot_downloads,
911 entropy_user_scores.score as `score`
912 FROM
913 entropy_base
914 LEFT JOIN entropy_votes ON entropy_base.idkey = entropy_votes.idkey
915 LEFT JOIN entropy_docs ON entropy_base.idkey = entropy_docs.idkey
916 LEFT JOIN entropy_docs as ed ON entropy_base.idkey = ed.idkey
917 LEFT JOIN entropy_user_scores on entropy_docs.userid = entropy_user_scores.userid
918 LEFT JOIN entropy_downloads on entropy_base.idkey = entropy_downloads.idkey
919 WHERE
920 entropy_docs.`username` LIKE %s AND
921 entropy_docs.iddoctype """+iddoctypes_str+"""
922 GROUP BY entropy_docs.`iddoc`
923 """+order_by_string+"""
924 LIMIT %s,%s
925 """, search_params)
926
927 results = self.fetchall()
928
929 for item in results:
930 if item['avg_vote'] is None:
931 item['avg_vote'] = 0.0
932
933 self.execute_query('SELECT FOUND_ROWS() as count')
934 data = self.fetchone() or {}
935 count = data.get('count', 0)
936 if count is None:
937 count = 0
938 return results, count
939
940 - def search_content_items(self, pkgkey_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
941 self.check_connection()
942
943 if iddoctypes is None:
944 iddoctypes = self.DOC_TYPES.values()
945
946 if len(iddoctypes) == 1:
947 iddoctypes_str = " = %s" % (iddoctypes[0],)
948 else:
949 iddoctypes_str = "IN ("+', '.join([str(x) for x in iddoctypes])+")"
950
951 myterm = "%"+pkgkey_string+"%"
952 search_params = [myterm,myterm,myterm,results_offset,results_limit]
953
954 order_by_string = ''
955 if order_by == "key":
956 order_by_string = 'ORDER BY entropy_base.`key`'
957 elif order_by == "username":
958 order_by_string = 'ORDER BY entropy_docs.`username`'
959 elif order_by == "vote":
960 order_by_string = 'ORDER BY avg_vote DESC'
961 elif order_by == "downloads":
962 order_by_string = 'ORDER BY tot_downloads DESC'
963
964 self.execute_query("""
965 SELECT
966 SQL_CALC_FOUND_ROWS entropy_base.`key`,
967 entropy_docs.*,
968 entropy_downloads.iddownload,
969 entropy_downloads.ddate,
970 entropy_votes.idvote,
971 entropy_votes.vdate,
972 entropy_votes.vote,
973 avg(entropy_votes.vote) as avg_vote,
974 sum(entropy_downloads.`count`) as tot_downloads,
975 entropy_user_scores.score as `score`
976 FROM
977 entropy_base
978 LEFT JOIN entropy_votes ON entropy_base.idkey = entropy_votes.idkey
979 LEFT JOIN entropy_docs ON entropy_base.idkey = entropy_docs.idkey
980 LEFT JOIN entropy_docs as ed ON entropy_base.idkey = ed.idkey
981 LEFT JOIN entropy_user_scores on entropy_docs.userid = entropy_user_scores.userid
982 LEFT JOIN entropy_downloads on entropy_base.idkey = entropy_downloads.idkey
983 WHERE
984 (entropy_docs.`title` LIKE %s OR entropy_docs.`description` LIKE %s OR entropy_docs.`ddata` LIKE %s) AND
985 entropy_docs.iddoctype """+iddoctypes_str+"""
986 GROUP BY entropy_docs.`iddoc`
987 """+order_by_string+"""
988 LIMIT %s,%s
989 """, search_params)
990
991 results = self.fetchall()
992
993 for item in results:
994 if item['avg_vote'] is None:
995 item['avg_vote'] = 0.0
996
997 self.execute_query('SELECT FOUND_ROWS() as count')
998 data = self.fetchone() or {}
999 count = data.get('count', 0)
1000 if count is None:
1001 count = 0
1002 return results, count
1003
1004 - def search_keyword_items(self, keyword_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
1005 self.check_connection()
1006
1007 if iddoctypes is None:
1008 iddoctypes = self.DOC_TYPES.values()
1009
1010 if len(iddoctypes) == 1:
1011 iddoctypes_str = " = %s" % (iddoctypes[0],)
1012 else:
1013 iddoctypes_str = "IN ("+', '.join([str(x) for x in iddoctypes])+")"
1014
1015 myterm = "%"+keyword_string+"%"
1016
1017 search_params = [myterm,results_offset,results_limit]
1018
1019 order_by_string = ''
1020 if order_by == "key":
1021 order_by_string = 'ORDER BY entropy_base.`key`'
1022 elif order_by == "username":
1023 order_by_string = 'ORDER BY entropy_docs.`username`'
1024 elif order_by == "vote":
1025 order_by_string = 'ORDER BY avg_vote DESC'
1026 elif order_by == "downloads":
1027 order_by_string = 'ORDER BY tot_downloads DESC'
1028
1029 self.execute_query("""
1030 SELECT
1031 SQL_CALC_FOUND_ROWS entropy_base.`key`,
1032 entropy_docs.*,
1033 entropy_downloads.iddownload,
1034 entropy_downloads.ddate,
1035 entropy_votes.idvote,
1036 entropy_votes.vdate,
1037 entropy_votes.vote,
1038 avg(entropy_votes.vote) as avg_vote,
1039 sum(entropy_downloads.`count`) as tot_downloads,
1040 entropy_user_scores.score as `score`
1041 FROM
1042 entropy_base
1043 LEFT JOIN entropy_votes ON entropy_base.idkey = entropy_votes.idkey
1044 LEFT JOIN entropy_docs ON entropy_base.idkey = entropy_docs.idkey
1045 LEFT JOIN entropy_docs as ed ON entropy_base.idkey = ed.idkey
1046 LEFT JOIN entropy_user_scores on entropy_docs.userid = entropy_user_scores.userid
1047 LEFT JOIN entropy_downloads on entropy_base.idkey = entropy_downloads.idkey
1048 LEFT JOIN entropy_docs_keywords on entropy_docs_keywords.iddoc = entropy_docs.iddoc
1049 WHERE
1050 entropy_docs_keywords.`keyword` LIKE %s AND
1051 entropy_docs.iddoctype """+iddoctypes_str+"""
1052 GROUP BY entropy_docs.`iddoc`
1053 """+order_by_string+"""
1054 LIMIT %s,%s
1055 """, search_params)
1056
1057 results = self.fetchall()
1058
1059 for item in results:
1060 if item['avg_vote'] is None:
1061 item['avg_vote'] = 0.0
1062
1063 self.execute_query('SELECT FOUND_ROWS() as count')
1064 data = self.fetchone() or {}
1065 count = data.get('count', 0)
1066 if count is None:
1067 count = 0
1068 return results, count
1069
1070 - def search_iddoc_item(self, iddoc_string, iddoctypes = None, results_offset = 0, results_limit = 30, order_by = None):
1071 self.check_connection()
1072
1073 if iddoctypes is None:
1074 iddoctypes = self.DOC_TYPES.values()
1075
1076 if len(iddoctypes) == 1:
1077 iddoctypes_str = " = %s" % (iddoctypes[0],)
1078 else:
1079 iddoctypes_str = "IN ("+', '.join([str(x) for x in iddoctypes])+")"
1080
1081 try:
1082 myterm = int(iddoc_string)
1083 except ValueError:
1084 return [], 0
1085
1086 search_params = [myterm,results_offset,results_limit]
1087
1088 order_by_string = ''
1089 if order_by == "key":
1090 order_by_string = 'ORDER BY entropy_base.`key`'
1091 elif order_by == "username":
1092 order_by_string = 'ORDER BY entropy_docs.`username`'
1093 elif order_by == "vote":
1094 order_by_string = 'ORDER BY avg_vote DESC'
1095 elif order_by == "downloads":
1096 order_by_string = 'ORDER BY tot_downloads DESC'
1097
1098 self.execute_query("""
1099 SELECT
1100 SQL_CALC_FOUND_ROWS entropy_base.`key`,
1101 entropy_docs.*,
1102 entropy_downloads.iddownload,
1103 entropy_downloads.ddate,
1104 entropy_votes.idvote,
1105 entropy_votes.vdate,
1106 entropy_votes.vote,
1107 avg(entropy_votes.vote) as avg_vote,
1108 sum(entropy_downloads.`count`) as tot_downloads,
1109 entropy_user_scores.score as `score`
1110 FROM
1111 entropy_base
1112 LEFT JOIN entropy_votes ON entropy_base.idkey = entropy_votes.idkey
1113 LEFT JOIN entropy_docs ON entropy_base.idkey = entropy_docs.idkey
1114 LEFT JOIN entropy_docs as ed ON entropy_base.idkey = ed.idkey
1115 LEFT JOIN entropy_user_scores on entropy_docs.userid = entropy_user_scores.userid
1116 LEFT JOIN entropy_downloads on entropy_base.idkey = entropy_downloads.idkey
1117 WHERE
1118 entropy_docs.`iddoc` = %s AND
1119 entropy_docs.iddoctype """+iddoctypes_str+"""
1120 GROUP BY entropy_docs.`iddoc`
1121 """+order_by_string+"""
1122 LIMIT %s,%s
1123 """, search_params)
1124
1125 results = self.fetchall()
1126
1127 for item in results:
1128 if item['avg_vote'] is None:
1129 item['avg_vote'] = 0.0
1130
1131 self.execute_query('SELECT FOUND_ROWS() as count')
1132 data = self.fetchone() or {}
1133 count = data.get('count', 0)
1134 if count is None:
1135 count = 0
1136 return results, count
1137
1143
1145 self.check_connection()
1146 self.execute_query('SELECT max(`ts`) as ts FROM entropy_docs WHERE `userid` = %s', (userid,))
1147 data = self.fetchone()
1148 if not data:
1149 return False
1150 elif not data.has_key('ts'):
1151 return False
1152 elif data['ts'] == None:
1153 return False
1154 delta = self.datetime.fromtimestamp(time.time()) - data['ts']
1155 if (delta.days == 0) and (delta.seconds <= self.FLOOD_INTERVAL):
1156 return True
1157 return False
1158
1159 - def insert_generic_doc(self, idkey, userid, username, doc_type, data, title, description, keywords, do_commit = False):
1160 self.check_connection()
1161
1162 title = title[:self.entropy_docs_title_len]
1163 description = description[:self.entropy_docs_description_len]
1164
1165
1166 flood_risk = self.insert_flood_control_check(userid)
1167 if flood_risk:
1168 return 'flooding detected'
1169
1170 self.execute_query('INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)',(
1171 None,
1172 idkey,
1173 userid,
1174 username,
1175 doc_type,
1176 data,
1177 title,
1178 description,
1179 None,
1180 )
1181 )
1182 if do_commit:
1183 self.commit()
1184 iddoc = self.lastrowid()
1185 self.insert_keywords(iddoc, keywords)
1186 self.update_user_score(userid)
1187 return iddoc
1188
1190 keywords = keywords.split(",")
1191 clean_keys = []
1192 for key in keywords:
1193 try:
1194 key = key.strip().split()[0]
1195 except IndexError:
1196 continue
1197 if not key: continue
1198 if not key.isalnum(): continue
1199 key = key[:self.entropy_docs_keyword_len]
1200 if key in clean_keys: continue
1201 clean_keys.append(key)
1202
1203 if not clean_keys:
1204 return
1205
1206 mydata = []
1207 for key in clean_keys:
1208 mydata.append((iddoc, key,))
1209
1210 self.execute_many('INSERT INTO entropy_docs_keywords VALUES (%s,%s)', mydata)
1211
1213 self.execute_query('DELETE FROM entropy_docs_keywords WHERE `iddoc` = %s',(iddoc,))
1214
1225
1243
1256
1257
1258 - def do_vote(self, pkgkey, userid, vote, do_commit = False):
1259 self.check_connection()
1260 idkey = self.handle_pkgkey(pkgkey)
1261 vote = int(vote)
1262 if vote not in self.VOTE_RANGE:
1263 vote = 3
1264 mydate = self.get_date()
1265 if self.has_user_already_voted(pkgkey, userid):
1266 return False
1267 self.execute_query('INSERT INTO entropy_votes VALUES (%s,%s,%s,%s,%s,%s)',(
1268 None,
1269 idkey,
1270 userid,
1271 mydate,
1272 vote,
1273 None,
1274 )
1275 )
1276 if do_commit:
1277 self.commit()
1278 self.update_user_score(userid)
1279 return True
1280
1282 self.check_connection()
1283 idkey = self.handle_pkgkey(pkgkey)
1284 self.execute_query('SELECT `idvote` FROM entropy_votes WHERE `idkey` = %s AND `userid` = %s', (idkey,userid,))
1285 data = self.fetchone()
1286 if data:
1287 return True
1288 return False
1289
1290
1291 - def do_downloads(self, pkgkeys, ip_addr = None, do_commit = False):
1292 self.check_connection()
1293 mydate = self.get_date()
1294 iddownloads = set()
1295 for pkgkey in pkgkeys:
1296 iddownload = self.get_iddownload(pkgkey, mydate)
1297 if iddownload == -1:
1298 iddownload = self.insert_download(pkgkey, mydate, count = 1)
1299 else:
1300 self.update_download(iddownload)
1301 if (iddownload > 0) and isinstance(ip_addr,basestring):
1302 iddownloads.add(iddownload)
1303
1304 if iddownloads:
1305 self.store_download_data(iddownloads, ip_addr)
1306 if do_commit:
1307 self.commit()
1308 return True
1309
1310 - def do_download_stats(self, branch, release_string, hw_hash, pkgkeys,
1311 ip_addr, do_commit = False):
1312
1313 self.check_connection()
1314 branch_id = self.get_entropy_branches_id(branch)
1315 if branch_id == -1:
1316 branch_id = self.insert_entropy_branch(branch)
1317
1318 rel_strings_id = self.get_entropy_release_strings_id(release_string)
1319 if rel_strings_id == -1:
1320 rel_strings_id = self.insert_entropy_release_string(release_string)
1321
1322 self.do_downloads(pkgkeys, ip_addr = ip_addr)
1323
1324 entropy_distribution_usage_id = self.is_user_ip_available_in_entropy_distribution_usage(ip_addr)
1325
1326 hits = 1
1327 if self.STATS_MAP['installer'] in pkgkeys:
1328 hits = 0
1329 if entropy_distribution_usage_id == -1:
1330 entropy_ip_locations_id = self.handle_entropy_ip_locations_id(ip_addr)
1331 self.execute_query('INSERT INTO entropy_distribution_usage VALUES (%s,%s,%s,%s,%s,%s,%s,%s)',(
1332 None,
1333 branch_id,
1334 rel_strings_id,
1335 None,
1336 ip_addr,
1337 entropy_ip_locations_id,
1338 self.get_datetime(),
1339 hits,
1340 )
1341 )
1342 entropy_distribution_usage_id = self.lastrowid()
1343 else:
1344 self.execute_query("""
1345 UPDATE entropy_distribution_usage SET `entropy_branches_id` = %s,
1346 `entropy_release_strings_id` = %s,
1347 `hits` = `hits`+%s
1348 WHERE `entropy_distribution_usage_id` = %s
1349 """,(
1350 branch_id,
1351 rel_strings_id,
1352 hits,
1353 entropy_distribution_usage_id,
1354 )
1355 )
1356
1357
1358 if hw_hash and not \
1359 self.is_entropy_hardware_usage_stats_available(entropy_distribution_usage_id):
1360
1361 self.do_entropy_hardware_usage_stats(entropy_distribution_usage_id,
1362 hw_hash)
1363
1364 if do_commit: self.commit()
1365 return True
1366
1368
1369 self.execute_query('INSERT INTO entropy_hardware_usage VALUES (%s,%s,%s)', (
1370 None,
1371 entropy_distribution_usage_id,
1372 hw_hash,
1373 )
1374 )
1375
1377 self.check_connection()
1378 self.execute_query('SELECT entropy_hardware_usage_id FROM entropy_hardware_usage WHERE `entropy_distribution_usage_id` = %s',(entropy_distribution_usage_id,))
1379 data = self.fetchone()
1380 if data:
1381 return True
1382 return False
1383
1385 self.check_connection()
1386 self.execute_query('SELECT entropy_distribution_usage_id FROM entropy_distribution_usage WHERE `ip_address` = %s',(ip_address,))
1387 data = self.fetchone() or {}
1388 myid = data.get('entropy_distribution_usage_id')
1389 if myid is None:
1390 return -1
1391 return myid
1392
1393 - def insert_document(self, pkgkey, userid, username, text, title,
1394 description, keywords, doc_type = None, do_commit = False):
1395 self.check_connection()
1396 idkey = self.handle_pkgkey(pkgkey)
1397 if doc_type == None: doc_type = self.DOC_TYPES['bbcode_doc']
1398 iddoc = self.insert_generic_doc(idkey, userid, username, doc_type,
1399 text, title, description, keywords)
1400 if isinstance(iddoc, basestring):
1401 return False, iddoc
1402 if do_commit:
1403 self.commit()
1404 return True, iddoc
1405
1406 - def edit_document(self, iddoc, new_document, new_title, new_keywords, do_commit = False):
1425
1438
1440
1441 if not os.access(filepath,os.R_OK):
1442 return False,None
1443
1444 args = [self.VIRUS_CHECK_EXEC]
1445 args += self.VIRUS_CHECK_ARGS
1446 args += [filepath]
1447 f = open("/dev/null","w")
1448 p = subprocess.Popen(args, stdout = f, stderr = f)
1449 rc = p.wait()
1450 f.close()
1451 if rc == 1:
1452 return True, None
1453 return False, None
1454
1455 - def insert_generic_file(self, pkgkey, userid, username, file_path,
1456 file_name, doc_type, title, description, keywords):
1457 self.check_connection()
1458 file_path = os.path.realpath(file_path)
1459
1460
1461 virus_found, virus_type = self.scan_for_viruses(file_path)
1462 if virus_found:
1463 os.remove(file_path)
1464 return False, None
1465
1466
1467 flood_risk = self.insert_flood_control_check(userid)
1468 if flood_risk: return False, 'flooding detected'
1469
1470
1471 if doc_type == self.DOC_TYPES['image']:
1472 valid = False
1473 if os.path.isfile(file_path) and os.access(file_path,os.R_OK):
1474 valid = self.entropyTools.is_supported_image_file(file_path)
1475 if not valid:
1476 return False, 'not a valid image'
1477
1478 dest_path = os.path.join(self.STORE_PATH,file_name)
1479
1480
1481 dest_dir = os.path.dirname(dest_path)
1482 if not os.path.isdir(dest_dir):
1483 try:
1484 os.makedirs(dest_dir)
1485 except OSError, e:
1486 raise PermissionDenied('PermissionDenied: %s' % (e,))
1487 if etpConst['entropygid'] != None:
1488 const_setup_perms(dest_dir,etpConst['entropygid'])
1489
1490 orig_dest_path = dest_path
1491 dcount = 0
1492 while os.path.isfile(dest_path):
1493 dcount += 1
1494 dest_path_name = "%s_%s" % (dcount,os.path.basename(orig_dest_path),)
1495 dest_path = os.path.join(os.path.dirname(orig_dest_path),dest_path_name)
1496
1497 if os.path.dirname(file_path) != dest_dir:
1498 try:
1499 os.rename(file_path, dest_path)
1500 except OSError:
1501
1502 shutil.move(file_path, dest_path)
1503 if etpConst['entropygid'] != None:
1504 try:
1505 const_setup_file(dest_path, etpConst['entropygid'], 0664)
1506 except OSError:
1507 pass
1508
1509 try:
1510 const_set_chmod(dest_path,0664)
1511 except OSError:
1512 pass
1513
1514 title = title[:self.entropy_docs_title_len]
1515 description = description[:self.entropy_docs_description_len]
1516
1517
1518 idkey = self.handle_pkgkey(pkgkey)
1519 self.execute_query('INSERT INTO entropy_docs VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)',(
1520 None,
1521 idkey,
1522 userid,
1523 username,
1524 doc_type,
1525 file_name,
1526 title,
1527 description,
1528 None,
1529 )
1530 )
1531 iddoc = self.lastrowid()
1532 self.insert_keywords(iddoc, keywords)
1533 store_url = os.path.basename(dest_path)
1534 if self.store_url:
1535 store_url = os.path.join(self.store_url,store_url)
1536 self.update_user_score(userid)
1537 return True, (iddoc, store_url)
1538
1539 - def insert_image(self, pkgkey, userid, username, image_path, file_name,
1540 title, description, keywords):
1541 return self.insert_generic_file(pkgkey, userid, username, image_path,
1542 file_name, self.DOC_TYPES['image'], title, description, keywords)
1543
1544 - def insert_file(self, pkgkey, userid, username, file_path, file_name, title,
1545 description, keywords):
1546 return self.insert_generic_file(pkgkey, userid, username, file_path,
1547 file_name, self.DOC_TYPES['generic_file'], title, description,
1548 keywords)
1549
1552
1555
1557 self.check_connection()
1558
1559 userid = self.get_iddoc_userid(iddoc)
1560 self.execute_query('SELECT `ddata` FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1561 iddoc,
1562 doc_type,
1563 )
1564 )
1565 data = self.fetchone() or {}
1566 mypath = data.get('ddata')
1567 if not isinstance(mypath, basestring) and (mypath is not None):
1568 mypath = mypath.tostring()
1569 if mypath is not None:
1570 mypath = os.path.join(self.STORE_PATH,mypath)
1571 if os.path.isfile(mypath) and os.access(mypath,os.W_OK):
1572 os.remove(mypath)
1573
1574 self.remove_keywords(iddoc)
1575 self.execute_query('DELETE FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1576 iddoc,
1577 doc_type,
1578 )
1579 )
1580 if userid:
1581 self.update_user_score(userid)
1582 return True, (iddoc, None)
1583
1584 - def insert_youtube_video(self, pkgkey, userid, username, video_path, file_name, title, description, keywords):
1585 self.check_connection()
1586 if not self.gdata:
1587 return False, None
1588
1589 idkey = self.handle_pkgkey(pkgkey)
1590 video_path = os.path.realpath(video_path)
1591 if not (os.access(video_path,os.R_OK) and os.path.isfile(video_path)):
1592 return False
1593 virus_found, virus_type = self.scan_for_viruses(video_path)
1594 if virus_found:
1595 os.remove(video_path)
1596 return False, None
1597
1598 new_video_path = video_path
1599 if isinstance(file_name,basestring):
1600
1601 new_video_path = os.path.join(os.path.dirname(video_path),os.path.basename(file_name))
1602 scount = 0
1603 while os.path.lexists(new_video_path):
1604 scount += 1
1605 bpath = "%s.%s" % (unicode(scount),os.path.basename(file_name),)
1606 new_video_path = os.path.join(os.path.dirname(video_path),bpath)
1607 shutil.move(video_path,new_video_path)
1608
1609 yt_service = self.get_youtube_service()
1610 if yt_service == None:
1611 return False, None
1612
1613 mykeywords = ', '.join([x.strip().strip(',') for x in \
1614 keywords.split() + ["sabayon"] if (x.strip() and x.strip(",") and \
1615 (len(x.strip()) > 4))])
1616 gd_keywords = self.gdata.media.Keywords(text = mykeywords)
1617
1618 mydescription = "%s: %s" % (pkgkey,description,)
1619 mytitle = "%s: %s" % (self.system_name,title,)
1620 my_media_group = self.gdata.media.Group(
1621 title = self.gdata.media.Title(text = mytitle),
1622 description = self.gdata.media.Description(
1623 description_type = 'plain',
1624 text = mydescription
1625 ),
1626 keywords = gd_keywords,
1627 category = self.gdata.media.Category(
1628 text = 'Tech',
1629 scheme = 'http://gdata.youtube.com/schemas/2007/categories.cat',
1630 label = 'Tech'
1631 ),
1632 player = None
1633 )
1634 video_entry = self.gdata.youtube.YouTubeVideoEntry(media = my_media_group)
1635 new_entry = yt_service.InsertVideoEntry(video_entry, new_video_path)
1636 if not isinstance(new_entry, self.gdata.youtube.YouTubeVideoEntry):
1637 return False, None
1638 video_url = new_entry.GetSwfUrl()
1639 video_id = os.path.basename(video_url)
1640
1641 iddoc = self.insert_generic_doc(idkey, userid, username,
1642 self.DOC_TYPES['youtube_video'], video_id, title, description,
1643 keywords)
1644 if isinstance(iddoc,basestring):
1645 return False, (iddoc, None,)
1646 return True, (iddoc, video_id,)
1647
1667
1668 self.execute_query('SELECT `ddata` FROM entropy_docs WHERE `iddoc` = %s AND `iddoctype` = %s',(
1669 iddoc,
1670 self.DOC_TYPES['youtube_video'],
1671 )
1672 )
1673 data = self.fetchone()
1674 if data is None:
1675 do_remove()
1676 return False, None
1677 elif not data.has_key('ddata'):
1678 do_remove()
1679 return False, None
1680
1681 video_id = data.get('ddata')
1682 try:
1683 video_entry = yt_service.GetYouTubeVideoEntry(video_id = video_id)
1684 deleted = yt_service.DeleteVideoEntry(video_entry)
1685 except:
1686 deleted = True
1687
1688 if deleted:
1689 do_remove()
1690 if userid: self.update_user_score(userid)
1691 return deleted, (iddoc, video_id,)
1692
1694 self.check_connection()
1695 if not self.gdata:
1696 return None
1697 keywords = ['google_email', 'google_password']
1698 for keyword in keywords:
1699 if not self.connection_data.has_key(keyword):
1700 return None
1701
1702 srv = self.YouTubeService.YouTubeService()
1703 srv.email = self.connection_data['google_email']
1704 srv.password = self.connection_data['google_password']
1705 if self.connection_data.has_key('google_developer_key'):
1706 srv.developer_key = self.connection_data['google_developer_key']
1707 if self.connection_data.has_key('google_client_id'):
1708 srv.client_id = self.connection_data['google_client_id']
1709 srv.source = 'Entropy'
1710 srv.ProgrammaticLogin()
1711 return srv
1712
1714
1715 import socket
1716 import entropy.dump as dumpTools
1717 import entropy.tools as entropyTools
1718 import zlib
1719 - def __init__(self, OutputInterface, ClientCommandsClass, quiet = False, show_progress = True, output_header = '', ssl = False, socket_timeout = 25):
1720
1721
1722 if not hasattr(OutputInterface,'updateProgress'):
1723 mytxt = _("OutputInterface does not have an updateProgress method")
1724 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
1725 elif not callable(OutputInterface.updateProgress):
1726 mytxt = _("OutputInterface does not have an updateProgress method")
1727 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (OutputInterface,mytxt,))
1728
1729 from entropy.client.services.ugc.commands import Base
1730 if not issubclass(ClientCommandsClass, (Base,)):
1731 mytxt = _("A valid entropy.client.services.ugc.commands.Base interface is needed")
1732 raise IncorrectParameter("IncorrectParameter: %s, (! %s !)" % (ClientCommandsClass,mytxt,))
1733
1734 self.ssl_mod = None
1735 self.setup_ssl(ssl)
1736
1737 self.answers = etpConst['socket_service']['answers']
1738 self.Output = OutputInterface
1739 self.sock_conn = None
1740 self.real_sock_conn = None
1741 self.hostname = None
1742 self.hostport = None
1743 self.buffered_data = ''
1744 self.buffer_length = None
1745 self.quiet = quiet
1746 self.show_progress = show_progress
1747 self.output_header = output_header
1748 self.CmdInterface = ClientCommandsClass(self.Output, self)
1749 self.CmdInterface.output_header = self.output_header
1750 self.socket_timeout = socket_timeout
1751 self.socket.setdefaulttimeout(self.socket_timeout)
1752
1753
1755
1756 self.SSL = {}
1757 self.SSL_exceptions = {
1758 'WantReadError': None,
1759 'WantWriteError': None,
1760 'WantX509LookupError': None,
1761 'ZeroReturnError': None,
1762 'Error': None,
1763 'SysCallError': None
1764 }
1765 self.ssl = ssl
1766 self.pyopenssl = True
1767 self.context = None
1768
1769 '''
1770 self.server_cert = server_cert
1771 self.server_ca_cert = server_ca_cert
1772 self.ssl_pkey = None
1773 self.ssl_cert = None
1774 self.ssl_CN = 'Entropy Repository Service Client'
1775 self.ssl_digest = 'md5'
1776 self.ssl_serial = 1
1777 self.ssl_not_before = 0
1778 self.ssl_not_after = 60*60*24*1 # 1 day
1779 '''
1780
1781 if self.ssl:
1782
1783 if "--nopyopenssl" in sys.argv:
1784 self.pyopenssl = False
1785 else:
1786 try:
1787 from OpenSSL import SSL, crypto
1788 except ImportError:
1789 self.pyopenssl = False
1790
1791
1792 try:
1793 import ssl as ssl_mod
1794 self.ssl_mod = ssl_mod
1795 except ImportError:
1796 pass
1797
1798 '''
1799 if not (self.server_cert and self.server_ca_cert):
1800 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),)
1801 if not (os.path.isfile(self.server_cert) and \
1802 os.access(self.server_cert,os.R_OK) and \
1803 os.path.isfile(self.server_ca_cert) and \
1804 os.access(self.server_ca_cert,os.R_OK)) and self.pyopenssl:
1805 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),self.server_cert,))
1806 '''
1807
1808 if self.pyopenssl:
1809
1810 self.SSL_exceptions['WantReadError'] = SSL.WantReadError
1811 self.SSL_exceptions['WantWriteError'] = SSL.WantWriteError
1812 self.SSL_exceptions['WantX509LookupError'] = SSL.WantX509LookupError
1813 self.SSL_exceptions['ZeroReturnError'] = SSL.ZeroReturnError
1814 self.SSL_exceptions['Error'] = SSL.Error
1815 self.SSL_exceptions['SysCallError'] = SSL.SysCallError
1816 self.SSL['m'] = SSL
1817 self.SSL['crypto'] = crypto
1818
1819
1820 self.context = self.SSL['m'].Context(self.SSL['m'].SSLv23_METHOD)
1821
1822
1823
1824 '''
1825 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1826 self.context.use_privatekey(self.ssl_pkey)
1827 self.context.use_certificate_file(self.server_cert)
1828 self.context.load_verify_locations(self.server_ca_cert)
1829 self.context.load_client_ca(self.server_cert)
1830 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1831 self.ssl_cert = self.create_ssl_certificate(self.ssl_pkey)
1832 self.context.use_privatekey(self.ssl_pkey)
1833 self.context.use_certificate(self.ssl_cert)
1834 self.context.load_client_ca(self.server_cert)
1835 '''
1836
1837 else:
1838 self.ssl = False
1839 self.pyopenssl = False
1840
1841
1843 if not self.pyopenssl:
1844 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1845
1846 '''
1847 # this function should do the authentication checking to see that
1848 # the client is who they say they are.
1849 def verify_ssl_cb(self, conn, cert, errnum, depth, ok):
1850 self.check_pyopenssl()
1851 #print 'Got certificate: %s' % cert.get_subject()
1852 #print repr(ok),repr(cert),repr(errnum),repr(depth)
1853 return ok
1854
1855
1856 def create_ssl_key_pair(self, keytype, bits):
1857 if not self.pyopenssl:
1858 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1859 pkey = self.SSL['crypto'].PKey()
1860 pkey.generate_key(keytype, bits)
1861 return pkey
1862
1863 def create_ssl_certificate(self, pkey):
1864 self.check_pyopenssl()
1865 myreq = self.create_ssl_certificate_request(pkey, CN = self.ssl_CN)
1866 cert = self.SSL['crypto'].X509()
1867 cert.set_serial_number(self.ssl_serial)
1868 cert.gmtime_adj_notBefore(self.ssl_not_before)
1869 cert.gmtime_adj_notAfter(self.ssl_not_after)
1870 cert.set_issuer(myreq.get_subject())
1871 cert.set_subject(myreq.get_subject())
1872 cert.set_pubkey(myreq.get_pubkey())
1873 cert.sign(pkey, self.ssl_digest)
1874 return cert
1875
1876 def create_ssl_certificate_request(self, pkey, **name):
1877 self.check_pyopenssl()
1878 req = self.SSL['crypto'].X509Req()
1879 subj = req.get_subject()
1880 for (key,value) in name.items():
1881 setattr(subj, key, value)
1882 req.set_pubkey(pkey)
1883 req.sign(pkey, self.ssl_digest)
1884
1885 return req
1886 '''
1887
1889
1890 if gzipped:
1891 data = self.zlib.decompress(data)
1892 obj = self.dumpTools.unserialize_string(data)
1893
1894 return obj
1895
1897 return str(len(data))+self.answers['eos']+data
1898
1900 self.check_socket_connection()
1901 if hasattr(self.sock_conn,'settimeout'):
1902 self.sock_conn.settimeout(self.socket_timeout)
1903 data = self.append_eos(data)
1904 try:
1905
1906 encode_done = False
1907 mydata = data[:]
1908 while 1:
1909 try:
1910 if self.ssl and not self.pyopenssl:
1911 sent = self.sock_conn.write(mydata)
1912 else:
1913 sent = self.sock_conn.send(mydata)
1914 if sent == len(mydata):
1915 break
1916 mydata = mydata[sent:]
1917
1918 except self.SSL_exceptions['WantWriteError']:
1919 self._ssl_poll(select.POLLOUT, 'write')
1920 except self.SSL_exceptions['WantReadError']:
1921 self._ssl_poll(select.POLLIN, 'write')
1922 except UnicodeEncodeError, e:
1923 if encode_done:
1924 raise
1925 mydata = mydata.encode('utf-8')
1926 encode_done = True
1927 continue
1928
1929 except self.SSL_exceptions['Error'], e:
1930 self.disconnect()
1931 raise SSLError('SSLError: %s' % (e,))
1932 except self.socket.sslerror, e:
1933 self.disconnect()
1934 raise SSLError('SSL Socket error: %s' % (e,))
1935 except:
1936 self.disconnect()
1937 raise
1938
1940 self.check_socket_connection()
1941 try:
1942 self.transmit("%s end" % (session_id,))
1943
1944 data = self.receive()
1945 except self.socket.error, e:
1946 if etpUi['debug']:
1947 self.entropyTools.print_traceback()
1948 import pdb
1949 pdb.set_trace()
1950 if e[0] == 32:
1951 return None
1952 raise
1953 except SSLError:
1954 raise
1955 return data
1956
1963
1965 self.check_socket_connection()
1966 self.socket.setdefaulttimeout(self.socket_timeout)
1967 self.transmit('alive %s' % (session,))
1968 data = self.receive()
1969 if data == self.answers['ok']:
1970 return True
1971 return False
1972
1973 - def _ssl_poll(self, filter_type, caller_name):
1974 poller = select.poll()
1975 poller.register(self.sock_conn, filter_type)
1976 res = poller.poll(self.sock_conn.gettimeout() * 1000)
1977 if len(res) != 1:
1978 raise TimeoutError("Connection timed out on %s" % caller_name)
1979
1981
1982 self.check_socket_connection()
1983 if hasattr(self.sock_conn,'settimeout'):
1984 self.sock_conn.settimeout(self.socket_timeout)
1985 self.ssl_prepending = True
1986
1987 def do_receive():
1988 data = ''
1989 if self.ssl and not self.pyopenssl:
1990 data = self.sock_conn.read(1024)
1991 elif self.ssl:
1992 if self.ssl_prepending:
1993 data = self.sock_conn.recv(1024)
1994 self.ssl_prepending = False
1995 while self.sock_conn.pending():
1996 data += self.sock_conn.recv(1024)
1997 else:
1998 data = self.sock_conn.recv(1024)
1999 return data
2000
2001 myeos = self.answers['eos']
2002 while 1:
2003
2004 try:
2005
2006 data = do_receive()
2007 if self.buffer_length == None:
2008 self.buffered_data = ''
2009 if (data == '') or (data == self.answers['cl']):
2010
2011
2012 if not self.quiet:
2013 mytxt = _("command not supported. receive aborted")
2014 self.Output.updateProgress(
2015 "[%s:%s] %s" % (
2016 brown(self.hostname),
2017 bold(str(self.hostport)),
2018 blue(mytxt),
2019 ),
2020 importance = 1,
2021 type = "warning",
2022 header = self.output_header
2023 )
2024 return None
2025 elif len(data) < len(myeos):
2026 if not self.quiet:
2027 mytxt = _("malformed EOS. receive aborted")
2028 self.Output.updateProgress(
2029 "[%s:%s] %s" % (
2030 brown(self.hostname),
2031 bold(str(self.hostport)),
2032 blue(mytxt),
2033 ),
2034 importance = 1,
2035 type = "warning",
2036 header = self.output_header
2037 )
2038 if etpUi['debug']:
2039 self.entropyTools.print_traceback()
2040 import pdb
2041 pdb.set_trace()
2042 return None
2043 mystrlen = data.split(myeos)[0]
2044 self.buffer_length = int(mystrlen)
2045 data = data[len(mystrlen)+1:]
2046 self.buffer_length -= len(data)
2047 self.buffered_data = data
2048 else:
2049 self.buffer_length -= len(data)
2050 self.buffered_data += data
2051
2052 while self.buffer_length > 0:
2053 x = do_receive()
2054 if self.ssl and self.pyopenssl and not x:
2055 self.ssl_prepending = True
2056 self.buffer_length -= len(x)
2057 self.buffered_data += x
2058 self.buffer_length = None
2059 break
2060
2061 except ValueError, e:
2062 if not self.quiet:
2063 mytxt = _("malformed data. receive aborted")
2064 self.Output.updateProgress(
2065 "[%s:%s] %s: %s" % (
2066 brown(self.hostname),
2067 bold(str(self.hostport)),
2068 blue(mytxt),
2069 e,
2070 ),
2071 importance = 1,
2072 type = "warning",
2073 header = self.output_header
2074 )
2075 return None
2076 except self.socket.timeout, e:
2077 if not self.quiet:
2078 mytxt = _("connection timed out while receiving data")
2079 self.Output.updateProgress(
2080 "[%s:%s] %s: %s" % (
2081 brown(self.hostname),
2082 bold(str(self.hostport)),
2083 blue(mytxt),
2084 e,
2085 ),
2086 importance = 1,
2087 type = "warning",
2088 header = self.output_header
2089 )
2090 return None
2091 except self.socket.error, e:
2092 if not self.quiet:
2093 mytxt = _("connection error while receiving data")
2094 self.Output.updateProgress(
2095 "[%s:%s] %s: %s" % (
2096 brown(self.hostname),
2097 bold(str(self.hostport)),
2098 blue(mytxt),
2099 e,
2100 ),
2101 importance = 1,
2102 type = "warning",
2103 header = self.output_header
2104 )
2105 return None
2106 except self.SSL_exceptions['WantX509LookupError']:
2107 continue
2108 except self.SSL_exceptions['WantReadError']:
2109 self._ssl_poll(select.POLLIN, 'read')
2110 except self.SSL_exceptions['WantWriteError']:
2111 self._ssl_poll(select.POLLOUT, 'read')
2112 except self.SSL_exceptions['ZeroReturnError']:
2113 break
2114 except self.SSL_exceptions['SysCallError'], e:
2115 if not self.quiet:
2116 mytxt = _("syscall error while receiving data")
2117 self.Output.updateProgress(
2118 "[%s:%s] %s: %s" % (
2119 brown(self.hostname),
2120 bold(str(self.hostport)),
2121 blue(mytxt),
2122 e,
2123 ),
2124 importance = 1,
2125 type = "warning",
2126 header = self.output_header
2127 )
2128 return None
2129
2130 return self.buffered_data
2131
2133 if not self.quiet:
2134 mytxt = _("Reconnecting to socket")
2135 self.Output.updateProgress(
2136 "[%s:%s] %s" % (
2137 brown(unicode(self.hostname)),
2138 bold(unicode(self.hostport)),
2139 blue(mytxt),
2140 ),
2141 importance = 1,
2142 type = "info",
2143 header = self.output_header
2144 )
2145 self.connect(self.hostname,self.hostport)
2146
2148 if not self.sock_conn:
2149 raise ConnectionError("ConnectionError: %s" % (_("Not connected to host"),))
2150
2152
2153 if self.ssl:
2154 self.real_sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2155 if hasattr(self.real_sock_conn,'settimeout'):
2156 self.real_sock_conn.settimeout(self.socket_timeout)
2157 if self.pyopenssl:
2158 self.sock_conn = self.SSL['m'].Connection(self.context, self.real_sock_conn)
2159 else:
2160 self.sock_conn = self.real_sock_conn
2161
2162
2163
2164 self.real_sock_conn.setblocking(True)
2165 else:
2166 self.sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2167 if hasattr(self.sock_conn,'settimeout'):
2168 self.sock_conn.settimeout(self.socket_timeout)
2169 self.real_sock_conn = self.sock_conn
2170
2171 self.hostname = host
2172 self.hostport = port
2173
2174 try:
2175 self.sock_conn.connect((self.hostname, self.hostport))
2176 if self.ssl and not self.pyopenssl:
2177 if self.ssl_mod is not None:
2178 self.sock_conn = self.ssl_mod.wrap_socket(self.real_sock_conn)
2179 else:
2180 self.sock_conn = self.socket.ssl(self.real_sock_conn)
2181
2182 if not self.quiet:
2183 mytxt = _("Warning: you are using an emergency SSL interface, SSL certificate can't be verified. Please install dev-python/pyopenssl")
2184 self.Output.updateProgress(
2185 "[%s:%s] %s" % (
2186 brown(str(self.hostname)),
2187 bold(str(self.hostport)),
2188 blue(mytxt),
2189 ),
2190 importance = 1,
2191 type = "warning",
2192 header = self.output_header
2193 )
2194 mytxt = _("Service issuer")
2195 self.Output.updateProgress(
2196 "[%s:%s] %s: %s" % (
2197 brown(str(self.hostname)),
2198 bold(str(self.hostport)),
2199 blue(mytxt),
2200 self.sock_conn.issuer()
2201 ),
2202 importance = 1,
2203 type = "warning",
2204 header = self.output_header
2205 )
2206 except self.socket.error, e:
2207 if e[0] == 111:
2208 mytxt = "%s: %s, %s: %s" % (_("Cannot connect to"),host,_("on port"),port,)
2209 raise ConnectionError("ConnectionError: %s" % (mytxt,))
2210 else:
2211 raise
2212
2213 if not self.quiet:
2214 mytxt = _("Successfully connected to host")
2215 self.Output.updateProgress(
2216 "[%s:%s] %s" % (
2217 brown(self.hostname),
2218 bold(str(self.hostport)),
2219 blue(mytxt),
2220 ),
2221 importance = 1,
2222 type = "info",
2223 header = self.output_header
2224 )
2225
2227 if not self.real_sock_conn:
2228 return True
2229 if self.ssl and self.pyopenssl:
2230 self.sock_conn.shutdown()
2231 self.sock_conn.close()
2232 elif self.ssl and not self.pyopenssl:
2233 try:
2234 self.real_sock_conn.shutdown(self.socket.SHUT_RDWR)
2235 except self.socket.error:
2236 pass
2237 del self.sock_conn
2238 self.sock_conn = None
2239 try:
2240 self.real_sock_conn.close()
2241 except self.socket.error:
2242 pass
2243 if not self.quiet:
2244 mytxt = _("Successfully disconnected from host")
2245 self.Output.updateProgress(
2246 "[%s:%s] %s" % (
2247 brown(self.hostname),
2248 bold(str(self.hostport)),
2249 blue(mytxt),
2250 ),
2251 importance = 1,
2252 type = "info",
2253 header = self.output_header
2254 )
2255 self.real_sock_conn = None
2256
2257
2258
2259