Skip to content

Commit

Permalink
chore: another refactor.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitsper2nd committed Apr 1, 2024
1 parent 8e00600 commit c05693b
Showing 1 changed file with 139 additions and 149 deletions.
288 changes: 139 additions & 149 deletions generate/idcac/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,190 +22,177 @@ import (
"github.com/xarantolus/jsonextract"
)

func readVersion(extBaseDir string) (s string, err error) {
type VersionInfo struct {
Version string `json:"version"`
}

func readVersion(extBaseDir string) (string, error) {
f, err := os.Open(filepath.Join(extBaseDir, "manifest.json"))
if err != nil {
return
return "", err
}
defer f.Close()

type vinfo struct {
Version string `json:"version"`
var vinfo VersionInfo
err = json.NewDecoder(f).Decode(&vinfo)

return vinfo.Version, err
}

func toJSONString(obj interface{}) string {
s, err := json.Marshal(obj)
if err != nil {
log.Fatalf("failed to marshal object to JSON string: %s\n", err.Error())
}
return string(s)
}

i := new(vinfo)
err = json.NewDecoder(f).Decode(i)
func isCommons(m map[string]interface{}) bool {
for k := range m {
_, numerr := strconv.Atoi(k)
if numerr != nil {
return false
}
}
return true
}

return i.Version, err
func isRules(m map[string]interface{}) bool {
for k := range m {
if !strings.ContainsRune(k, '.') {
return false
}
}
return true
}

func mapFunctions(fnts map[int]string) string {
var sb strings.Builder
sb.WriteString("{")

var keys []int
for key := range fnts {
keys = append(keys, key)
}
sort.Ints(keys)

for i, key := range keys {
sb.WriteString(toJSONString(strconv.Itoa(key)))
sb.WriteString(": (function () {")
sb.WriteString(fnts[key])
sb.WriteString("})")

if i != len(keys)-1 {
sb.WriteString(",")
}
}
sb.WriteString("}")

return sb.String()
}

func hashFile(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()

h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return "", err
}

return fmt.Sprintf("%x", h.Sum(nil)), nil
}

const (
extensionURL = "https://addons.mozilla.org/en/firefox/addon/istilldontcareaboutcookies/"
licenseHashCheck = "9ab30fb6fc1e6366fa1dda7231d6424893c3c77a48a6b68309bbcbcd1eaeeb16"
)

func main() {
var (
scriptTarget = flag.String("output", "idcac.user.js", "Path to output file")
)
var scriptTarget = flag.String("output", "idcac.user.js", "Path to output file")
flag.Parse()

// Read script template content
scriptTemplateContent, err := ioutil.ReadFile("script-template.js")
if err != nil {
log.Fatalf("reading script template file: %s\n", err.Error())
log.Fatalf("failed to read script template file: %s\n", err.Error())
}
scriptTemplate := template.Must(template.New("").Parse(string(scriptTemplateContent)))

// Scraping extension info
extensionURL := "https://addons.mozilla.org/en/firefox/addon/istilldontcareaboutcookies/"
extensionInfo, err := amo.ScrapeInfo(extensionURL)
if err != nil {
log.Fatalf("scraping idcac extension info: %s\n", err.Error())
log.Fatalf("failed to scrape extension info: %s\n", err.Error())
}

// Creating temporary directory for extension
extensionBaseDir, err := ioutil.TempDir("", "idcac-extension-*")
if err != nil {
log.Fatalf("creating temporary directory for idcac extension: %s\n", err.Error())
log.Fatalf("failed to create temporary directory for extension: %s\n", err.Error())
}
defer os.RemoveAll(extensionBaseDir)

// Downloading extension zip file
extStream, cancel, err := amo.DownloadFile(extensionInfo.URL)
defer cancel()
if err != nil {
log.Fatalf("downloading extension zip file: %s\n", err.Error())
log.Fatalf("failed to download extension zip file: %s\n", err.Error())
}
defer extStream.Close()

// Extracting extension zip
err = extract.Zip(extStream, extensionBaseDir)
if err != nil {
log.Fatalf("extracting extension zip: %s\n", err.Error())
log.Fatalf("failed to extract extension zip: %s\n", err.Error())
}

// Hashing license file
licenseHash, err := hashFile(filepath.Join(extensionBaseDir, "LICENSE"))
if err != nil {
log.Fatalf("cannot hash license file: %s\n", err.Error())
log.Fatalf("failed to hash license file: %s\n", err.Error())
}

// Matching license hash
expectedLicenseHash := "9ab30fb6fc1e6366fa1dda7231d6424893c3c77a48a6b68309bbcbcd1eaeeb16"
if licenseHash != expectedLicenseHash {
if licenseHash != licenseHashCheck {
log.Fatalf("license hash does not match: %s\n", licenseHash)
}
log.Println("License hash matches")

// Opening rules file
rulesFile, err := os.Open(filepath.Join(extensionBaseDir, "data/rules.json"))
rulesFile := filepath.Join(extensionBaseDir, "data/rules.js")
rulesContent, err := ioutil.ReadFile(rulesFile)
if err != nil {
log.Fatalf("open rules file from extension: %s\n", err.Error())
log.Fatalf("failed to read rules file: %s\n", err.Error())
}
defer rulesFile.Close()

var (
commons string
rules string
javascriptFixes = make(map[int]string)
)
var commons, rules string
var javascriptFixes = make(map[int]string)

// Reading and processing rules file
err = processRulesFile(rulesFile, func(data map[string]interface{}) error {
if isCommons(data) {
commons = toJSONString(data)
} else if isRules(data) {
rules = toJSONString(data)
}
return nil
})
if err != nil {
log.Fatalf("reading/converting rules file: %s\n", err.Error())
}

// Additional processing or actions as needed
}

// processRulesFile reads and processes rules file line by line
func processRulesFile(file *os.File, handler func(data map[string]interface{}) error) error {
reader := bufio.NewReader(file)
for {
line, err := reader.ReadBytes('\n')
if err != nil {
if err == io.EOF {
break
}
return err
}
err = jsonextract.Reader(strings.NewReader(string(rulesContent)), func(b []byte) error {
var data map[string]interface{}
err = json.Unmarshal(line, &data)
if err != nil {
if err := json.Unmarshal(b, &data); err != nil {
return err
}
err = handler(data)
if err != nil {
return err
}
}
return nil
}

// isRules checks if the data contains required keys for rules
func isRules(data map[string]interface{}) bool {
requiredKeys := []string{"manifest_version", "version", "background"}
for _, key := range requiredKeys {
if _, exists := data[key]; !exists {
return false
}
}
return true
}

// isCommons checks if the data contains required keys for commons
func isCommons(data map[string]interface{}) bool {
requiredKeys := []string{"key1", "key2", "key3"} // Add required keys for commons
for _, key := range requiredKeys {
if _, exists := data[key]; !exists {
return false
if isCommons(data) {
commons = string(b)
} else if isRules(data) {
rules = string(b)
}
}
return true
}

// toJSONString converts data to JSON string
func toJSONString(data map[string]interface{}) string {
b, err := json.Marshal(data)
if err != nil {
return ""
}
return string(b)
}

// hashFile generates sha256 hash for a file
func hashFile(path string) (string, error) {
f, err := os.Open(path)
return nil
})
if err != nil {
return "", err
}
defer f.Close()

h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return "", err
log.Fatalf("failed to read/converting rules file: %s\n", err.Error())
}

return fmt.Sprintf("%x", h.Sum(nil)), nil
}

cookieBlockCSSBytes, err := ioutil.ReadFile(filepath.Join(extensionBaseDir, "data/css/common.css"))
cookieBlockCSSFile := filepath.Join(extensionBaseDir, "data/css/common.css")
cookieBlockCSSBytes, err := ioutil.ReadFile(cookieBlockCSSFile)
if err != nil {
log.Fatalf("Error reading common css rules: %s\n", err.Error())
log.Fatalf("failed to read common css rules: %s\n", err.Error())
}
cookieBlockCSS = string(cookieBlockCSSBytes)
cookieBlockCSS := string(cookieBlockCSSBytes)

err = filepath.Walk(filepath.Join(extensionBaseDir, "data/js"), func(path string, d os.FileInfo, err error) error {
if err != nil || d.IsDir() {
return err
}

var base = filepath.Base(path)

var number int

_, err = fmt.Sscanf(base, "common%d.js", &number)
Expand All @@ -215,47 +202,50 @@ func hashFile(path string) (string, error) {

fileContent, err := ioutil.ReadFile(path)
if err != nil {
return fmt.Errorf("reading common javascript fix file: %w", err)
return fmt.Errorf("failed to read common javascript fix file: %w", err)
}

javascriptFixes[number] = strings.TrimSpace(string(fileContent))

return nil
})

extensionVersion, err := readVersion(extensionBaseDir)
if err != nil {
extensionVersion = "(unknown)"
log.Fatalf("failed to read javascript fix files: %s\n", err.Error())
}

if len(commons) == 0 || len(rules) == 0 || len(javascriptFixes) == 0 {
log.Fatalf("Unexpected lengths of commons(%d)/rules(%d)/javascriptFixes(%d) -- expected at least one of each", len(commons), len(rules), len(javascriptFixes))
}
extensionVersion, err := readVersion(extensionBaseDir)
if err != nil {
extensionVersion = "(unknown)"
}

outputFile, err := os.Create(*scriptTarget)
if err != nil {
log.Fatalf("creating output file: %s\n", err.Error())
}
if len(commons) == 0 || len(rules) == 0 || len(javascriptFixes) == 0 {
log.Fatalf("Unexpected lengths of commons(%d)/rules(%d)/javascriptFixes(%d) -- expected at least one of each", len(commons), len(rules), len(javascriptFixes))
}

_, err = outputFile.WriteString("// THIS FILE IS AUTO-GENERATED. DO NOT EDIT. See generate/idcac directory for more info\n")
if err != nil {
log.Fatalf("could not write auto generated message: %s\n", err.Error())
}
outputFile, err := os.Create(*scriptTarget)
if err != nil {
log.Fatalf("creating output file: %s\n", err.Error())
}
defer outputFile.Close()

err = scriptTemplate.Execute(outputFile, map[string]string{
"version": time.Now().Format("2006.01.02"),
"commons": commons,
"rules": rules,
"javascriptFixes": mapFunctions(javascriptFixes),
"cookieBlockCSS": toJSString(cookieBlockCSS),
"statistics": fmt.Sprintf("generated from version `%s` available at %s", extensionVersion, extensionURL),
})
if err != nil {
log.Fatalf("Error generating script text: %s\n", err.Error())
}
_, err = outputFile.WriteString("// THIS FILE IS AUTO-GENERATED. DO NOT EDIT. See generate/idcac directory for more info\n")
if err != nil {
log.Fatalf("could not write auto generated message: %s\n", err.Error())
}

err = outputFile.Close()
if err != nil {
log.Fatalf("could not close output file: %s\n", err.Error())
}
}
generatedTime := time.Now().Format("2006.01.02")
statistics := fmt.Sprintf("generated from version `%s` available at %s", extensionVersion, extensionURL)

err = scriptTemplate.Execute(outputFile, map[string]string{
"version": generatedTime,
"commons": commons,
"rules": rules,
"javascriptFixes": mapFunctions(javascriptFixes),
"cookieBlockCSS": toJSString(cookieBlockCSS),
"statistics": statistics,
})
if err != nil {
log.Fatalf("Error generating script text: %s\n", err.Error())
}

log.Printf("Script generated successfully with version %s\n", generatedTime)

0 comments on commit c05693b

Please sign in to comment.