func lstorrent(path string) { fmt.Printf("%s\n", path) defer fmt.Printf("\n") f, err := os.OpenFile(path, os.O_RDONLY, 0600) if err != nil { fmt.Printf("Failed opening file: ", err) return } defer f.Close() datb, err := bencode.Decode(f) if err != nil { fmt.Printf("Failed decoding:", err) return } tor_info, ok := datb["info"].(map[string]interface{}) if !ok { } // first look for files key files, ok := tor_info["files"].([]interface{}) if ok { for _, v := range files { file := v.(map[string]interface{}) path := file["path"].([]interface{})[0].(string) fmt.Printf("%s\n", path) } return // finished printing multifile torrent } // second look for name key file, ok := tor_info["name"].(string) if ok { fmt.Printf("%s\n", file) return } fmt.Printf("couldnt find files in torrent: %s", path) }
//New creates new torrent func New(fileName string) *MetainfoFile { file, err := os.Open(fileName) if err != nil { log.Print("Opening file err: ", err) return nil } defer file.Close() encodedTorrent, err := bencode.Decode(file) if err != nil { log.Print("Decoding torrent err: ", err) return nil } encodedInfo := encodedTorrent["info"].(map[string]interface{}) //Parse File element files := []fileDict{} if length, ok := encodedInfo["length"].(int64); ok { //Single File Mode files = append(files, fileDict{ length: length, path: []string{encodedInfo["name"].(string)}, md5sum: getFromMapWithDefault(encodedTorrent, "md5sum", "").(string), }) } else { //Multi File Mode for _, encodedFileElement := range encodedInfo["files"].([]interface{}) { encodedFile := encodedFileElement.(map[string]interface{}) encodedPath := []string{} for _, encodedPathElement := range encodedFile["path"].([]interface{}) { encodedPath = append(encodedPath, encodedPathElement.(string)) } files = append(files, fileDict{ length: encodedFile["length"].(int64), path: encodedPath, md5sum: getFromMapWithDefault(encodedTorrent, "md5sum", "").(string), }) } } //Parse Announce List (arrays of arrays of strings announceList := [][]string{} if encodedAnnounceList, ok := encodedTorrent["announce-list"]; ok { for _, encodedAnnounceListElement := range encodedAnnounceList.([]interface{}) { announceListElement := []string{} for _, encodedAnnounceListElementElement := range encodedAnnounceListElement.([]interface{}) { announceListElement = append(announceListElement, encodedAnnounceListElementElement.(string)) } announceList = append(announceList, announceListElement) } } return &MetainfoFile{ info: infoDict{ name: encodedInfo["name"].(string), pieceLength: encodedInfo["piece length"].(int64), pieces: encodedInfo["pieces"].(string), files: files, }, announce: encodedTorrent["announce"].(string), announceList: announceList, comment: getFromMapWithDefault(encodedTorrent, "comment", "").(string), private: getFromMapWithDefault(encodedTorrent, "private", false).(bool), } }
func (torrent *Torrent) open(filename string) error { file, err := os.Open(filename) if err != nil { return err } defer file.Close() data, err := bencode.Decode(file) if err != nil { return err } if announceLists, ok := data["announce-list"].([]interface{}); ok { for _, announceList := range announceLists { for _, announceURL := range announceList.([]interface{}) { torrent.parseTrackerURL(announceURL.(string)) } } } else { torrent.parseTrackerURL(data["announce"].(string)) } if comment, ok := data["comment"]; ok { torrent.comment = comment.(string) } info := data["info"].(map[string]interface{}) torrent.name = info["name"].(string) torrent.pieceLength = info["piece length"].(int64) infoHash := sha1.Sum(bencode.Encode(info)) // Set handshake var buffer bytes.Buffer buffer.WriteByte(19) // length of the string "BitTorrent Protocol" buffer.WriteString("BitTorrent protocol") buffer.WriteString("\x00\x00\x00\x00\x00\x00\x00\x00") // reserved buffer.Write(infoHash[:]) buffer.Write(client.peerID) torrent.handshake = buffer.Bytes() // Set pieces pieces := info["pieces"].(string) for i := 0; i < len(pieces); i += 20 { torrent.pieces = append(torrent.pieces, TorrentPiece{ hash: pieces[i : i+20], }) } if err := os.Mkdir("Downloads", 0700); err != nil && !os.IsExist(err) { return err } cwd, err := os.Getwd() if err != nil { return err } base := filepath.Join(cwd, "Downloads") // Set files if files, exists := info["files"]; exists { dirName := filepath.Join("Downloads", info["name"].(string)) if err := torrent.validatePath(base, dirName); err != nil { return err } base := filepath.Join(cwd, dirName) for _, v := range files.([]interface{}) { v := v.(map[string]interface{}) torrent.totalSize += v["length"].(int64) } // Multiple files var begin int64 for k, v := range files.([]interface{}) { v := v.(map[string]interface{}) // Set up directory structure pathList := v["path"].([]interface{}) pathElements := []string{dirName} for i := 0; i < len(pathList)-1; i++ { pathElements = append(pathElements, pathList[i].(string)) } path := filepath.Join(pathElements...) fullPath := filepath.Join(path, pathList[len(pathList)-1].(string)) if err := torrent.validatePath(base, fullPath); err != nil { return err } if len(path) != 0 { if err := os.MkdirAll(path, 0700); err != nil { return err } } length := v["length"].(int64) file, err := os.OpenFile(fullPath, os.O_RDWR, 0600) if err == nil { torrent.findCompletedPieces(file, begin, length, k) file.Close() } torrent.files = append(torrent.files, File{fullPath, begin, length}) begin += length } } else { // Single file fileName := filepath.Join("Downloads", info["name"].(string)) if err := torrent.validatePath(base, fileName); err != nil { return err } length := info["length"].(int64) torrent.totalSize = length file, err := os.OpenFile(fileName, os.O_RDWR, 0600) if err == nil { torrent.findCompletedPieces(file, 0, length, 0) file.Close() } torrent.files = []File{{fileName, 0, length}} } return nil }