func main() { flag.Parse() if flag.NArg() != 0 { fmt.Fprintf(os.Stderr, "%s\n", "torrent-magnet: unexpected positional arguments") os.Exit(2) } mi, err := metainfo.Load(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "error reading metainfo from stdin: %s", err) os.Exit(1) } ts := torrent.TorrentSpecFromMetaInfo(mi) m := torrent.Magnet{ InfoHash: ts.InfoHash, Trackers: func() (ret []string) { for _, tier := range ts.Trackers { for _, tr := range tier { ret = append(ret, tr) } } return }(), DisplayName: ts.DisplayName, } fmt.Fprintf(os.Stdout, "%s\n", m.String()) }
// Gives a temporary directory containing the completed "greeting" torrent, // and a corresponding metainfo describing it. The temporary directory can be // cleaned away with os.RemoveAll. func GreetingTestTorrent() (tempDir string, metaInfo *metainfo.MetaInfo) { tempDir, err := ioutil.TempDir(os.TempDir(), "") if err != nil { panic(err) } name := CreateDummyTorrentData(tempDir) w := &bytes.Buffer{} CreateMetaInfo(name, w) metaInfo, _ = metainfo.Load(w) return }
func main() { tagflag.Parse(nil) mi, err := metainfo.Load(os.Stdin) if err != nil { fmt.Fprintf(os.Stderr, "error reading metainfo from stdin: %s", err) os.Exit(1) } fmt.Fprintf(os.Stdout, "%s\n", mi.Magnet().String()) }
func newGreetingLayout() (tl testLayout, err error) { tl.BaseDir, err = ioutil.TempDir("", "torrentfs") if err != nil { return } tl.Completed = filepath.Join(tl.BaseDir, "completed") os.Mkdir(tl.Completed, 0777) tl.MountDir = filepath.Join(tl.BaseDir, "mnt") os.Mkdir(tl.MountDir, 0777) name := testutil.CreateDummyTorrentData(tl.Completed) metaInfoBuf := &bytes.Buffer{} testutil.CreateMetaInfo(name, metaInfoBuf) tl.Metainfo, err = metainfo.Load(metaInfoBuf) return }
func (this *Downloader) metaInfoFromUrl(url string) (metaInfo *metainfo.MetaInfo, err error) { var response = &http.Response{} defer response.Body.Close() response, err = http.Get(url) if err != nil { return } metaInfo, err = metainfo.Load(response.Body) if err != nil { return } return metaInfo, nil }
func (s *Server) api(r *http.Request) error { defer r.Body.Close() if r.Method != "POST" { return fmt.Errorf("Invalid request method (expecting POST)") } action := strings.TrimPrefix(r.URL.Path, "/api/") data, err := ioutil.ReadAll(r.Body) if err != nil { return fmt.Errorf("Failed to download request body") } //convert url into torrent bytes if action == "url" { url := string(data) remote, err := http.Get(url) if err != nil { return fmt.Errorf("Invalid remote torrent URL: %s (%s)", err, url) } //TODO enforce max body size (32k?) data, err = ioutil.ReadAll(remote.Body) if err != nil { return fmt.Errorf("Failed to download remote torrent: %s", err) } action = "torrentfile" } //convert torrent bytes into magnet if action == "torrentfile" { reader := bytes.NewBuffer(data) info, err := metainfo.Load(reader) if err != nil { return err } ts := torrent.TorrentSpecFromMetaInfo(info) trackers := []string{} for _, tier := range ts.Trackers { for _, t := range tier { trackers = append(trackers, t) } } m := torrent.Magnet{ InfoHash: ts.InfoHash, Trackers: trackers, DisplayName: ts.DisplayName, } data = []byte(m.String()) action = "magnet" } //update after action completes defer s.state.Update() //interface with engine switch action { case "configure": c := engine.Config{} if err := json.Unmarshal(data, &c); err != nil { return err } if err := s.reconfigure(c); err != nil { return err } case "magnet": uri := string(data) if err := s.engine.NewTorrent(uri); err != nil { return fmt.Errorf("Magnet error: %s", err) } case "torrent": cmd := strings.SplitN(string(data), ":", 2) if len(cmd) != 2 { return fmt.Errorf("Invalid request") } state := cmd[0] infohash := cmd[1] if state == "start" { if err := s.engine.StartTorrent(infohash); err != nil { return err } } else if state == "stop" { if err := s.engine.StopTorrent(infohash); err != nil { return err } } else if state == "delete" { if err := s.engine.DeleteTorrent(infohash); err != nil { return err } } else { return fmt.Errorf("Invalid state: %s", state) } case "file": cmd := strings.SplitN(string(data), ":", 3) if len(cmd) != 3 { return fmt.Errorf("Invalid request") } state := cmd[0] infohash := cmd[1] filepath := cmd[2] if state == "start" { if err := s.engine.StartFile(infohash, filepath); err != nil { return err } } else if state == "stop" { if err := s.engine.StopFile(infohash, filepath); err != nil { return err } } else { return fmt.Errorf("Invalid state: %s", state) } default: return fmt.Errorf("Invalid action: %s", action) } return nil }
// Add Torrent/Magnet func add(w http.ResponseWriter, r *http.Request) { c := Add{} if e := json.NewDecoder(r.Body).Decode(&c); e != nil { httpd.Error(w, e, "Invalid input.") return } if c.User == "" { httpd.Error(w, nil, "No user.") return } if c.Dir == "" { httpd.Error(w, nil, "No dir.") return } if strings.Contains(c.Dir, "..") { httpd.Error(w, nil, "Dir hack.") return } if _, ok := clients[c.User]; !ok { dlDir := fmt.Sprintf(config.C.Basedir + c.Dir) if _, e := os.Stat(config.C.Basedir); os.IsNotExist(e) { if e := os.Mkdir(dlDir, os.ModeDir); e != nil { config.L.Printf("CRIT: %s", e.Error()) httpd.Error(w, e, "Permission error.") return } } // https://github.com/anacrolix/torrent/blob/master/config.go#L9 cl, e := torrent.NewClient(&torrent.Config{ DataDir: config.C.Basedir + c.Dir, // IPBlocklist => http://john.bitsurge.net/public/biglist.p2p.gz }) if e != nil { httpd.Error(w, e, "Client init failed") return } clients[c.User] = cl } client := clients[c.User] var ( t torrent.Torrent e error ) if len(c.Magnet) > 0 { t, e = client.AddMagnet(c.Magnet) if e != nil { httpd.Error(w, e, "Magnet add failed") return } } else if len(c.Torrent) > 0 { // strip base64 b, e := base64.StdEncoding.DecodeString(c.Torrent) if e != nil { httpd.Error(w, e, "Failed base64 decode torrent input") return } m, e := metainfo.Load(bytes.NewReader(b)) if e != nil { httpd.Error(w, e, "Failed base64 decode torrent input") return } t, e = client.AddTorrent(m) if e != nil { httpd.Error(w, e, "Failed adding torrent") return } } else { httpd.Error(w, nil, "No magnet nor torrent.") return } // queue go func() { <-t.GotInfo() t.DownloadAll() }() // (cl *Client) AddTorrentSpec(spec *TorrentSpec) (T Torrent, new bool, err error) { // TorrentSpecFromMagnetURI(uri string) (spec *TorrentSpec, err error) { // TorrentSpecFromMetaInfo(mi *metainfo.MetaInfo) (spec *TorrentSpec) { // (me *Client) AddMagnet(uri string) (T Torrent, err error) { // (me *Client) AddTorrent(mi *metainfo.MetaInfo) (T Torrent, err error) { msg := fmt.Sprintf(`{"status": true, "hash": "%s", "text": "Queued."}`, t.InfoHash().HexString()) w.Header().Set("Content-Type", "application/json") if _, e := w.Write([]byte(msg)); e != nil { httpd.Error(w, e, "Flush failed") return } }