├── .editorconfig
├── .github
├── CODEOWNERS
├── dependabot.yml
├── labels.yml
└── workflows
│ ├── build.yml
│ ├── labels.yml
│ └── released.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── assets
└── assets.go
├── build.properties
├── build.xml
├── go.mod
├── go.sum
├── main.go
├── mozlz4.go
├── res
├── FirefoxDeveloperEdition.lnk
├── app.ico
├── papp.ico
├── papp.manifest
├── papp.png
├── run.iss
└── setup-mini.bmp
└── tools
└── tools.go
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs.
2 | # More information at http://editorconfig.org
3 |
4 | root = true
5 |
6 | [*]
7 | charset = utf-8
8 | indent_size = 2
9 | indent_style = space
10 | end_of_line = lf
11 | insert_final_newline = true
12 | trim_trailing_whitespace = true
13 |
14 | [*.md]
15 | trim_trailing_whitespace = false
16 |
17 | [*.go]
18 | indent_style = tab
19 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @crazy-max
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "gomod"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 | time: "08:00"
8 | timezone: "Europe/Paris"
9 | labels:
10 | - ":game_die: dependencies"
11 | - ":robot: bot"
12 | - package-ecosystem: "github-actions"
13 | directory: "/"
14 | schedule:
15 | interval: "daily"
16 | time: "08:00"
17 | timezone: "Europe/Paris"
18 | labels:
19 | - ":game_die: dependencies"
20 | - ":robot: bot"
21 |
--------------------------------------------------------------------------------
/.github/labels.yml:
--------------------------------------------------------------------------------
1 | ## more info https://github.com/crazy-max/ghaction-github-labeler
2 | - # bot
3 | name: ":robot: bot"
4 | color: "69cde9"
5 | description: ""
6 | - # broken
7 | name: ":zap: broken"
8 | color: "a3090e"
9 | description: ""
10 | - # bug
11 | name: ":bug: bug"
12 | color: "b60205"
13 | description: ""
14 | - # dependencies
15 | name: ":game_die: dependencies"
16 | color: "0366d6"
17 | description: ""
18 | - # documentation
19 | name: ":memo: documentation"
20 | color: "c5def5"
21 | description: ""
22 | - # duplicate
23 | name: ":busts_in_silhouette: duplicate"
24 | color: "cccccc"
25 | description: ""
26 | - # enhancement
27 | name: ":sparkles: enhancement"
28 | color: "0054ca"
29 | description: ""
30 | - # feature request
31 | name: ":bulb: feature request"
32 | color: "0e8a16"
33 | description: ""
34 | - # feedback
35 | name: ":mega: feedback"
36 | color: "03a9f4"
37 | description: ""
38 | - # future maybe
39 | name: ":rocket: future maybe"
40 | color: "fef2c0"
41 | description: ""
42 | - # good first issue
43 | name: ":hatching_chick: good first issue"
44 | color: "7057ff"
45 | description: ""
46 | - # help wanted
47 | name: ":pray: help wanted"
48 | color: "4caf50"
49 | description: ""
50 | - # hold
51 | name: ":hand: hold"
52 | color: "24292f"
53 | description: ""
54 | - # invalid
55 | name: ":no_entry_sign: invalid"
56 | color: "e6e6e6"
57 | description: ""
58 | - # maybe bug
59 | name: ":interrobang: maybe bug"
60 | color: "ff5722"
61 | description: ""
62 | - # needs more info
63 | name: ":thinking: needs more info"
64 | color: "795548"
65 | description: ""
66 | - # question
67 | name: ":question: question"
68 | color: "3f51b5"
69 | description: ""
70 | - # trademark violation
71 | name: ":construction: trademark violation"
72 | color: "cfe524"
73 | description: ""
74 | - # upstream
75 | name: ":eyes: upstream"
76 | color: "fbca04"
77 | description: ""
78 | - # wontfix
79 | name: ":coffin: wontfix"
80 | color: "ffffff"
81 | description: ""
82 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | tags:
7 | - '*'
8 | pull_request:
9 |
10 | jobs:
11 | build:
12 | uses: portapps/.github/.github/workflows/app-build.yml@master
13 |
--------------------------------------------------------------------------------
/.github/workflows/labels.yml:
--------------------------------------------------------------------------------
1 | name: labels
2 |
3 | on:
4 | push:
5 | branches:
6 | - 'master'
7 | paths:
8 | - '.github/labels.yml'
9 | - '.github/workflows/labels.yml'
10 |
11 | jobs:
12 | labeler:
13 | runs-on: ubuntu-latest
14 | steps:
15 | -
16 | name: Checkout
17 | uses: actions/checkout@v4
18 | -
19 | name: Run Labeler
20 | uses: crazy-max/ghaction-github-labeler@v5
21 |
--------------------------------------------------------------------------------
/.github/workflows/released.yml:
--------------------------------------------------------------------------------
1 | name: released
2 |
3 | on:
4 | release:
5 | types: [published]
6 |
7 | jobs:
8 | virustotal:
9 | uses: portapps/.github/.github/workflows/app-virustotal.yml@master
10 | secrets:
11 | vt_api_key: ${{ secrets.VT_API_KEY }}
12 | vt_monitor_api_key: ${{ secrets.VT_MONITOR_API_KEY }}
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Intellij
2 | /.idea
3 | /*.iml
4 |
5 | # App
6 | /.dev
7 | /bin
8 | /vendor
9 | /*.syso
10 | /*.exe
11 | /versioninfo.json
12 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## 138.0b3-52 (2025/04/06)
4 |
5 | * Firefox Developer Edition 138.0b3
6 | * Portapps 3.16.0
7 |
8 | ## 133.0b7-51 (2024/11/12)
9 |
10 | * Firefox Developer Edition 133.0b7
11 | * Portapps 3.15.0
12 |
13 | ## 126.0b9-50 (2024/05/05)
14 |
15 | * Firefox Developer Edition 126.0b9
16 | * Portapps 3.10.0
17 |
18 | ## 122.0b3-49 (2023/12/25)
19 |
20 | * Firefox Developer Edition 122.0b3
21 | * Portapps 3.9.0
22 |
23 | ## 115.0b9-48 (2023/07/03)
24 |
25 | * Firefox Developer Edition 115.0b9
26 | * Portapps 3.8.0
27 |
28 | ## 110.0b9-47 (2023/02/12)
29 |
30 | * Firefox Developer Edition 110.0b9
31 | * Portapps 3.7.0
32 |
33 | ## 106.0b7-46 (2022/10/04)
34 |
35 | * Firefox Developer Edition 106.0b7
36 | * Portapps 3.6.0
37 | * Bump github.com/kevinburke/go-bindata
38 |
39 | ## 101.0b9-45 (2022/05/22)
40 |
41 | * Firefox Developer Edition 101.0b9
42 | * Portapps 3.5.0
43 | * Bump github.com/kevinburke/go-bindata (#47)
44 | * Bump github.com/pierrec/lz4/v3 from 3.3.4 to 3.3.5 (#53)
45 |
46 | ## 97.0b8-44 (2022/01/27)
47 |
48 | * Firefox Developer Edition 97.0b8
49 | * Portapps 3.4.0
50 |
51 | ## 93.0b6-43 (2021/07/25)
52 |
53 | * Firefox Developer Edition 93.0b6
54 | * Portapps 3.3.1
55 |
56 | ## 91.0b6-42 (2021/07/25)
57 |
58 | * Firefox Developer Edition 91.0b6
59 |
60 | ## 89.0b15-41 (2021/05/22)
61 |
62 | * Firefox Developer Edition 89.0b15
63 |
64 | ## 88.0b5-40 (2021/04/04)
65 |
66 | * Firefox Developer Edition 88.0b5
67 | * Portapps 3.3.0
68 | * No more win32 release
69 |
70 | ## 86.0b5-39 (2021/02/06)
71 |
72 | * Firefox Developer Edition 86.0b5
73 | * Portapps 3.1.0
74 |
75 | ## 84.0b8-38 (2020/12/07)
76 |
77 | * Firefox Developer Edition 84.0b8
78 | * Portapps 3.0.3
79 |
80 | ## 83.0b5-37 (2020/10/28)
81 |
82 | * Firefox Developer Edition 83.0b5
83 |
84 | ## 82.0b2-36 (2020/09/29)
85 |
86 | * Firefox Developer Edition 82.0b2
87 |
88 | ## 81.0b1-35 (2020/08/24)
89 |
90 | * Firefox Developer Edition 81.0b1
91 | * Portapps 2.6.0
92 |
93 | ## 80.0b2-34 (2020/07/31)
94 |
95 | * Firefox Developer Edition 80.0b2
96 |
97 | ## 79.0b5-33 (2020/07/08)
98 |
99 | * Firefox Developer Edition 79.0b5
100 |
101 | ## 78.0b6-32 (2020/06/13)
102 |
103 | * Firefox Developer Edition 78.0b6
104 |
105 | ## 77.0b3-31 (2020/05/29)
106 |
107 | * Fix addons startup (portapps/phyrox-portable#3)
108 | * Portapps 2.4.4
109 |
110 | ## 77.0b3-30 (2020/05/10)
111 |
112 | * Firefox Developer Edition 77.0b3
113 | * Allow custom `policies.json`
114 | * `DisableTelemetry` and `DisableFirefoxStudies` removed (use policies file instead)
115 | * Portapps 2.2.4
116 |
117 | ## 76.0b6-29 (2020/04/21)
118 |
119 | * Firefox Developer Edition 76.0b6
120 | * Portapps 2.1.2
121 |
122 | ## 75.0b7-28 (2020/03/25)
123 |
124 | * Firefox Developer Edition 75.0b7
125 | * Add `cleanup` config
126 | * Portapps 1.31.0
127 |
128 | ## 74.0b3-27 (2020/02/14)
129 |
130 | * Firefox Developer Edition 74.0b3
131 |
132 | ## 72.0b2-26 (2019/12/03)
133 |
134 | * Firefox Developer Edition 72.0b2
135 |
136 | ## 71.0b12-25 (2019/12/01)
137 |
138 | * Firefox Developer Edition 71.0b12
139 |
140 | ## 71.0b5-24 (2019/12/01)
141 |
142 | * Following a trademark violation report (#5), name and logo have been changed
143 | * Portapps 1.30.1
144 |
145 | ## 71.0b5-23 (2019/10/29)
146 |
147 | * Firefox Developer Edition 71.0b5
148 | * Update Firefox logo
149 |
150 | ## 71.0b1-22 (2019/10/16)
151 |
152 | * Firefox Developer Edition 71.0b1
153 |
154 | ## 70.0b12-21 (2019/10/08)
155 |
156 | * Firefox Developer Edition 70.0b12
157 | * Portapps 1.28.0
158 |
159 | ## 70.0b6-20 (2019/09/13)
160 |
161 | * Firefox Developer Edition 70.0b6
162 | * Fix addons disabled on startup (#1)
163 | * Portapps 1.26.1
164 |
165 | ## 70.0b2-19 (2019/09/02)
166 |
167 | * Firefox Developer Edition 70.0b2
168 |
169 | ## 69.0b16-18 (2019/09/02)
170 |
171 | * Firefox Developer Edition 69.0b16
172 | * Portapps 1.26.0
173 |
174 | ## 69.0b11-17 (2019/08/07)
175 |
176 | * Firefox Developer Edition 69.0b11
177 | * Portapps 1.25.0
178 |
179 | ## 69.0b4-16 (2019/07/12)
180 |
181 | * Firefox Developer Edition 69.0b4
182 |
183 | ## 69.0b1-15 (2019/07/02)
184 |
185 | * Firefox Developer Edition 69.0b1
186 |
187 | ## 68.0b13-14 (2019/06/26)
188 |
189 | * Firefox Developer Edition 68.0b13
190 |
191 | ## 68.0b10-13 (2019/06/16)
192 |
193 | * Firefox Developer Edition 68.0b10
194 |
195 | ## 68.0b7-12 (2019/06/06)
196 |
197 | * Firefox Developer Edition 68.0b7
198 | * Extensions break on path change (portapps/firefox-portable#2)
199 |
200 | ## 68.0b6-11 (2019/06/02)
201 |
202 | * Firefox Developer Edition 68.0b6
203 |
204 | ## 68.0b2-10 (2019/05/20)
205 |
206 | * Firefox Developer Edition 68.0b2
207 | * Portapps 1.24.1
208 |
209 | ## 67.0b18-9 (2019/05/08)
210 |
211 | * Firefox Developer Edition 67.0b18
212 | * Portapps 1.23.0
213 |
214 | ## 67.0b17-8 (2019/05/06)
215 |
216 | * Firefox Developer Edition 67.0b17
217 | * Portapps 1.22.2
218 |
219 | ## 67.0b10-7 (2019/04/14)
220 |
221 | * Firefox Developer Edition 67.0b10
222 |
223 | ## 67.0b6-6 (2019/03/31)
224 |
225 | * Firefox Developer Edition 67.0b6
226 | * Portapps 1.21.0
227 |
228 | ## 67.0b4-5 (2019/03/23)
229 |
230 | * Firefox Developer Edition 67.0b4
231 |
232 | ## 67.0b3-4 (2019/03/20)
233 |
234 | * Firefox Developer Edition 67.0b3
235 |
236 | ## 66.0b14-3 (2019/03/17)
237 |
238 | * Firefox Developer Edition 66.0b14
239 | * Handle notifications
240 | * Portapps 1.20.3
241 |
242 | ## 66.0b13-2 (2019/03/06)
243 |
244 | * Initial version based on Firefox Developer Edition 66.0b13
245 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019-2025 CrazyMax
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |

2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | ## About
13 |
14 | Phyrox Developer Edition (based on Mozilla Firefox Developer Edition) portable app made with 🚀 [Portapps](https://portapps.io).
15 | Documentation and downloads can be found on https://portapps.io/app/phyrox-developer-portable/
16 |
17 | > :warning: Following a trademark violation report ([#5](https://github.com/portapps/phyrox-developer-portable/issues/5)) from Mozilla, Firefox Developer Edition portable has been named Phyrox Developer Edition portable on Portapps. Nothing changes except its name.
18 |
19 | ## Contributing
20 |
21 | Want to contribute? Awesome! The most basic way to show your support is to star the project, or to raise issues. If
22 | you want to open a pull request, please read the [contributing guidelines](https://portapps.io/doc/contribute/).
23 |
24 | You can also support this project by [**becoming a sponsor on GitHub**](https://github.com/sponsors/crazy-max) or by
25 | making a [Paypal donation](https://www.paypal.me/crazyws) to ensure this journey continues indefinitely!
26 |
27 | Thanks again for your support, it is much appreciated! :pray:
28 |
29 | ## License
30 |
31 | MIT. See `LICENSE` for more details.
32 | Logo credit to [Nadja Hallfahrt](http://blog.artcore-illustrations.de/).
33 | Rocket icon credit to [Squid Ink](http://thesquid.ink).
34 |
--------------------------------------------------------------------------------
/assets/assets.go:
--------------------------------------------------------------------------------
1 | // Code generated by go-bindata. DO NOT EDIT.
2 | // sources:
3 | // res/FirefoxDeveloperEdition.lnk (1.294kB)
4 |
5 | package assets
6 |
7 | import (
8 | "bytes"
9 | "compress/gzip"
10 | "crypto/sha256"
11 | "fmt"
12 | "io"
13 | "os"
14 | "path/filepath"
15 | "strings"
16 | "time"
17 | )
18 |
19 | func bindataRead(data []byte, name string) ([]byte, error) {
20 | gz, err := gzip.NewReader(bytes.NewBuffer(data))
21 | if err != nil {
22 | return nil, fmt.Errorf("read %q: %w", name, err)
23 | }
24 |
25 | var buf bytes.Buffer
26 | _, err = io.Copy(&buf, gz)
27 | clErr := gz.Close()
28 |
29 | if err != nil {
30 | return nil, fmt.Errorf("read %q: %w", name, err)
31 | }
32 | if clErr != nil {
33 | return nil, err
34 | }
35 |
36 | return buf.Bytes(), nil
37 | }
38 |
39 | type asset struct {
40 | bytes []byte
41 | info os.FileInfo
42 | digest [sha256.Size]byte
43 | }
44 |
45 | type bindataFileInfo struct {
46 | name string
47 | size int64
48 | mode os.FileMode
49 | modTime time.Time
50 | }
51 |
52 | func (fi bindataFileInfo) Name() string {
53 | return fi.name
54 | }
55 | func (fi bindataFileInfo) Size() int64 {
56 | return fi.size
57 | }
58 | func (fi bindataFileInfo) Mode() os.FileMode {
59 | return fi.mode
60 | }
61 | func (fi bindataFileInfo) ModTime() time.Time {
62 | return fi.modTime
63 | }
64 | func (fi bindataFileInfo) IsDir() bool {
65 | return false
66 | }
67 | func (fi bindataFileInfo) Sys() interface{} {
68 | return nil
69 | }
70 |
71 | var _firefoxdevelopereditionLnk = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xb4\x93\x5f\x68\x23\x55\x14\xc6\x7f\x71\xbb\xae\x75\x5f\x1a\x5c\xc4\x2d\x5d\x3a\x0f\x22\x5d\x35\xd9\x49\x9a\xa4\x49\xd6\x95\xa6\x49\xc6\x68\xe2\x36\xb4\x2a\x45\xe6\xc1\xd6\xdc\xb4\xa3\x49\x27\x9d\xd4\x92\x42\x29\x0a\x42\xb1\xa8\x88\x0a\x56\x44\x1a\x8b\xd2\x0a\xb5\xe0\x1f\x10\x69\x91\x82\xf8\xe2\x83\x04\x69\x41\x14\x6a\x2b\xfa\xa0\x20\xc5\xfa\xa4\x16\x2a\x77\x32\x91\xa6\x2a\x8a\xb0\xe7\xe1\x9c\xe4\x9c\x73\xe7\xfb\xee\x77\xcf\xc9\x00\xae\x73\xd7\x21\x6d\xd3\xf6\x68\xaf\x01\x0a\xb0\xb7\xf4\x61\xe1\xee\xed\x2d\xd7\x77\x3f\xd7\xe3\x95\xa3\x4c\xf1\xe5\x2f\xb6\x5c\xb5\x0b\x67\xec\x46\x17\xcd\xf6\x96\xeb\x1c\x9d\xd9\xdd\xfe\x9a\xf2\x63\xd4\x68\x5b\xfa\xf2\x06\xee\x50\xd5\xd7\xcf\x73\x29\x1e\xd5\xf9\xab\x2d\xe0\xb3\xe3\xe8\xd5\xc7\x36\xdc\x64\x07\xfa\xef\x19\x88\xcd\xfa\xe1\x49\x5a\x69\x61\xff\xe3\x4b\xf7\x47\xef\x92\x35\x2f\xd0\x79\x7d\x33\xe0\x43\xb6\x4f\xbf\xd1\x4a\x16\x0b\x93\x51\x2c\x86\x29\xa2\xa0\x61\x50\x40\x50\x46\xa1\x8b\x0a\x61\x42\x5c\x04\x7a\x29\x33\x86\xa0\x40\x81\x6e\xfc\x78\xc9\xd9\xbf\xef\xc4\x83\x1f\x1f\x61\x7c\xf4\x00\xb7\x30\x73\x8c\x57\x1b\xda\xbd\x03\x49\xad\x7f\xd6\x07\x39\x87\x97\xcc\x37\x78\xb9\xdf\x97\x9c\xce\x9e\xb8\xd9\xf2\xe5\xac\xcd\xc3\x42\x90\xc7\xa4\x82\x42\x02\xc1\x94\x8d\x6f\x52\x42\x60\xa1\x90\x24\x87\xc1\x24\x06\x26\xe3\x36\xf6\x08\x7e\xa4\xbc\xb9\xab\xab\x13\x0a\x79\xc3\x12\x79\xb3\xe2\x15\x15\x41\xea\x6f\xd0\x6b\x1f\x48\xf4\xd6\x13\xe8\x9f\xb4\x3f\x4d\xbe\x09\xdd\x8b\xa0\x82\x00\xda\x81\x32\xd0\xe1\xa8\x29\x63\xd0\x39\x67\x01\xe7\x81\x53\x40\x7c\xbd\x43\x6f\x03\x12\xc6\xad\x13\x4f\x08\x25\x4e\x3c\xaa\x67\x2d\x73\xd4\x1a\x2e\x2a\x9a\x51\x10\x65\xa5\xab\x12\x0e\x5d\xd4\xb5\x3a\x43\x25\x21\xa6\x44\xc1\x2c\x09\x4b\x49\xe6\x8c\x49\xc3\x1c\xd7\x8f\x73\xa7\x0f\x2f\x5e\xf4\x26\xff\xdf\x1e\x4e\xff\x1f\x42\xea\xff\x70\x7d\x95\x38\xd1\x6b\x8a\x2c\x25\x3b\x0d\xd5\xdb\x81\x4f\x1d\x79\xcf\x42\x75\xbf\xf7\xe1\x99\xdf\xab\x87\xe9\xb9\xfb\x36\x0f\x76\x3f\xfa\xed\x79\x59\x7b\xa4\x2e\x75\x75\xc8\x91\xbf\xf4\xa8\x67\x6c\x38\x27\xca\x8d\x67\xcc\xad\xad\x4d\x4e\x1f\xac\x26\x5f\x7c\xea\xfb\xb7\xbf\x5a\x99\x6b\xf1\xbf\x70\x79\xa7\x23\xf6\x83\xfb\xd5\xc7\x1f\x78\xef\xd4\x8d\xf3\x99\x7f\xab\xab\x2e\x7b\x34\xaa\xcf\x00\xbe\xc1\xec\xe0\xb7\xf3\x43\xda\x46\x26\x1c\x5f\x3f\xbc\xe9\xa5\xdb\x16\x8a\x9f\x17\x81\x16\x09\xd4\x09\xc8\x69\x1a\xc4\x83\x0f\x0f\x41\x67\x23\x3c\x74\xd3\x43\x84\x00\x01\x22\x44\x08\xd9\xc2\xc8\x5a\x84\x20\x2a\x01\xfb\xbf\x9f\xb0\xdd\x19\x24\x80\x8a\x6a\x6f\x91\x3c\x11\xb2\xbf\x56\xcf\xd4\x6d\xc4\x21\xf2\x60\x57\x66\x71\x7a\x31\x92\x5e\xa9\xed\x6d\x79\xf6\xb6\x7f\x71\x37\x36\x48\xba\xa3\xa3\xfa\x40\x9e\x6e\x30\x93\x55\x0d\x8d\x04\x01\x92\x24\xe8\x23\x44\x1f\x31\x62\xf4\xd8\xb9\x38\xdd\x7f\x4e\x7e\xc4\x41\x78\xf7\xe6\x62\xe2\x9d\xe7\x4a\xa9\xe5\x54\xaf\xf7\xcd\x2b\x95\x67\x2f\x00\x63\xb2\x21\x05\x7c\xb3\xd3\xfe\xd3\xdc\xaf\xfb\xa9\x57\xd6\xbe\x4e\x9f\xf9\x6c\x56\x3d\xbe\x3a\x7f\x04\x00\x00\xff\xff\xb2\xca\x3f\x21\x0e\x05\x00\x00")
72 |
73 | func firefoxdevelopereditionLnkBytes() ([]byte, error) {
74 | return bindataRead(
75 | _firefoxdevelopereditionLnk,
76 | "FirefoxDeveloperEdition.lnk",
77 | )
78 | }
79 |
80 | func firefoxdevelopereditionLnk() (*asset, error) {
81 | bytes, err := firefoxdevelopereditionLnkBytes()
82 | if err != nil {
83 | return nil, err
84 | }
85 |
86 | info := bindataFileInfo{name: "FirefoxDeveloperEdition.lnk", size: 1294, mode: os.FileMode(0666), modTime: time.Unix(1572378781, 0)}
87 | a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf1, 0x64, 0x23, 0x53, 0x23, 0x7a, 0x80, 0x9d, 0xb4, 0x38, 0x88, 0x8e, 0x8e, 0xb2, 0xd2, 0xad, 0x74, 0x67, 0xbc, 0x64, 0x79, 0x2b, 0x22, 0x77, 0x32, 0xe2, 0xef, 0x5f, 0x13, 0x74, 0xac, 0x70}}
88 | return a, nil
89 | }
90 |
91 | // Asset loads and returns the asset for the given name.
92 | // It returns an error if the asset could not be found or
93 | // could not be loaded.
94 | func Asset(name string) ([]byte, error) {
95 | canonicalName := strings.Replace(name, "\\", "/", -1)
96 | if f, ok := _bindata[canonicalName]; ok {
97 | a, err := f()
98 | if err != nil {
99 | return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
100 | }
101 | return a.bytes, nil
102 | }
103 | return nil, fmt.Errorf("Asset %s not found", name)
104 | }
105 |
106 | // AssetString returns the asset contents as a string (instead of a []byte).
107 | func AssetString(name string) (string, error) {
108 | data, err := Asset(name)
109 | return string(data), err
110 | }
111 |
112 | // MustAsset is like Asset but panics when Asset would return an error.
113 | // It simplifies safe initialization of global variables.
114 | func MustAsset(name string) []byte {
115 | a, err := Asset(name)
116 | if err != nil {
117 | panic("asset: Asset(" + name + "): " + err.Error())
118 | }
119 |
120 | return a
121 | }
122 |
123 | // MustAssetString is like AssetString but panics when Asset would return an
124 | // error. It simplifies safe initialization of global variables.
125 | func MustAssetString(name string) string {
126 | return string(MustAsset(name))
127 | }
128 |
129 | // AssetInfo loads and returns the asset info for the given name.
130 | // It returns an error if the asset could not be found or
131 | // could not be loaded.
132 | func AssetInfo(name string) (os.FileInfo, error) {
133 | canonicalName := strings.Replace(name, "\\", "/", -1)
134 | if f, ok := _bindata[canonicalName]; ok {
135 | a, err := f()
136 | if err != nil {
137 | return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
138 | }
139 | return a.info, nil
140 | }
141 | return nil, fmt.Errorf("AssetInfo %s not found", name)
142 | }
143 |
144 | // AssetDigest returns the digest of the file with the given name. It returns an
145 | // error if the asset could not be found or the digest could not be loaded.
146 | func AssetDigest(name string) ([sha256.Size]byte, error) {
147 | canonicalName := strings.Replace(name, "\\", "/", -1)
148 | if f, ok := _bindata[canonicalName]; ok {
149 | a, err := f()
150 | if err != nil {
151 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err)
152 | }
153 | return a.digest, nil
154 | }
155 | return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name)
156 | }
157 |
158 | // Digests returns a map of all known files and their checksums.
159 | func Digests() (map[string][sha256.Size]byte, error) {
160 | mp := make(map[string][sha256.Size]byte, len(_bindata))
161 | for name := range _bindata {
162 | a, err := _bindata[name]()
163 | if err != nil {
164 | return nil, err
165 | }
166 | mp[name] = a.digest
167 | }
168 | return mp, nil
169 | }
170 |
171 | // AssetNames returns the names of the assets.
172 | func AssetNames() []string {
173 | names := make([]string, 0, len(_bindata))
174 | for name := range _bindata {
175 | names = append(names, name)
176 | }
177 | return names
178 | }
179 |
180 | // _bindata is a table, holding each asset generator, mapped to its name.
181 | var _bindata = map[string]func() (*asset, error){
182 | "FirefoxDeveloperEdition.lnk": firefoxdevelopereditionLnk,
183 | }
184 |
185 | // AssetDebug is true if the assets were built with the debug flag enabled.
186 | const AssetDebug = false
187 |
188 | // AssetDir returns the file names below a certain
189 | // directory embedded in the file by go-bindata.
190 | // For example if you run go-bindata on data/... and data contains the
191 | // following hierarchy:
192 | //
193 | // data/
194 | // foo.txt
195 | // img/
196 | // a.png
197 | // b.png
198 | //
199 | // then AssetDir("data") would return []string{"foo.txt", "img"},
200 | // AssetDir("data/img") would return []string{"a.png", "b.png"},
201 | // AssetDir("foo.txt") and AssetDir("notexist") would return an error, and
202 | // AssetDir("") will return []string{"data"}.
203 | func AssetDir(name string) ([]string, error) {
204 | node := _bintree
205 | if len(name) != 0 {
206 | canonicalName := strings.Replace(name, "\\", "/", -1)
207 | pathList := strings.Split(canonicalName, "/")
208 | for _, p := range pathList {
209 | node = node.Children[p]
210 | if node == nil {
211 | return nil, fmt.Errorf("Asset %s not found", name)
212 | }
213 | }
214 | }
215 | if node.Func != nil {
216 | return nil, fmt.Errorf("Asset %s not found", name)
217 | }
218 | rv := make([]string, 0, len(node.Children))
219 | for childName := range node.Children {
220 | rv = append(rv, childName)
221 | }
222 | return rv, nil
223 | }
224 |
225 | type bintree struct {
226 | Func func() (*asset, error)
227 | Children map[string]*bintree
228 | }
229 |
230 | var _bintree = &bintree{nil, map[string]*bintree{
231 | "FirefoxDeveloperEdition.lnk": {firefoxdevelopereditionLnk, map[string]*bintree{}},
232 | }}
233 |
234 | // RestoreAsset restores an asset under the given directory.
235 | func RestoreAsset(dir, name string) error {
236 | data, err := Asset(name)
237 | if err != nil {
238 | return err
239 | }
240 | info, err := AssetInfo(name)
241 | if err != nil {
242 | return err
243 | }
244 | err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
245 | if err != nil {
246 | return err
247 | }
248 | err = os.WriteFile(_filePath(dir, name), data, info.Mode())
249 | if err != nil {
250 | return err
251 | }
252 | return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
253 | }
254 |
255 | // RestoreAssets restores an asset under the given directory recursively.
256 | func RestoreAssets(dir, name string) error {
257 | children, err := AssetDir(name)
258 | // File
259 | if err != nil {
260 | return RestoreAsset(dir, name)
261 | }
262 | // Dir
263 | for _, child := range children {
264 | err = RestoreAssets(dir, filepath.Join(name, child))
265 | if err != nil {
266 | return err
267 | }
268 | }
269 | return nil
270 | }
271 |
272 | func _filePath(dir, name string) string {
273 | canonicalName := strings.Replace(name, "\\", "/", -1)
274 | return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...)
275 | }
276 |
--------------------------------------------------------------------------------
/build.properties:
--------------------------------------------------------------------------------
1 | # Portapps
2 | core.dir = ../portapps
3 |
4 | # App
5 | app = phyrox-developer
6 | app.name = Phyrox Developer Edition
7 | app.type = archive
8 | app.version = 138.0b3
9 | app.release = 52
10 | app.homepage = https://www.mozilla.org/en-US/firefox
11 |
12 | # Portable app
13 | papp.id = ${app}-portable
14 | papp.guid = {829F3ADB-1DE7-4176-8DA8-532558319F16}
15 | papp.name = ${app.name} Portable
16 | papp.desc = ${app.name} portable on Windows by Portapps
17 | papp.url = https://github.com/portapps/${papp.id}
18 | papp.folder = app
19 |
20 | # Official artifacts
21 | atf.id = Firefox
22 | atf.win64.filename = ${atf.id}DevEditionSetup-${app.version}-win64
23 | atf.win64.ext = .exe
24 | atf.win64.url = https://ftp.mozilla.org/pub/devedition/releases/${app.version}/win64/en-US/Firefox%20Setup%20${app.version}.exe
25 | atf.win64.assertextract = core/firefox.exe
26 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/portapps/phyrox-developer-portable
2 |
3 | go 1.24.0
4 |
5 | require (
6 | github.com/Jeffail/gabs v1.4.0
7 | github.com/kevinburke/go-bindata/v4 v4.0.2
8 | github.com/pierrec/lz4/v3 v3.3.5
9 | github.com/pkg/errors v0.9.1
10 | github.com/portapps/portapps/v3 v3.16.0
11 | )
12 |
13 | require (
14 | github.com/akavel/rsrc v0.10.2 // indirect
15 | github.com/go-ole/go-ole v1.3.0 // indirect
16 | github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
17 | github.com/ilya1st/rotatewriter v0.0.0-20171126183947-3df0c1a3ed6d // indirect
18 | github.com/josephspurrier/goversioninfo v1.5.0 // indirect
19 | github.com/mattn/go-colorable v0.1.13 // indirect
20 | github.com/mattn/go-isatty v0.0.19 // indirect
21 | github.com/rs/zerolog v1.34.0 // indirect
22 | golang.org/x/sys v0.32.0 // indirect
23 | gopkg.in/yaml.v3 v3.0.1 // indirect
24 | )
25 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | code.cloudfoundry.org/bytefmt v0.0.0-20190710193110-1eb035ffe2b6/go.mod h1:wN/zk7mhREp/oviagqUXY3EwuHhWyOvAdsn5Y4CzOrc=
2 | github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
3 | github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
4 | github.com/akavel/rsrc v0.10.2 h1:Zxm8V5eI1hW4gGaYsJQUhxpjkENuG91ki8B4zCrvEsw=
5 | github.com/akavel/rsrc v0.10.2/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
6 | github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
7 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
8 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
10 | github.com/frankban/quicktest v1.4.0 h1:rCSCih1FnSWJEel/eub9wclBSqpF2F/PuvxUWGWnbO8=
11 | github.com/frankban/quicktest v1.4.0/go.mod h1:36zfPVQyHxymz4cH7wlDmVwDrJuljRB60qkgn7rorfQ=
12 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
13 | github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
14 | github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
15 | github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
16 | github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
17 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
18 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
19 | github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
20 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
21 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
22 | github.com/ilya1st/rotatewriter v0.0.0-20171126183947-3df0c1a3ed6d h1:OGuVAVny/97zsQ5BWg0mOjzTBBD9zR+Lug1co144+rU=
23 | github.com/ilya1st/rotatewriter v0.0.0-20171126183947-3df0c1a3ed6d/go.mod h1:S1q6q+21PRGd0WRX+fHjQ+TOe3CgpSv7zgCWnZcbxCs=
24 | github.com/josephspurrier/goversioninfo v1.5.0 h1:9TJtORoyf4YMoWSOo/cXFN9A/lB3PniJ91OxIH6e7Zg=
25 | github.com/josephspurrier/goversioninfo v1.5.0/go.mod h1:6MoTvFZ6GKJkzcdLnU5T/RGYUbHQbKpYeNP0AgQLd2o=
26 | github.com/kevinburke/go-bindata/v4 v4.0.2 h1:6qQI0nNTL27wM1En8zQHGBEPp3ETzgFU6hVdSjlkrfE=
27 | github.com/kevinburke/go-bindata/v4 v4.0.2/go.mod h1:M/CkBqw2qCZ1Ztv5JyKgocGYWyUkYlDqkqXS1ktLe5c=
28 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
29 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
30 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
31 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
32 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
33 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
34 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
35 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
36 | github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
37 | github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
38 | github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
39 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
40 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
41 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
42 | github.com/pierrec/cmdflag v0.0.2/go.mod h1:a3zKGZ3cdQUfxjd0RGMLZr8xI3nvpJOB+m6o/1X5BmU=
43 | github.com/pierrec/lz4/v3 v3.3.5 h1:JzKda6jLXZpQK5/ulrEfT1I66tsKiGlw6sjKssFpwt8=
44 | github.com/pierrec/lz4/v3 v3.3.5/go.mod h1:280XNCGS8jAcG++AHdd6SeWnzyJ1w9oow2vbORyey8Q=
45 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
46 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
47 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
48 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
49 | github.com/portapps/portapps/v3 v3.16.0 h1:wQyDDoYAh7YTTaIwo48K8lbegODZuasSq4S7XIppe6s=
50 | github.com/portapps/portapps/v3 v3.16.0/go.mod h1:4ue65AQ4rAe0iiOr3tTvmmNyDYIB9R6JywBBEPrJKZU=
51 | github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
52 | github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
53 | github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
54 | github.com/schollz/progressbar/v2 v2.13.2/go.mod h1:6YZjqdthH6SCZKv2rqGryrxPtfmRB/DWZxSMfCXPyD8=
55 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
56 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
57 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
58 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
59 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
60 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
61 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
62 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
63 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
64 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
65 | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
66 | golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
67 | golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
68 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
69 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
70 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
71 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
72 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
73 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
74 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
75 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
76 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | //go:generate go install -v github.com/kevinburke/go-bindata/v4/go-bindata
2 | //go:generate go-bindata -prefix res/ -pkg assets -o assets/assets.go res/FirefoxDeveloperEdition.lnk
3 | //go:generate go install -v github.com/josephspurrier/goversioninfo/cmd/goversioninfo
4 | //go:generate goversioninfo -icon=res/papp.ico -manifest=res/papp.manifest
5 | package main
6 |
7 | import (
8 | "fmt"
9 | "os"
10 | "path"
11 | "strings"
12 |
13 | "github.com/Jeffail/gabs"
14 | "github.com/pkg/errors"
15 | "github.com/portapps/phyrox-developer-portable/assets"
16 | "github.com/portapps/portapps/v3"
17 | "github.com/portapps/portapps/v3/pkg/log"
18 | "github.com/portapps/portapps/v3/pkg/mutex"
19 | "github.com/portapps/portapps/v3/pkg/shortcut"
20 | "github.com/portapps/portapps/v3/pkg/utl"
21 | "github.com/portapps/portapps/v3/pkg/win"
22 | )
23 |
24 | type config struct {
25 | Profile string `yaml:"profile" mapstructure:"profile"`
26 | MultipleInstances bool `yaml:"multiple_instances" mapstructure:"multiple_instances"`
27 | Cleanup bool `yaml:"cleanup" mapstructure:"cleanup"`
28 | }
29 |
30 | var (
31 | app *portapps.App
32 | cfg *config
33 | )
34 |
35 | func init() {
36 | var err error
37 |
38 | // Default config
39 | cfg = &config{
40 | Profile: "default",
41 | MultipleInstances: false,
42 | Cleanup: false,
43 | }
44 |
45 | // Init app
46 | if app, err = portapps.NewWithCfg("phyrox-developer-portable", "Phyrox Developer Edition", cfg); err != nil {
47 | log.Fatal().Err(err).Msg("Cannot initialize application. See log file for more info.")
48 | }
49 | }
50 |
51 | func main() {
52 | utl.CreateFolder(app.DataPath)
53 | profileFolder := utl.CreateFolder(app.DataPath, "profile", cfg.Profile)
54 |
55 | app.Process = utl.PathJoin(app.AppPath, "firefox.exe")
56 | app.Args = []string{
57 | "--profile",
58 | profileFolder,
59 | }
60 |
61 | // Set env vars
62 | crashreporterFolder := utl.CreateFolder(app.DataPath, "crashreporter")
63 | pluginsFolder := utl.CreateFolder(app.DataPath, "plugins")
64 | os.Setenv("MOZ_CRASHREPORTER", "0")
65 | os.Setenv("MOZ_CRASHREPORTER_DATA_DIRECTORY", crashreporterFolder)
66 | os.Setenv("MOZ_CRASHREPORTER_DISABLE", "1")
67 | os.Setenv("MOZ_CRASHREPORTER_NO_REPORT", "1")
68 | os.Setenv("MOZ_DATA_REPORTING", "0")
69 | os.Setenv("MOZ_MAINTENANCE_SERVICE", "0")
70 | os.Setenv("MOZ_PLUGIN_PATH", pluginsFolder)
71 | os.Setenv("MOZ_UPDATER", "0")
72 |
73 | // Create and check mutex
74 | mu, err := mutex.Create(app.ID)
75 | defer mutex.Release(mu)
76 | if err != nil {
77 | if !cfg.MultipleInstances {
78 | log.Error().Msg("You have to enable multiple instances in your configuration if you want to launch another instance")
79 | if _, err = win.MsgBox(
80 | fmt.Sprintf("%s portable", app.Name),
81 | "Other instance detected. You have to enable multiple instances in your configuration if you want to launch another instance.",
82 | win.MsgBoxBtnOk|win.MsgBoxIconError); err != nil {
83 | log.Error().Err(err).Msg("Cannot create dialog box")
84 | }
85 | return
86 | } else {
87 | log.Warn().Msg("Another instance is already running")
88 | }
89 | }
90 |
91 | // Cleanup on exit
92 | if cfg.Cleanup {
93 | defer func() {
94 | utl.Cleanup([]string{
95 | path.Join(os.Getenv("APPDATA"), "Mozilla", "Firefox"),
96 | path.Join(os.Getenv("LOCALAPPDATA"), "Mozilla", "Firefox"),
97 | path.Join(os.Getenv("USERPROFILE"), "AppData", "LocalLow", "Mozilla"),
98 | })
99 | }()
100 | }
101 |
102 | // Multiple instances
103 | if cfg.MultipleInstances {
104 | log.Info().Msg("Multiple instances enabled")
105 | app.Args = append(app.Args, "--no-remote")
106 | }
107 |
108 | // Policies
109 | if err := createPolicies(); err != nil {
110 | log.Fatal().Err(err).Msg("Cannot create policies")
111 | }
112 |
113 | // Fix extensions path
114 | if err := updateAddonStartup(profileFolder); err != nil {
115 | log.Error().Err(err).Msg("Cannot fix extensions path")
116 | }
117 |
118 | // Copy default shortcut
119 | shortcutPath := path.Join(os.Getenv("APPDATA"), "Microsoft", "Windows", "Start Menu", "Programs", "Phyrox Developer Edition Portable.lnk")
120 | defaultShortcut, err := assets.Asset("FirefoxDeveloperEdition.lnk")
121 | if err != nil {
122 | log.Error().Err(err).Msg("Cannot load asset FirefoxDeveloperEdition.lnk")
123 | }
124 | err = os.WriteFile(shortcutPath, defaultShortcut, 0644)
125 | if err != nil {
126 | log.Error().Err(err).Msg("Cannot write default shortcut")
127 | }
128 |
129 | // Update default shortcut
130 | err = shortcut.Create(shortcut.Shortcut{
131 | ShortcutPath: shortcutPath,
132 | TargetPath: app.Process,
133 | Arguments: shortcut.Property{Clear: true},
134 | Description: shortcut.Property{Value: "Phyrox Developer Edition Portable by Portapps"},
135 | IconLocation: shortcut.Property{Value: app.Process},
136 | WorkingDirectory: shortcut.Property{Value: app.AppPath},
137 | })
138 | if err != nil {
139 | log.Error().Err(err).Msg("Cannot create shortcut")
140 | }
141 | defer func() {
142 | if err := os.Remove(shortcutPath); err != nil {
143 | log.Error().Err(err).Msg("Cannot remove shortcut")
144 | }
145 | }()
146 |
147 | defer app.Close()
148 | app.Launch(os.Args[1:])
149 | }
150 |
151 | func createPolicies() error {
152 | appFile := utl.PathJoin(utl.CreateFolder(app.AppPath, "distribution"), "policies.json")
153 | dataFile := utl.PathJoin(app.DataPath, "policies.json")
154 | defaultPolicies := struct {
155 | Policies map[string]interface{} `json:"policies"`
156 | }{
157 | Policies: map[string]interface{}{
158 | "DisableAppUpdate": true,
159 | "DontCheckDefaultBrowser": true,
160 | },
161 | }
162 |
163 | jsonPolicies, err := gabs.Consume(defaultPolicies)
164 | if err != nil {
165 | return errors.Wrap(err, "Cannot consume default policies")
166 | }
167 | log.Debug().Msgf("Default policies: %s", jsonPolicies.String())
168 |
169 | if utl.Exists(dataFile) {
170 | rawCustomPolicies, err := os.ReadFile(dataFile)
171 | if err != nil {
172 | return errors.Wrap(err, "Cannot read custom policies")
173 | }
174 |
175 | jsonPolicies, err = gabs.ParseJSON(rawCustomPolicies)
176 | if err != nil {
177 | return errors.Wrap(err, "Cannot consume custom policies")
178 | }
179 | log.Debug().Msgf("Custom policies: %s", jsonPolicies.String())
180 |
181 | jsonPolicies.Set(true, "policies", "DisableAppUpdate")
182 | jsonPolicies.Set(true, "policies", "DontCheckDefaultBrowser")
183 | }
184 |
185 | log.Debug().Msgf("Applied policies: %s", jsonPolicies.String())
186 | err = os.WriteFile(appFile, []byte(jsonPolicies.StringIndent("", " ")), 0644)
187 | if err != nil {
188 | return errors.Wrap(err, "Cannot write policies")
189 | }
190 |
191 | return nil
192 | }
193 |
194 | func updateAddonStartup(profileFolder string) error {
195 | lz4File := path.Join(profileFolder, "addonStartup.json.lz4")
196 | if !utl.Exists(lz4File) || app.Prev.RootPath == "" {
197 | return nil
198 | }
199 |
200 | lz4Raw, err := mozLz4Decompress(lz4File)
201 | if err != nil {
202 | return err
203 | }
204 |
205 | prevPathLin := strings.Replace(utl.FormatUnixPath(app.Prev.RootPath), ` `, `%20`, -1)
206 | currPathLin := strings.Replace(utl.FormatUnixPath(app.RootPath), ` `, `%20`, -1)
207 | lz4Str := strings.Replace(string(lz4Raw), prevPathLin, currPathLin, -1)
208 |
209 | prevPathWin := strings.Replace(strings.Replace(utl.FormatWindowsPath(app.Prev.RootPath), `\`, `\\`, -1), ` `, `%20`, -1)
210 | currPathWin := strings.Replace(strings.Replace(utl.FormatWindowsPath(app.RootPath), `\`, `\\`, -1), ` `, `%20`, -1)
211 | lz4Str = strings.Replace(lz4Str, prevPathWin, currPathWin, -1)
212 |
213 | lz4Enc, err := mozLz4Compress([]byte(lz4Str))
214 | if err != nil {
215 | return err
216 | }
217 |
218 | return os.WriteFile(lz4File, lz4Enc, 0644)
219 | }
220 |
--------------------------------------------------------------------------------
/mozlz4.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "bytes"
5 | "encoding/binary"
6 | "io"
7 | "os"
8 |
9 | "github.com/pierrec/lz4/v3"
10 | "github.com/pkg/errors"
11 | )
12 |
13 | const (
14 | mozLz4Header = "mozLz40\x00"
15 | )
16 |
17 | func mozLz4Decompress(filename string) ([]byte, error) {
18 | file, err := os.Open(filename)
19 | if err != nil {
20 | return nil, err
21 | }
22 |
23 | header := make([]byte, len(mozLz4Header))
24 | _, err = file.Read(header)
25 | if err != nil {
26 | return nil, errors.Wrap(err, "couldn't read header")
27 | }
28 | if string(header) != mozLz4Header {
29 | return nil, errors.New("no mozLz4 header")
30 | }
31 |
32 | var size uint32
33 | err = binary.Read(file, binary.LittleEndian, &size)
34 | if err != nil {
35 | return nil, errors.Wrap(err, "couldn't read size")
36 | }
37 |
38 | src, err := io.ReadAll(file)
39 | if err != nil {
40 | return nil, errors.Wrap(err, "couldn't read compressed data")
41 | }
42 |
43 | out := make([]byte, size)
44 | _, err = lz4.UncompressBlock(src, out)
45 | if err != nil {
46 | return nil, errors.Wrap(err, "couldn't decompress data")
47 | }
48 |
49 | return out, nil
50 | }
51 |
52 | func mozLz4Compress(src []byte) ([]byte, error) {
53 | out := new(bytes.Buffer)
54 |
55 | _, err := out.Write([]byte(mozLz4Header))
56 | if err != nil {
57 | return nil, errors.Wrap(err, "couldn't write header")
58 | }
59 |
60 | err = binary.Write(out, binary.LittleEndian, uint32(len(src)))
61 | if err != nil {
62 | return nil, errors.Wrap(err, "couldn't encode length")
63 | }
64 |
65 | buf := make([]byte, 10*len(src))
66 | sz, err := lz4.CompressBlockHC(src, buf, -1)
67 | if err != nil {
68 | return nil, errors.Wrap(err, "couldn't compress data")
69 | }
70 | if sz == 0 {
71 | return nil, errors.New("data incompressible")
72 | }
73 |
74 | _, err = out.Write(buf[:sz])
75 | if err != nil {
76 | return nil, errors.Wrap(err, "couldn't write compressed data")
77 | }
78 |
79 | return out.Bytes(), nil
80 | }
81 |
--------------------------------------------------------------------------------
/res/FirefoxDeveloperEdition.lnk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/portapps/phyrox-developer-portable/4a8eaf06fcedf033a7565ecd37fa022ca2726de0/res/FirefoxDeveloperEdition.lnk
--------------------------------------------------------------------------------
/res/app.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/portapps/phyrox-developer-portable/4a8eaf06fcedf033a7565ecd37fa022ca2726de0/res/app.ico
--------------------------------------------------------------------------------
/res/papp.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/portapps/phyrox-developer-portable/4a8eaf06fcedf033a7565ecd37fa022ca2726de0/res/papp.ico
--------------------------------------------------------------------------------
/res/papp.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/papp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/portapps/phyrox-developer-portable/4a8eaf06fcedf033a7565ecd37fa022ca2726de0/res/papp.png
--------------------------------------------------------------------------------
/res/run.iss:
--------------------------------------------------------------------------------
1 | [Run]
2 | Filename: {app}\{#pappId}.exe; Description: Run {#pappName}; Flags: nowait postinstall skipifsilent unchecked
3 |
--------------------------------------------------------------------------------
/res/setup-mini.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/portapps/phyrox-developer-portable/4a8eaf06fcedf033a7565ecd37fa022ca2726de0/res/setup-mini.bmp
--------------------------------------------------------------------------------
/tools/tools.go:
--------------------------------------------------------------------------------
1 | //go:build tools
2 | // +build tools
3 |
4 | // Package tools tracks dependencies on binaries not referenced in this codebase.
5 | // https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module
6 | package tools
7 |
8 | import (
9 | _ "github.com/kevinburke/go-bindata/v4"
10 | _ "github.com/portapps/portapps/v3/tools"
11 | )
12 |
--------------------------------------------------------------------------------