Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

# -*- coding: utf-8 -*- 

# 

# Original file from BitTorrent-5.3-GPL.tar.gz 

# Copyright (C) Bram Cohen 

# 

# Modifications for use in Deluge: 

# Copyright (C) 2007 Andrew Resch <andrewresch@gmail.com> 

# 

# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with 

# the additional special exception to link portions of this program with the OpenSSL library. 

# See LICENSE for more details. 

# 

 

import logging 

import os.path 

import sys 

import time 

from hashlib import sha1 as sha 

 

import deluge.component as component 

from deluge.bencode import bencode 

from deluge.event import CreateTorrentProgressEvent 

 

log = logging.getLogger(__name__) 

 

ignore = ['core', 'CVS', 'Thumbs.db', 'desktop.ini'] 

 

noncharacter_translate = {} 

for i in xrange(0xD800, 0xE000): 

    noncharacter_translate[i] = ord('-') 

for i in xrange(0xFDD0, 0xFDF0): 

    noncharacter_translate[i] = ord('-') 

for i in (0xFFFE, 0xFFFF): 

    noncharacter_translate[i] = ord('-') 

 

 

def gmtime(): 

    return time.mktime(time.gmtime()) 

 

 

def get_filesystem_encoding(): 

    return sys.getfilesystemencoding() 

 

 

def decode_from_filesystem(path): 

    encoding = get_filesystem_encoding() 

    if encoding is None: 

        assert isinstance(path, unicode), "Path should be unicode not %s" % type(path) 

        decoded_path = path 

    else: 

        assert isinstance(path, str), "Path should be str not %s" % type(path) 

        decoded_path = path.decode(encoding) 

 

    return decoded_path 

 

 

def dummy(*v): 

    pass 

 

 

class RemoteFileProgress(object): 

    def __init__(self, session_id): 

        self.session_id = session_id 

 

    def __call__(self, piece_count, num_pieces): 

        component.get("RPCServer").emit_event_for_session_id( 

            self.session_id, CreateTorrentProgressEvent(piece_count, num_pieces) 

        ) 

 

 

def make_meta_file(path, url, piece_length, progress=None, title=None, comment=None, 

                   safe=None, content_type=None, target=None, webseeds=None, name=None, 

                   private=False, created_by=None, trackers=None): 

    data = {'creation date': int(gmtime())} 

    if url: 

        data['announce'] = url.strip() 

    a, b = os.path.split(path) 

    if not target: 

        if b == '': 

            f = a + '.torrent' 

        else: 

            f = os.path.join(a, b + '.torrent') 

    else: 

        f = target 

 

    if progress is None: 

        session_id = component.get("RPCServer").get_session_id() 

        if not session_id: 

            progress = dummy 

        else: 

            progress = RemoteFileProgress(component.get("RPCServer").get_session_id()) 

 

    info = makeinfo(path, piece_length, progress, name, content_type, private) 

 

    # check_info(info) 

    h = file(f, 'wb') 

 

    data['info'] = info 

    if title: 

        data['title'] = title.encode("utf8") 

    if comment: 

        data['comment'] = comment.encode("utf8") 

    if safe: 

        data['safe'] = safe.encode("utf8") 

 

    httpseeds = [] 

    url_list = [] 

 

    if webseeds: 

        for webseed in webseeds: 

            if webseed.endswith(".php"): 

                httpseeds.append(webseed) 

            else: 

                url_list.append(webseed) 

 

    if url_list: 

        data['url-list'] = url_list 

    if httpseeds: 

        data['httpseeds'] = httpseeds 

    if created_by: 

        data['created by'] = created_by.encode("utf8") 

 

    if trackers and (len(trackers[0]) > 1 or len(trackers) > 1): 

        data['announce-list'] = trackers 

 

    data["encoding"] = "UTF-8" 

 

    h.write(bencode(data)) 

    h.close() 

 

 

