示例#1
0
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())
}
示例#2
0
// 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
}
示例#3
0
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())
}
示例#4
0
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
}
示例#5
0
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
}
示例#6
0
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
}
示例#7
0
// 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
	}
}