@@ -2,6 +2,8 @@ package tly
22
33import (
44 "context"
5+ "fmt"
6+ "io"
57 "net/http"
68 "strings"
79
@@ -31,38 +33,76 @@ func (s Scanner) Keywords() []string {
3133}
3234
3335// FromData will find and optionally verify TLy secrets in a given set of bytes.
34- func (s Scanner ) FromData (ctx context.Context , verify bool , data []byte ) (results []detectors.Result , err error ) {
35- dataStr := string (data )
36+ func (s Scanner ) FromData (
37+ ctx context.Context ,
38+ verify bool ,
39+ data []byte ,
40+ ) (results []detectors.Result , err error ) {
3641
37- matches := keyPat . FindAllStringSubmatch ( dataStr , - 1 )
42+ dataStr := string ( data )
3843
39- for _ , match := range matches {
40- resMatch := strings .TrimSpace (match [1 ])
44+ uniqueKeys := make (map [string ]struct {})
45+ for _ , match := range keyPat .FindAllStringSubmatch (dataStr , - 1 ) {
46+ uniqueKeys [strings .TrimSpace (match [1 ])] = struct {}{}
47+ }
4148
42- s1 := detectors.Result {
49+ for key := range uniqueKeys {
50+ result := detectors.Result {
4351 DetectorType : detector_typepb .DetectorType_TLy ,
44- Raw : []byte (resMatch ),
45- SecretParts : map [string ]string {"key" : resMatch },
52+ Raw : []byte (key ),
53+ SecretParts : map [string ]string {
54+ "key" : key ,
55+ },
4656 }
4757
4858 if verify {
49- req , err := http .NewRequestWithContext (ctx , "GET" , "https://t.ly/api/v1/link/stats?api_token=" + resMatch + "&short_url=https://t.ly/h9YS" , nil )
50- if err != nil {
51- continue
52- }
53- res , err := client .Do (req )
54- if err == nil {
55- defer func () { _ = res .Body .Close () }()
56- if res .StatusCode >= 200 && res .StatusCode < 300 {
57- s1 .Verified = true
58- }
59- }
59+ verified , verificationErr := verifyTLyKey (ctx , client , key )
60+ result .SetVerificationError (verificationErr , key )
61+ result .Verified = verified
6062 }
6163
62- results = append (results , s1 )
64+ results = append (results , result )
65+ }
66+
67+ return
68+ }
69+
70+ func verifyTLyKey (
71+ ctx context.Context ,
72+ client * http.Client ,
73+ key string ,
74+ ) (bool , error ) {
75+
76+ req , err := http .NewRequestWithContext (
77+ ctx ,
78+ http .MethodGet ,
79+ "https://api.t.ly/api/v1/link/list" ,
80+ http .NoBody ,
81+ )
82+ if err != nil {
83+ return false , err
6384 }
6485
65- return results , nil
86+ req .Header .Set ("Authorization" , "Bearer " + key )
87+ req .Header .Set ("Accept" , "application/json" )
88+
89+ res , err := client .Do (req )
90+ if err != nil {
91+ return false , err
92+ }
93+ defer func () {
94+ _ , _ = io .Copy (io .Discard , res .Body )
95+ _ = res .Body .Close ()
96+ }()
97+
98+ switch res .StatusCode {
99+ case http .StatusOK :
100+ return true , nil
101+ case http .StatusUnauthorized , http .StatusForbidden :
102+ return false , nil
103+ default :
104+ return false , fmt .Errorf ("unexpected HTTP response status %d" , res .StatusCode )
105+ }
66106}
67107
68108func (s Scanner ) Type () detector_typepb.DetectorType {
0 commit comments