def calcsize(path): 

    total = 0 

    for s in subfiles(os.path.abspath(path)): 

        total += os.path.getsize(s[1]) 

    return total 

 

 

def makeinfo(path, piece_length, progress, name=None, content_type=None, private=False): 

    # HEREDAVE. If path is directory, how do we assign content type? 

    def to_utf8(name): 

        if isinstance(name, unicode): 

            u = name 

        else: 

            try: 

                u = decode_from_filesystem(name) 

            except Exception: 

                raise Exception('Could not convert file/directory name %r to ' 

                                'Unicode. Either the assumed filesystem ' 

                                'encoding "%s" is wrong or the filename contains ' 

                                'illegal bytes.' % (name, get_filesystem_encoding())) 

 

        if u.translate(noncharacter_translate) != u: 

            raise Exception('File/directory name "%s" contains reserved ' 

                            'unicode values that do not correspond to ' 

                            'characters.' % name) 

        return u.encode('utf-8') 

    path = os.path.abspath(path) 

    piece_count = 0 

    if os.path.isdir(path): 

        subs = subfiles(path) 

        subs.sort() 

        pieces = [] 

        sh = sha() 

        done = 0 

        fs = [] 

        totalsize = 0.0 

        totalhashed = 0 

        for p, f in subs: 

            totalsize += os.path.getsize(f) 

        if totalsize >= piece_length: 

            import math 

            num_pieces = math.ceil(float(totalsize) / float(piece_length)) 

        else: 

            num_pieces = 1 

 

        for p, f in subs: 

            pos = 0 

            size = os.path.getsize(f) 

            p2 = [to_utf8(n) for n in p] 

            if content_type: 

                fs.append({'length': size, 'path': p2, 

                           'content_type': content_type})  # HEREDAVE. bad for batch! 

            else: 

                fs.append({'length': size, 'path': p2}) 

            h = file(f, 'rb') 

            while pos < size: 

                a = min(size - pos, piece_length - done) 

                sh.update(h.read(a)) 

                done += a 

                pos += a 

                totalhashed += a 

 

                if done == piece_length: 

                    pieces.append(sh.digest()) 

                    piece_count += 1 

                    done = 0 

                    sh = sha() 

                    progress(piece_count, num_pieces) 

            h.close() 

        if done > 0: 

            pieces.append(sh.digest()) 

            piece_count += 1 

            progress(piece_count, num_pieces) 

 

        if name is not None: 

            assert isinstance(name, unicode) 

            name = to_utf8(name) 

        else: 

            name = to_utf8(os.path.split(path)[1]) 

 

        return {'pieces': ''.join(pieces), 

                'piece length': piece_length, 

                'files': fs, 

                'name': name, 

                'private': private} 

    else: 

        size = os.path.getsize(path) 

        if size >= piece_length: 

            num_pieces = size / piece_length 

        else: 

            num_pieces = 1 

 

        pieces = [] 

        p = 0 

        h = file(path, 'rb') 

        while p < size: 

            x = h.read(min(piece_length, size - p)) 

            pieces.append(sha(x).digest()) 

            piece_count += 1 

            p += piece_length 

            if p > size: 

                p = size 

            progress(piece_count, num_pieces) 

        h.close() 

        if content_type is not None: 

            return {'pieces': ''.join(pieces), 

                    'piece length': piece_length, 'length': size, 

                    'name': to_utf8(os.path.split(path)[1]), 

                    'content_type': content_type, 

                    'private': private} 

        return {'pieces': ''.join(pieces), 

                'piece length': piece_length, 'length': size, 

                'name': to_utf8(os.path.split(path)[1]), 

                'private': private} 

 

 

def subfiles(d): 

    r = [] 

    stack = [([], d)] 

    while stack: 

        p, n = stack.pop() 

        if os.path.isdir(n): 

            for s in os.listdir(n): 

                if s not in ignore and not s.startswith('.'): 

                    stack.append((p + [s], os.path.join(n, s))) 

        else: 

            r.append((p, n)) 

    return r