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 import os
14 import sys
15 import select
16 import time
17 import subprocess
18 import shutil
19 from entropy.services.skel import RemoteDatabase
20 from entropy.exceptions import *
21 from entropy.const import etpConst, etpUi, etpCache, const_setup_perms, \
22 const_set_chmod, const_setup_file, const_get_stringtype, \
23 const_convert_to_rawstring, const_convert_to_unicode, const_debug_write
24 from entropy.output import brown, bold, blue, darkred, darkblue
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 as 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 = list(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 = list(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 = list(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 = list(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 = list(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 'ts' not in data:
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):
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, const_get_stringtype()):
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 as 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'], 0o664)
1506 except OSError:
1507 pass
1508
1509 try:
1510 const_set_chmod(dest_path, 0o664)
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, const_get_stringtype()) 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, const_get_stringtype()):
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" % (str(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, const_get_stringtype()):
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 'ddata' not in data:
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 keyword not in self.connection_data:
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 'google_developer_key' in self.connection_data:
1706 srv.developer_key = self.connection_data['google_developer_key']
1707 if 'google_client_id' in self.connection_data:
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.0):
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 hasattr(OutputInterface.updateProgress, '__call__'):
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 = const_convert_to_rawstring('')
1744 self.buffer_length = None
1745 self.quiet = quiet
1746 if self.quiet and etpUi['debug']:
1747 self.quiet = False
1748 self.show_progress = show_progress
1749 self.output_header = output_header
1750 self.CmdInterface = ClientCommandsClass(self.Output, self)
1751 self.CmdInterface.output_header = self.output_header
1752 const_debug_write(__name__, "%s loaded with timeout %s" % (
1753 self, float(socket_timeout),))
1754 self.socket_timeout = float(socket_timeout)
1755 self.socket.setdefaulttimeout(self.socket_timeout)
1756
1757
1759
1760 self.SSL = {}
1761 self.SSL_exceptions = {
1762 'WantReadError': DumbException,
1763 'WantWriteError': DumbException,
1764 'WantX509LookupError': DumbException,
1765 'ZeroReturnError': DumbException,
1766 'Error': DumbException,
1767 'SysCallError': DumbException,
1768 }
1769 self.ssl = ssl
1770 self.pyopenssl = True
1771 self.context = None
1772
1773 '''
1774 self.server_cert = server_cert
1775 self.server_ca_cert = server_ca_cert
1776 self.ssl_pkey = None
1777 self.ssl_cert = None
1778 self.ssl_CN = 'Entropy Repository Service Client'
1779 self.ssl_digest = 'md5'
1780 self.ssl_serial = 1
1781 self.ssl_not_before = 0
1782 self.ssl_not_after = 60*60*24*1 # 1 day
1783 '''
1784
1785 if self.ssl:
1786
1787 if "--nopyopenssl" in sys.argv:
1788 self.pyopenssl = False
1789 else:
1790 try:
1791 from OpenSSL import SSL, crypto
1792 except ImportError:
1793 self.pyopenssl = False
1794
1795
1796 try:
1797 import ssl as ssl_mod
1798 self.ssl_mod = ssl_mod
1799 except ImportError:
1800 pass
1801
1802 '''
1803 if not (self.server_cert and self.server_ca_cert):
1804 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),)
1805 if not (os.path.isfile(self.server_cert) and \
1806 os.access(self.server_cert,os.R_OK) and \
1807 os.path.isfile(self.server_ca_cert) and \
1808 os.access(self.server_ca_cert,os.R_OK)) and self.pyopenssl:
1809 raise SSLError('SSLError: %s: %s' % (_("Specified SSL server certificate not available"),self.server_cert,))
1810 '''
1811
1812 if self.pyopenssl:
1813
1814 self.SSL_exceptions['WantReadError'] = SSL.WantReadError
1815 self.SSL_exceptions['WantWriteError'] = SSL.WantWriteError
1816 self.SSL_exceptions['WantX509LookupError'] = SSL.WantX509LookupError
1817 self.SSL_exceptions['ZeroReturnError'] = SSL.ZeroReturnError
1818 self.SSL_exceptions['Error'] = SSL.Error
1819 self.SSL_exceptions['SysCallError'] = SSL.SysCallError
1820 self.SSL['m'] = SSL
1821 self.SSL['crypto'] = crypto
1822
1823
1824 self.context = self.SSL['m'].Context(self.SSL['m'].SSLv23_METHOD)
1825
1826
1827
1828 '''
1829 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1830 self.context.use_privatekey(self.ssl_pkey)
1831 self.context.use_certificate_file(self.server_cert)
1832 self.context.load_verify_locations(self.server_ca_cert)
1833 self.context.load_client_ca(self.server_cert)
1834 self.ssl_pkey = self.create_ssl_key_pair(self.SSL['crypto'].TYPE_RSA, 1024)
1835 self.ssl_cert = self.create_ssl_certificate(self.ssl_pkey)
1836 self.context.use_privatekey(self.ssl_pkey)
1837 self.context.use_certificate(self.ssl_cert)
1838 self.context.load_client_ca(self.server_cert)
1839 '''
1840
1841 else:
1842 self.ssl = False
1843 self.pyopenssl = False
1844
1845
1847 if not self.pyopenssl:
1848 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1849
1850 '''
1851 # this function should do the authentication checking to see that
1852 # the client is who they say they are.
1853 def verify_ssl_cb(self, conn, cert, errnum, depth, ok):
1854 self.check_pyopenssl()
1855 #print 'Got certificate: %s' % cert.get_subject()
1856 #print repr(ok),repr(cert),repr(errnum),repr(depth)
1857 return ok
1858
1859
1860 def create_ssl_key_pair(self, keytype, bits):
1861 if not self.pyopenssl:
1862 raise SSLError('SSLError: %s' % (_("OpenSSL Python module not available, you need dev-python/pyopenssl"),))
1863 pkey = self.SSL['crypto'].PKey()
1864 pkey.generate_key(keytype, bits)
1865 return pkey
1866
1867 def create_ssl_certificate(self, pkey):
1868 self.check_pyopenssl()
1869 myreq = self.create_ssl_certificate_request(pkey, CN = self.ssl_CN)
1870 cert = self.SSL['crypto'].X509()
1871 cert.set_serial_number(self.ssl_serial)
1872 cert.gmtime_adj_notBefore(self.ssl_not_before)
1873 cert.gmtime_adj_notAfter(self.ssl_not_after)
1874 cert.set_issuer(myreq.get_subject())
1875 cert.set_subject(myreq.get_subject())
1876 cert.set_pubkey(myreq.get_pubkey())
1877 cert.sign(pkey, self.ssl_digest)
1878 return cert
1879
1880 def create_ssl_certificate_request(self, pkey, **name):
1881 self.check_pyopenssl()
1882 req = self.SSL['crypto'].X509Req()
1883 subj = req.get_subject()
1884 for (key,value) in name.items():
1885 setattr(subj, key, value)
1886 req.set_pubkey(pkey)
1887 req.sign(pkey, self.ssl_digest)
1888
1889 return req
1890 '''
1891
1893
1894 if gzipped:
1895 data = self.zlib.decompress(data)
1896 obj = self.dumpTools.unserialize_string(data)
1897
1898 return obj
1899
1903
1905
1906 if sys.hexversion >= 0x3000000:
1907
1908 data = const_convert_to_rawstring(data)
1909
1910 self.check_socket_connection()
1911 if hasattr(self.sock_conn, 'settimeout'):
1912 self.sock_conn.settimeout(self.socket_timeout)
1913 data = self.append_eos(data)
1914
1915 if etpUi['debug']:
1916 const_debug_write(__name__, darkblue("=== send ======== \\"))
1917 const_debug_write(__name__, darkblue(repr(data)))
1918 const_debug_write(__name__, darkblue("=== send ======== /"))
1919
1920 try:
1921
1922 encode_done = False
1923 mydata = data[:]
1924 while True:
1925 try:
1926 if self.ssl and not self.pyopenssl:
1927 sent = self.sock_conn.write(mydata)
1928 else:
1929 sent = self.sock_conn.send(mydata)
1930 if sent == len(mydata):
1931 break
1932 mydata = mydata[sent:]
1933
1934 except self.SSL_exceptions['WantWriteError']:
1935 self._ssl_poll(select.POLLOUT, 'write')
1936 except self.SSL_exceptions['WantReadError']:
1937 self._ssl_poll(select.POLLIN, 'write')
1938 except UnicodeEncodeError as e:
1939 if encode_done:
1940 raise
1941 mydata = mydata.encode('utf-8')
1942 encode_done = True
1943 continue
1944
1945 except self.SSL_exceptions['Error'] as e:
1946 self.disconnect()
1947 raise SSLError('SSLError: %s' % (e,))
1948 except self.socket.sslerror as e:
1949 self.disconnect()
1950 raise SSLError('SSL Socket error: %s' % (e,))
1951 except:
1952 self.disconnect()
1953 raise
1954
1956 self.check_socket_connection()
1957 try:
1958 self.transmit("%s end" % (session_id,))
1959
1960 data = self.receive()
1961 except self.socket.error as e:
1962 if etpUi['debug']:
1963 self.entropyTools.print_traceback()
1964 import pdb
1965 pdb.set_trace()
1966 if e[0] == 32:
1967 return None
1968 raise
1969 except SSLError:
1970 raise
1971 return data
1972
1979
1981 self.check_socket_connection()
1982 self.socket.setdefaulttimeout(self.socket_timeout)
1983 self.transmit('alive %s' % (session,))
1984 data = self.receive()
1985 if data == self.answers['ok']:
1986 return True
1987 return False
1988
1989 - def _ssl_poll(self, filter_type, caller_name):
1990 poller = select.poll()
1991 poller.register(self.sock_conn, filter_type)
1992 res = poller.poll(self.sock_conn.gettimeout() * 1000)
1993 if len(res) != 1:
1994 raise TimeoutError("Connection timed out on %s" % caller_name)
1995
1997
1998 self.check_socket_connection()
1999 if hasattr(self.sock_conn, 'settimeout'):
2000 self.sock_conn.settimeout(self.socket_timeout)
2001 self.ssl_prepending = True
2002
2003 def print_timeout_err():
2004 if not self.quiet:
2005 mytxt = _("connection error while receiving data")
2006 self.Output.updateProgress(
2007 "[%s:%s|timeout:%s] %s: %s" % (
2008 brown(self.hostname),
2009 bold(str(self.hostport)),
2010 blue(str(self.socket_timeout)),
2011 blue(mytxt),
2012 e,
2013 ),
2014 importance = 1,
2015 type = "warning",
2016 header = self.output_header
2017 )
2018
2019 def do_receive():
2020 data = const_convert_to_rawstring('')
2021 if self.ssl and not self.pyopenssl:
2022 data = self.sock_conn.read(16384)
2023 elif self.ssl:
2024 if self.ssl_prepending:
2025 data = self.sock_conn.recv(16384)
2026 self.ssl_prepending = False
2027 while self.sock_conn.pending():
2028 data += self.sock_conn.recv(16384)
2029 else:
2030 data = self.sock_conn.recv(16384)
2031 return data
2032
2033 myeos = self.answers['eos']
2034 while True:
2035
2036 try:
2037
2038 cl_answer = self.answers['cl']
2039 data = do_receive()
2040 if self.buffer_length == None:
2041 self.buffered_data = const_convert_to_rawstring('')
2042 if (not data) or (data == cl_answer):
2043
2044
2045 if not self.quiet:
2046 mytxt = _("command not supported. receive aborted")
2047 self.Output.updateProgress(
2048 "[%s:%s] %s" % (
2049 brown(self.hostname),
2050 bold(str(self.hostport)),
2051 blue(mytxt),
2052 ),
2053 importance = 1,
2054 type = "warning",
2055 header = self.output_header
2056 )
2057 return None
2058 elif len(data) < len(myeos):
2059 if not self.quiet:
2060 mytxt = _("malformed EOS. receive aborted")
2061 self.Output.updateProgress(
2062 "[%s:%s] %s" % (
2063 brown(self.hostname),
2064 bold(str(self.hostport)),
2065 blue(mytxt),
2066 ),
2067 importance = 1,
2068 type = "warning",
2069 header = self.output_header
2070 )
2071 if etpUi['debug']:
2072 self.entropyTools.print_traceback()
2073 import pdb
2074 pdb.set_trace()
2075 return None
2076
2077 mystrlen = data.split(myeos)[0]
2078 self.buffer_length = int(mystrlen)
2079 data = data[len(mystrlen)+1:]
2080 self.buffer_length -= len(data)
2081 self.buffered_data = data
2082
2083 else:
2084
2085 self.buffer_length -= len(data)
2086 self.buffered_data += data
2087
2088 while self.buffer_length > 0:
2089
2090 x = do_receive()
2091
2092 if self.ssl and self.pyopenssl and not x:
2093 self.ssl_prepending = True
2094 self.buffer_length -= len(x)
2095 self.buffered_data += x
2096 self.buffer_length = None
2097 break
2098
2099 except ValueError as e:
2100 if not self.quiet:
2101 mytxt = _("malformed data. receive aborted")
2102 self.Output.updateProgress(
2103 "[%s:%s] %s: %s" % (
2104 brown(self.hostname),
2105 bold(str(self.hostport)),
2106 blue(mytxt),
2107 e,
2108 ),
2109 importance = 1,
2110 type = "warning",
2111 header = self.output_header
2112 )
2113 return None
2114 except self.socket.timeout as e:
2115 if not self.quiet:
2116 mytxt = _("connection timed out 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 except self.socket.error as e:
2130 print_timeout_err()
2131 return None
2132
2133 except self.SSL_exceptions['WantX509LookupError']:
2134 const_debug_write(__name__, "WantX509LookupError on receive()")
2135 continue
2136
2137 except self.SSL_exceptions['WantReadError']:
2138 const_debug_write(__name__, "WantReadError on receive()")
2139 try:
2140 self._ssl_poll(select.POLLIN, 'read')
2141 except TimeoutError as e:
2142 print_timeout_err()
2143 return None
2144
2145 except self.SSL_exceptions['WantWriteError']:
2146 const_debug_write(__name__, "WantWriteError on receive()")
2147 try:
2148 self._ssl_poll(select.POLLOUT, 'read')
2149 except TimeoutError as e:
2150 print_timeout_err()
2151 return None
2152
2153 except self.SSL_exceptions['ZeroReturnError']:
2154 const_debug_write(__name__, "ZeroReturnError on receive(), breaking")
2155 break
2156
2157 except self.SSL_exceptions['SysCallError'] as e:
2158 if not self.quiet:
2159 mytxt = _("syscall error while receiving data")
2160 self.Output.updateProgress(
2161 "[%s:%s] %s: %s" % (
2162 brown(self.hostname),
2163 bold(str(self.hostport)),
2164 blue(mytxt),
2165 e,
2166 ),
2167 importance = 1,
2168 type = "warning",
2169 header = self.output_header
2170 )
2171 return None
2172
2173 if etpUi['debug']:
2174 const_debug_write(__name__, darkred("=== recv ======== \\"))
2175 const_debug_write(__name__, darkred(repr(data)))
2176 const_debug_write(__name__, darkred("=== recv ======== /"))
2177
2178 return const_convert_to_rawstring(self.buffered_data)
2179
2181 if not self.quiet:
2182 mytxt = _("Reconnecting to socket")
2183 self.Output.updateProgress(
2184 "[%s:%s] %s" % (
2185 brown(str(self.hostname)),
2186 bold(str(self.hostport)),
2187 blue(mytxt),
2188 ),
2189 importance = 1,
2190 type = "info",
2191 header = self.output_header
2192 )
2193 self.connect(self.hostname, self.hostport)
2194
2196 if not self.sock_conn:
2197 raise ConnectionError("ConnectionError: %s" % (_("Not connected to host"),))
2198
2200
2201 if self.ssl:
2202 self.real_sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2203 if hasattr(self.real_sock_conn, 'settimeout'):
2204 self.real_sock_conn.settimeout(self.socket_timeout)
2205 if self.pyopenssl:
2206 self.sock_conn = self.SSL['m'].Connection(self.context, self.real_sock_conn)
2207 else:
2208 self.sock_conn = self.real_sock_conn
2209 else:
2210 self.sock_conn = self.socket.socket(self.socket.AF_INET, self.socket.SOCK_STREAM)
2211 if hasattr(self.sock_conn, 'settimeout'):
2212 self.sock_conn.settimeout(self.socket_timeout)
2213 self.real_sock_conn = self.sock_conn
2214
2215 self.hostname = host
2216 self.hostport = port
2217
2218 try:
2219 self.sock_conn.connect((self.hostname, self.hostport))
2220 if self.ssl and not self.pyopenssl:
2221 if self.ssl_mod is not None:
2222 self.sock_conn = self.ssl_mod.wrap_socket(self.real_sock_conn)
2223 else:
2224 self.sock_conn = self.socket.ssl(self.real_sock_conn)
2225
2226 if not self.quiet:
2227 mytxt = _("Warning: you are using an emergency SSL interface, SSL certificate can't be verified. Please install dev-python/pyopenssl")
2228 self.Output.updateProgress(
2229 "[%s:%s] %s" % (
2230 brown(str(self.hostname)),
2231 bold(str(self.hostport)),
2232 blue(mytxt),
2233 ),
2234 importance = 1,
2235 type = "warning",
2236 header = self.output_header
2237 )
2238 mytxt = _("Service issuer")
2239 self.Output.updateProgress(
2240 "[%s:%s] %s: %s" % (
2241 brown(str(self.hostname)),
2242 bold(str(self.hostport)),
2243 blue(mytxt),
2244 self.sock_conn.issuer()
2245 ),
2246 importance = 1,
2247 type = "warning",
2248 header = self.output_header
2249 )
2250 except self.socket.error as e:
2251 if e.errno == 111:
2252 mytxt = "%s: %s, %s: %s" % (_("Cannot connect to"), host, _("on port"), port,)
2253 raise ConnectionError("ConnectionError: %s" % (mytxt,))
2254 else:
2255 raise
2256
2257 if self.ssl:
2258
2259
2260
2261
2262
2263
2264 self.real_sock_conn.setblocking(True)
2265
2266
2267
2268 if hasattr(self.real_sock_conn, 'settimeout'):
2269 self.real_sock_conn.settimeout(self.socket_timeout)
2270
2271 if not self.quiet:
2272 mytxt = _("Successfully connected to host")
2273 self.Output.updateProgress(
2274 "[%s:%s] %s" % (
2275 brown(self.hostname),
2276 bold(str(self.hostport)),
2277 blue(mytxt),
2278 ),
2279 importance = 1,
2280 type = "info",
2281 header = self.output_header
2282 )
2283
2285
2286 if not self.real_sock_conn:
2287 return True
2288
2289 if self.ssl and self.pyopenssl:
2290 self.sock_conn.shutdown()
2291 self.sock_conn.close()
2292 elif self.ssl and not self.pyopenssl:
2293 try:
2294 self.real_sock_conn.shutdown(self.socket.SHUT_RDWR)
2295 except self.socket.error:
2296 pass
2297
2298 sock_conn = self.sock_conn
2299 self.sock_conn = None
2300 real_sock_conn = self.real_sock_conn
2301 self.real_sock_conn = None
2302 try:
2303 real_sock_conn.close()
2304 except self.socket.error:
2305 pass
2306 try:
2307 if sock_conn is not real_sock_conn:
2308 sock_conn.close()
2309 except self.socket.error:
2310 pass
2311 if not self.quiet:
2312 mytxt = _("Successfully disconnected from host")
2313 self.Output.updateProgress(
2314 "[%s:%s] %s" % (
2315 brown(self.hostname),
2316 bold(str(self.hostport)),
2317 blue(mytxt),
2318 ),
2319 importance = 1,
2320 type = "info",
2321 header = self.output_header
2322 )
2323
2324
2325
2326
2327