mirror of
https://github.com/maxgoedjen/secretive.git
synced 2026-06-21 21:51:36 +00:00
Compare commits
7 Commits
auth_split
...
socket_lau
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
688b6380bd | ||
|
|
702e3f2cb0 | ||
|
|
76baba746c | ||
|
|
18107257ba | ||
|
|
98e2f38e46 | ||
|
|
a727d110c8 | ||
|
|
fbc4133f39 |
5
.github/workflows/nightly.yml
vendored
5
.github/workflows/nightly.yml
vendored
@@ -11,6 +11,7 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
attestations: write
|
attestations: write
|
||||||
|
artifact-metadata: write
|
||||||
actions: read
|
actions: read
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
@@ -40,7 +41,7 @@ jobs:
|
|||||||
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
||||||
- name: Upload App to Artifacts
|
- name: Upload App to Artifacts
|
||||||
id: upload
|
id: upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Secretive
|
name: Secretive
|
||||||
path: Artifact
|
path: Artifact
|
||||||
@@ -59,7 +60,7 @@ jobs:
|
|||||||
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
||||||
- name: Attest
|
- name: Attest
|
||||||
id: attest
|
id: attest
|
||||||
uses: actions/attest-build-provenance@v2
|
uses: actions/attest@v4
|
||||||
with:
|
with:
|
||||||
subject-name: "Secretive.zip"
|
subject-name: "Secretive.zip"
|
||||||
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
|
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
|
||||||
|
|||||||
5
.github/workflows/oneoff.yml
vendored
5
.github/workflows/oneoff.yml
vendored
@@ -10,6 +10,7 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
attestations: write
|
attestations: write
|
||||||
|
artifact-metadata: write
|
||||||
actions: read
|
actions: read
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
@@ -39,7 +40,7 @@ jobs:
|
|||||||
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
||||||
- name: Upload App to Artifacts
|
- name: Upload App to Artifacts
|
||||||
id: upload
|
id: upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Secretive
|
name: Secretive
|
||||||
path: Artifact
|
path: Artifact
|
||||||
@@ -58,7 +59,7 @@ jobs:
|
|||||||
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
||||||
- name: Attest
|
- name: Attest
|
||||||
id: attest
|
id: attest
|
||||||
uses: actions/attest-build-provenance@v2
|
uses: actions/attest@v4
|
||||||
with:
|
with:
|
||||||
subject-name: "Secretive.zip"
|
subject-name: "Secretive.zip"
|
||||||
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
|
subject-digest: sha256:${{ steps.upload.outputs.artifact-digest }}
|
||||||
|
|||||||
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@@ -32,6 +32,7 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
contents: write
|
contents: write
|
||||||
attestations: write
|
attestations: write
|
||||||
|
artifact-metadata: write
|
||||||
actions: read
|
actions: read
|
||||||
runs-on: macos-26
|
runs-on: macos-26
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
@@ -63,7 +64,7 @@ jobs:
|
|||||||
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
run: mkdir Artifact; cp -r Archive.xcarchive/Products/Applications/Secretive.app Artifact
|
||||||
- name: Upload App to Artifacts
|
- name: Upload App to Artifacts
|
||||||
id: upload
|
id: upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Secretive.zip
|
name: Secretive.zip
|
||||||
path: Artifact
|
path: Artifact
|
||||||
@@ -82,7 +83,7 @@ jobs:
|
|||||||
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
run: xcrun notarytool submit --key ~/.private_keys/AuthKey_$APPLE_API_KEY_ID.p8 --key-id $APPLE_API_KEY_ID --issuer $APPLE_API_ISSUER Secretive.zip
|
||||||
- name: Attest
|
- name: Attest
|
||||||
id: attest
|
id: attest
|
||||||
uses: actions/attest-build-provenance@v2
|
uses: actions/attest@v4
|
||||||
with:
|
with:
|
||||||
subject-path: "Secretive.zip"
|
subject-path: "Secretive.zip"
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
|
|||||||
@@ -1845,191 +1845,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_details_running_since_title" : {
|
|
||||||
"extractionState" : "manual",
|
|
||||||
"localizations" : {
|
|
||||||
"af" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ar" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ca" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Funcionant des de"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cs" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"da" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"de" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Läuft seit"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"el" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Εκτελείται Από"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"en" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"es" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fi" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Käynnissä alkaen"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"fr" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Actif depuis"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"he" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"hu" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"it" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ja" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "最後に起動した日時"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ko" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "실행 시각"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nb" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nl" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pl" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Uruchomiony od"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pt" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"pt-BR" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Rodando desde"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ro" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ru" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "Запущено с"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sr" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"sv" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tr" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uk" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vi" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "new",
|
|
||||||
"value" : "Running Since"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hans" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "运行时间始于"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"zh-Hant" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "執行時間始於"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"agent_details_socket_path_title" : {
|
"agent_details_socket_path_title" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
@@ -2770,7 +2585,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_not_running_notice_detail_description" : {
|
"agent_not_configured_notice_detail_description" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"af" : {
|
"af" : {
|
||||||
@@ -2787,7 +2602,7 @@
|
|||||||
},
|
},
|
||||||
"ca" : {
|
"ca" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "L'agent segur (SecretAgent) és un procés que funciona en rerefons per signar peticions, tal que no hages de tindre Secretive obert tot el temps.\n\n**Secretive no funcionarà correctament a menys que l'agent estiga instal·lat i en funcionament.**"
|
"value" : "L'agent segur (SecretAgent) és un procés que funciona en rerefons per signar peticions, tal que no hages de tindre Secretive obert tot el temps.\n\n**Secretive no funcionarà correctament a menys que l'agent estiga instal·lat i en funcionament.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2805,20 +2620,20 @@
|
|||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent ist ein Hintergrund-Prozess, der Anfragen signiert, sodass Du Secretive nicht durchgehend geöffnet haben musst.\n\n**Secretive wird nicht richtig funktionieren, wenn der Agent nicht installiert und ausgeführt wird.**"
|
"value" : "SecretAgent ist ein Hintergrund-Prozess, der Anfragen signiert, sodass Du Secretive nicht durchgehend geöffnet haben musst.\n\n**Secretive wird nicht richtig funktionieren, wenn der Agent nicht installiert und ausgeführt wird.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"el" : {
|
"el" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Το SecretAgent είναι μια διεργασία που εκτελείται στο παρασκήνιο για να υπογράφει αιτήματα. Δεν χρειάζεται να κρατάτε παράθυρο του Secretive ανοιχτό συνεχώς.\n\n**Το Secretive δεν θα μπορεί να λειτουργήσει σωστά εκτός και αν o Agent είναι εγκατεστημένος και εκτελείται.**"
|
"value" : "Το SecretAgent είναι μια διεργασία που εκτελείται στο παρασκήνιο για να υπογράφει αιτήματα. Δεν χρειάζεται να κρατάτε παράθυρο του Secretive ανοιχτό συνεχώς.\n\n**Το Secretive δεν θα μπορεί να λειτουργήσει σωστά εκτός και αν o Agent είναι εγκατεστημένος και εκτελείται.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "translated",
|
||||||
"value" : "SecretAgent is a process that runs in the background to sign requests, so you don't need to keep Secretive open all the time.\n\n**Secretive will not be able to function properly unless the agent is installed and running.**"
|
"value" : "SecretAgent is a process that runs in the background to sign requests, so you don't need to keep Secretive open all the time.\n\n**Secretive will not be able to function properly unless the agent is configured.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es" : {
|
"es" : {
|
||||||
@@ -2829,13 +2644,13 @@
|
|||||||
},
|
},
|
||||||
"fi" : {
|
"fi" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent-agenttiprosessi toimii taustalla ja allekirjoittaa pyyntöjä, jotta Secretive-käyttöliittymää ei tarvitse pitää aina auki.\n\n**Secretive ei toimi oikein, jollei agentti ole asennettu ja käynnissä.**"
|
"value" : "SecretAgent-agenttiprosessi toimii taustalla ja allekirjoittaa pyyntöjä, jotta Secretive-käyttöliittymää ei tarvitse pitää aina auki.\n\n**Secretive ei toimi oikein, jollei agentti ole asennettu ja käynnissä.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent est un processus qui s'exécute en arrière-plan pour signer les demandes, de sorte que vous n'ayez pas besoin de garder Secretive ouvert en permanence.\n\n**Secretive ne pourra pas fonctionner correctement sans que l'agent soit installé et fonctionne.**"
|
"value" : "SecretAgent est un processus qui s'exécute en arrière-plan pour signer les demandes, de sorte que vous n'ayez pas besoin de garder Secretive ouvert en permanence.\n\n**Secretive ne pourra pas fonctionner correctement sans que l'agent soit installé et fonctionne.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2859,13 +2674,13 @@
|
|||||||
},
|
},
|
||||||
"ja" : {
|
"ja" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgentはバックグラウンドで稼働し署名を行います。Secretiveアプリを常に実行する必要はありません。\n\n**Secretiveアプリはエージェントがインストールされて稼働しない限り正しく動作しません。**"
|
"value" : "SecretAgentはバックグラウンドで稼働し署名を行います。Secretiveアプリを常に実行する必要はありません。\n\n**Secretiveアプリはエージェントがインストールされて稼働しない限り正しく動作しません。**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ko" : {
|
"ko" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent는 백그라운드에서 실행되어 요청에 서명하는 프로세스이므로 Secretive를 항상 열어 둘 필요는 없습니다.\n\n**Secretive 에이전트가 설치되어 실행 중이어야 Secretive가 제대로 작동합니다.**"
|
"value" : "SecretAgent는 백그라운드에서 실행되어 요청에 서명하는 프로세스이므로 Secretive를 항상 열어 둘 필요는 없습니다.\n\n**Secretive 에이전트가 설치되어 실행 중이어야 Secretive가 제대로 작동합니다.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2883,7 +2698,7 @@
|
|||||||
},
|
},
|
||||||
"pl" : {
|
"pl" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent to proces działający w tle, który podpisuje żądania, dzięki czemu nie musisz mieć otwartego programu Secretive przez cały czas.\n\n**Program Secretive nie będzie działał poprawnie, jeśli agent nie zostanie zainstalowany i uruchomiony.**"
|
"value" : "SecretAgent to proces działający w tle, który podpisuje żądania, dzięki czemu nie musisz mieć otwartego programu Secretive przez cały czas.\n\n**Program Secretive nie będzie działał poprawnie, jeśli agent nie zostanie zainstalowany i uruchomiony.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2895,7 +2710,7 @@
|
|||||||
},
|
},
|
||||||
"pt-BR" : {
|
"pt-BR" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent é um processo que é executado em segundo plano para assinar pedidos, então não há necessidade de manter Secretive aberto o tempo todo.\n\n**Secretive não funcionará corretamente a menos que o agente esteja instalado e executando.**"
|
"value" : "SecretAgent é um processo que é executado em segundo plano para assinar pedidos, então não há necessidade de manter Secretive aberto o tempo todo.\n\n**Secretive não funcionará corretamente a menos que o agente esteja instalado e executando.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2907,7 +2722,7 @@
|
|||||||
},
|
},
|
||||||
"ru" : {
|
"ru" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent это процесс, который работает в фоне чтобы подписывать запросы. Так Вам не придется все время держать Secretive открытым.\n\n**Secretive не сможет нормально функционировать, пока агент не установлен и не запущен.**"
|
"value" : "SecretAgent это процесс, который работает в фоне чтобы подписывать запросы. Так Вам не придется все время держать Secretive открытым.\n\n**Secretive не сможет нормально функционировать, пока агент не установлен и не запущен.**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2943,19 +2758,19 @@
|
|||||||
},
|
},
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent是个在后台处理签名请求的进程,让您无需将Secretive一直保持在前台。\n\n**需要安装并运行Agent,否则Secretive无法正常工作。**"
|
"value" : "SecretAgent是个在后台处理签名请求的进程,让您无需将Secretive一直保持在前台。\n\n**需要安装并运行Agent,否则Secretive无法正常工作。**"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-Hant" : {
|
"zh-Hant" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent是個在後台處理簽名請求的行程,讓您無需將Secretive一直保持在前台。\n\n**需要安裝並執行Agent,否則Secretive無法正常工作。**"
|
"value" : "SecretAgent是個在後台處理簽名請求的行程,讓您無需將Secretive一直保持在前台。\n\n**需要安裝並執行Agent,否則Secretive無法正常工作。**"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_not_running_notice_title" : {
|
"agent_not_configured_notice_title" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"af" : {
|
"af" : {
|
||||||
@@ -2972,7 +2787,7 @@
|
|||||||
},
|
},
|
||||||
"ca" : {
|
"ca" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent inactiu"
|
"value" : "Agent inactiu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2990,20 +2805,20 @@
|
|||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent wird Nicht Ausgeführt"
|
"value" : "Agent wird Nicht Ausgeführt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"el" : {
|
"el" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Ο Agent Δεν Εκτελείται"
|
"value" : "Ο Agent Δεν Εκτελείται"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "translated",
|
||||||
"value" : "Agent Is Not Running"
|
"value" : "Agent Is Not Configured"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es" : {
|
"es" : {
|
||||||
@@ -3014,13 +2829,13 @@
|
|||||||
},
|
},
|
||||||
"fi" : {
|
"fi" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agentti ei ole käynnissä"
|
"value" : "Agentti ei ole käynnissä"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "L'agent n'est pas actif"
|
"value" : "L'agent n'est pas actif"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3038,19 +2853,19 @@
|
|||||||
},
|
},
|
||||||
"it" : {
|
"it" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent non è in esecuzione"
|
"value" : "Secret Agent non è in esecuzione"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ja" : {
|
"ja" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "エージェントが稼働していません"
|
"value" : "エージェントが稼働していません"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ko" : {
|
"ko" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent가 실행되고 있지 않음"
|
"value" : "Agent가 실행되고 있지 않음"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3068,7 +2883,7 @@
|
|||||||
},
|
},
|
||||||
"pl" : {
|
"pl" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent nie jest uruchomiony"
|
"value" : "Agent nie jest uruchomiony"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3080,7 +2895,7 @@
|
|||||||
},
|
},
|
||||||
"pt-BR" : {
|
"pt-BR" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent não está rodando"
|
"value" : "Agent não está rodando"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3092,7 +2907,7 @@
|
|||||||
},
|
},
|
||||||
"ru" : {
|
"ru" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Агент не запущен"
|
"value" : "Агент не запущен"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3128,19 +2943,19 @@
|
|||||||
},
|
},
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent尚未运行"
|
"value" : "Agent尚未运行"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-Hant" : {
|
"zh-Hant" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent尚未執行"
|
"value" : "Agent尚未執行"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_running_notice_detail_description" : {
|
"agent_ready_notice_detail_description" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"af" : {
|
"af" : {
|
||||||
@@ -3325,7 +3140,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_running_notice_detail_title" : {
|
"agent_ready_notice_detail_title" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"af" : {
|
"af" : {
|
||||||
@@ -3342,7 +3157,7 @@
|
|||||||
},
|
},
|
||||||
"ca" : {
|
"ca" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "L'agent secret està actiu"
|
"value" : "L'agent secret està actiu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3360,20 +3175,20 @@
|
|||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent wird Ausgeführt"
|
"value" : "Secret Agent wird Ausgeführt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"el" : {
|
"el" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Ο Πράκτορας εκτελείται"
|
"value" : "Ο Πράκτορας εκτελείται"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "translated",
|
||||||
"value" : "Secret Agent is Running"
|
"value" : "Secret Agent is Ready"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es" : {
|
"es" : {
|
||||||
@@ -3384,13 +3199,13 @@
|
|||||||
},
|
},
|
||||||
"fi" : {
|
"fi" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent on käynnissä"
|
"value" : "SecretAgent on käynnissä"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent est actif"
|
"value" : "SecretAgent est actif"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3408,19 +3223,19 @@
|
|||||||
},
|
},
|
||||||
"it" : {
|
"it" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent è in esecuzione"
|
"value" : "Secret Agent è in esecuzione"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ja" : {
|
"ja" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "エージェントは稼働中"
|
"value" : "エージェントは稼働中"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ko" : {
|
"ko" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent가 실행 중입니다."
|
"value" : "Secret Agent가 실행 중입니다."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3438,7 +3253,7 @@
|
|||||||
},
|
},
|
||||||
"pl" : {
|
"pl" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent jest uruchomiony"
|
"value" : "Secret Agent jest uruchomiony"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3450,7 +3265,7 @@
|
|||||||
},
|
},
|
||||||
"pt-BR" : {
|
"pt-BR" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent está rodando"
|
"value" : "Secret Agent está rodando"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3462,7 +3277,7 @@
|
|||||||
},
|
},
|
||||||
"ru" : {
|
"ru" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "SecretAgent запущен"
|
"value" : "SecretAgent запущен"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3498,19 +3313,19 @@
|
|||||||
},
|
},
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent运行中"
|
"value" : "Secret Agent运行中"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-Hant" : {
|
"zh-Hant" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Secret Agent執行中"
|
"value" : "Secret Agent執行中"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"agent_running_notice_title" : {
|
"agent_ready_notice_title" : {
|
||||||
"extractionState" : "manual",
|
"extractionState" : "manual",
|
||||||
"localizations" : {
|
"localizations" : {
|
||||||
"af" : {
|
"af" : {
|
||||||
@@ -3527,7 +3342,7 @@
|
|||||||
},
|
},
|
||||||
"ca" : {
|
"ca" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent actiu"
|
"value" : "Agent actiu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3545,7 +3360,7 @@
|
|||||||
},
|
},
|
||||||
"de" : {
|
"de" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent wird Ausgeführt"
|
"value" : "Agent wird Ausgeführt"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3557,8 +3372,8 @@
|
|||||||
},
|
},
|
||||||
"en" : {
|
"en" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "new",
|
"state" : "translated",
|
||||||
"value" : "Agent is Running"
|
"value" : "Agent is Ready"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es" : {
|
"es" : {
|
||||||
@@ -3569,13 +3384,13 @@
|
|||||||
},
|
},
|
||||||
"fi" : {
|
"fi" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agentti on käynnissä"
|
"value" : "Agentti on käynnissä"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr" : {
|
"fr" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "L'agent est actif"
|
"value" : "L'agent est actif"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3593,19 +3408,19 @@
|
|||||||
},
|
},
|
||||||
"it" : {
|
"it" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent è in esecuzione"
|
"value" : "Agent è in esecuzione"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ja" : {
|
"ja" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "エージェントは稼働中"
|
"value" : "エージェントは稼働中"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ko" : {
|
"ko" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent가 실행중"
|
"value" : "Agent가 실행중"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3623,7 +3438,7 @@
|
|||||||
},
|
},
|
||||||
"pl" : {
|
"pl" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent jest uruchomiony"
|
"value" : "Agent jest uruchomiony"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3635,7 +3450,7 @@
|
|||||||
},
|
},
|
||||||
"pt-BR" : {
|
"pt-BR" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent está rodando"
|
"value" : "Agent está rodando"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3647,7 +3462,7 @@
|
|||||||
},
|
},
|
||||||
"ru" : {
|
"ru" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Агент запущен"
|
"value" : "Агент запущен"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3683,13 +3498,13 @@
|
|||||||
},
|
},
|
||||||
"zh-Hans" : {
|
"zh-Hans" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent运行中"
|
"value" : "Agent运行中"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zh-Hant" : {
|
"zh-Hant" : {
|
||||||
"stringUnit" : {
|
"stringUnit" : {
|
||||||
"state" : "translated",
|
"state" : "needs_review",
|
||||||
"value" : "Agent執行中"
|
"value" : "Agent執行中"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,11 +36,11 @@ import XPCWrappers
|
|||||||
self.currentVersion = currentVersion
|
self.currentVersion = currentVersion
|
||||||
Task {
|
Task {
|
||||||
if checkOnLaunch {
|
if checkOnLaunch {
|
||||||
try await checkForUpdates()
|
try? await checkForUpdates()
|
||||||
}
|
}
|
||||||
while !Task.isCancelled {
|
while !Task.isCancelled {
|
||||||
try? await Task.sleep(for: .seconds(Int(checkFrequency)))
|
try? await Task.sleep(for: .seconds(Int(checkFrequency)))
|
||||||
try await checkForUpdates()
|
try? await checkForUpdates()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import OSLog
|
import OSLog
|
||||||
import SecretKit
|
import SecretKit
|
||||||
|
import launch
|
||||||
|
|
||||||
/// A controller that manages socket configuration and request dispatching.
|
/// A controller that manages socket configuration and request dispatching.
|
||||||
public struct SocketController {
|
public struct SocketController {
|
||||||
@@ -12,7 +13,8 @@ public struct SocketController {
|
|||||||
private let sessionsContinuation: AsyncStream<Session>.Continuation
|
private let sessionsContinuation: AsyncStream<Session>.Continuation
|
||||||
|
|
||||||
/// The active SocketPort. Must be retained to be kept valid.
|
/// The active SocketPort. Must be retained to be kept valid.
|
||||||
private let port: SocketPort
|
/// Only applicable for legacy non-launchd sockets.
|
||||||
|
private let port: SocketPort?
|
||||||
|
|
||||||
/// The FileHandle for the main socket.
|
/// The FileHandle for the main socket.
|
||||||
private let fileHandle: FileHandle
|
private let fileHandle: FileHandle
|
||||||
@@ -23,19 +25,41 @@ public struct SocketController {
|
|||||||
/// Tracer which determines who originates a socket connection.
|
/// Tracer which determines who originates a socket connection.
|
||||||
private let requestTracer = SigningRequestTracer()
|
private let requestTracer = SigningRequestTracer()
|
||||||
|
|
||||||
/// Initializes a socket controller with a specified path.
|
public enum Socket {
|
||||||
/// - Parameter path: The path to use as a socket.
|
case launchd(String)
|
||||||
public init(path: String) {
|
case path(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(_ socket: Socket) {
|
||||||
(sessions, sessionsContinuation) = AsyncStream<Session>.makeStream()
|
(sessions, sessionsContinuation) = AsyncStream<Session>.makeStream()
|
||||||
logger.debug("Socket controller setting up at \(path)")
|
switch socket {
|
||||||
if let _ = try? FileManager.default.removeItem(atPath: path) {
|
case .path(let path):
|
||||||
logger.debug("Socket controller removed existing socket")
|
logger.debug("Socket controller setting up at \(path)")
|
||||||
|
if let _ = try? FileManager.default.removeItem(atPath: path) {
|
||||||
|
logger.debug("Socket controller removed existing socket")
|
||||||
|
}
|
||||||
|
let exists = FileManager.default.fileExists(atPath: path)
|
||||||
|
assert(!exists)
|
||||||
|
logger.debug("Socket controller path is clear")
|
||||||
|
let port = SocketPort(path: path)
|
||||||
|
fileHandle = FileHandle(fileDescriptor: port.socket, closeOnDealloc: true)
|
||||||
|
self.port = port
|
||||||
|
logger.debug("Socket listening at \(path)")
|
||||||
|
case .launchd(let name):
|
||||||
|
logger.debug("Socket controller setting for launchd-controlled socket \(name)")
|
||||||
|
port = nil
|
||||||
|
var fileDescriptors: UnsafeMutablePointer<Int32>? = nil
|
||||||
|
var count = 0
|
||||||
|
let result = unsafe launch_activate_socket(name, &fileDescriptors, &count)
|
||||||
|
guard result == kOSReturnSuccess, let socket = unsafe fileDescriptors?.pointee else {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
fileHandle = FileHandle(fileDescriptor: socket, closeOnDealloc: true)
|
||||||
}
|
}
|
||||||
let exists = FileManager.default.fileExists(atPath: path)
|
listen()
|
||||||
assert(!exists)
|
}
|
||||||
logger.debug("Socket controller path is clear")
|
|
||||||
port = SocketPort(path: path)
|
func listen() {
|
||||||
fileHandle = FileHandle(fileDescriptor: port.socket, closeOnDealloc: true)
|
|
||||||
Task { @MainActor [fileHandle, sessionsContinuation, logger] in
|
Task { @MainActor [fileHandle, sessionsContinuation, logger] in
|
||||||
// Create the sequence before triggering the notification to
|
// Create the sequence before triggering the notification to
|
||||||
// ensure it will not be missed.
|
// ensure it will not be missed.
|
||||||
@@ -51,7 +75,7 @@ public struct SocketController {
|
|||||||
fileHandle.acceptConnectionInBackgroundAndNotify()
|
fileHandle.acceptConnectionInBackgroundAndNotify()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug("Socket listening at \(path)")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -94,7 +118,7 @@ extension SocketController {
|
|||||||
guard !data.isEmpty else {
|
guard !data.isEmpty else {
|
||||||
logger.debug("Socket controller received empty data, ending continuation.")
|
logger.debug("Socket controller received empty data, ending continuation.")
|
||||||
messagesContinuation.finish()
|
messagesContinuation.finish()
|
||||||
try fileHandle.close()
|
try? fileHandle.close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
messagesContinuation.yield(data)
|
messagesContinuation.yield(data)
|
||||||
@@ -125,14 +149,7 @@ private extension SocketPort {
|
|||||||
|
|
||||||
convenience init(path: String) {
|
convenience init(path: String) {
|
||||||
var addr = sockaddr_un()
|
var addr = sockaddr_un()
|
||||||
|
let length = addr.setPath(path)
|
||||||
let length = unsafe withUnsafeMutablePointer(to: &addr.sun_path.0) { pointer in
|
|
||||||
unsafe path.withCString { cstring in
|
|
||||||
let len = unsafe strlen(cstring)
|
|
||||||
unsafe strncpy(pointer, cstring, len)
|
|
||||||
return len
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// This doesn't seem to be _strictly_ neccessary with SocketPort.
|
// This doesn't seem to be _strictly_ neccessary with SocketPort.
|
||||||
// but just for good form.
|
// but just for good form.
|
||||||
addr.sun_family = sa_family_t(AF_UNIX)
|
addr.sun_family = sa_family_t(AF_UNIX)
|
||||||
@@ -144,3 +161,31 @@ private extension SocketPort {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension sockaddr_un {
|
||||||
|
|
||||||
|
mutating func setPath(_ path: String) -> Int {
|
||||||
|
#if compiler(<6.4)
|
||||||
|
unsafe withUnsafeMutablePointer(to: &self.sun_path.0) { pointer in
|
||||||
|
unsafe path.withCString { cstring in
|
||||||
|
let len = unsafe strlen(cstring)
|
||||||
|
unsafe strncpy(pointer, cstring, len)
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
withUnsafeMutablePointer(to: &self.sun_path.0) { pointer in
|
||||||
|
path.withCString { cstring in
|
||||||
|
let len = unsafe strlen(cstring)
|
||||||
|
unsafe strncpy(pointer, cstring, len)
|
||||||
|
return len
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes the header from `UnsafeMutablePointer<UnsafeMutablePointer<Int32>?>?` -> `UnsafeMutablePointer<UnsafeMutablePointer<Int32>?>!`
|
||||||
|
@_silgen_name("launch_activate_socket")
|
||||||
|
func launch_activate_socket(_ name: UnsafePointer<CChar>, _ fds: UnsafeMutablePointer<UnsafeMutablePointer<Int32>?>!, _ cnt: UnsafeMutablePointer<Int>!) -> Int32
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ extension ProcessInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
guard let value = SecTaskCopyValueForEntitlement(task, "com.apple.developer.team-identifier" as CFString, nil) as? String else {
|
guard let value = SecTaskCopyValueForEntitlement(task, "com.apple.developer.team-identifier" as CFString, nil) as? String else {
|
||||||
assertionFailure("SecTaskCopyValueForEntitlement(com.apple.developer.team-identifier) failed")
|
// assertionFailure("SecTaskCopyValueForEntitlement(com.apple.developer.team-identifier) failed")
|
||||||
return fallbackTeamID
|
return fallbackTeamID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,10 +41,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
@MainActor private lazy var agent: Agent = {
|
@MainActor private lazy var agent: Agent = {
|
||||||
Agent(storeList: storeList, certificateStore: EnvironmentValues._certificateStore, witness: notifier)
|
Agent(storeList: storeList, certificateStore: EnvironmentValues._certificateStore, witness: notifier)
|
||||||
}()
|
}()
|
||||||
private lazy var socketController: SocketController = {
|
private var shutdownTask: Task<Void, Error>?
|
||||||
let path = URL.socketPath as String
|
private let socketController = SocketController(.launchd("SecureListener"))
|
||||||
return SocketController(path: path)
|
|
||||||
}()
|
|
||||||
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "AppDelegate")
|
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "AppDelegate")
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||||
@@ -52,16 +50,17 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
Task {
|
Task {
|
||||||
for await session in socketController.sessions {
|
for await session in socketController.sessions {
|
||||||
Task {
|
Task {
|
||||||
let inputParser = try await XPCAgentInputParser()
|
|
||||||
do {
|
do {
|
||||||
|
let inputParser = try await XPCAgentInputParser()
|
||||||
for await message in session.messages {
|
for await message in session.messages {
|
||||||
let request = try await inputParser.parse(data: message)
|
let request = try await inputParser.parse(data: message)
|
||||||
let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
let agentResponse = await agent.handle(request: request, provenance: session.provenance)
|
||||||
try session.write(agentResponse)
|
try session.write(agentResponse)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
try session.close()
|
try? session.close()
|
||||||
}
|
}
|
||||||
|
startCountdownClock()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,5 +89,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startCountdownClock() {
|
||||||
|
// FIXME: ACCOUNT FOR STORED AUTH
|
||||||
|
logger.log("Beginning countdown clock")
|
||||||
|
shutdownTask?.cancel()
|
||||||
|
shutdownTask = Task { [logger] in
|
||||||
|
try await Task.sleep(for: .seconds(30))
|
||||||
|
logger.log("Shutting down")
|
||||||
|
await NSApplication.shared.terminate(nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
<string>1</string>
|
<string>1</string>
|
||||||
<key>com.apple.security.hardened-process.hardened-heap</key>
|
<key>com.apple.security.hardened-process.hardened-heap</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>com.apple.security.smartcard</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
|
<key>com.apple.security.hardened-process.platform-restrictions-string</key>
|
||||||
<string>2</string>
|
<string>2</string>
|
||||||
|
<key>com.apple.security.smartcard</key>
|
||||||
|
<true/>
|
||||||
<key>keychain-access-groups</key>
|
<key>keychain-access-groups</key>
|
||||||
<array>
|
<array>
|
||||||
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
|
<string>$(AppIdentifierPrefix)com.maxgoedjen.Secretive</string>
|
||||||
|
|||||||
@@ -21,11 +21,12 @@
|
|||||||
5008C23E2E525D8900507AC2 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 5008C23D2E525D8200507AC2 /* Localizable.xcstrings */; };
|
5008C23E2E525D8900507AC2 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 5008C23D2E525D8200507AC2 /* Localizable.xcstrings */; };
|
||||||
5008C2412E52D18700507AC2 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 5008C23D2E525D8200507AC2 /* Localizable.xcstrings */; };
|
5008C2412E52D18700507AC2 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 5008C23D2E525D8200507AC2 /* Localizable.xcstrings */; };
|
||||||
501421622781262300BBAA70 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 501421612781262300BBAA70 /* Brief */; };
|
501421622781262300BBAA70 /* Brief in Frameworks */ = {isa = PBXBuildFile; productRef = 501421612781262300BBAA70 /* Brief */; };
|
||||||
501421652781268000BBAA70 /* SecretAgent.app in CopyFiles */ = {isa = PBXBuildFile; fileRef = 50A3B78A24026B7500D209EA /* SecretAgent.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
501421652781268000BBAA70 /* SecretAgent.app in Copy SecretAgent */ = {isa = PBXBuildFile; fileRef = 50A3B78A24026B7500D209EA /* SecretAgent.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
50153E20250AFCB200525160 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E1F250AFCB200525160 /* UpdateView.swift */; };
|
50153E20250AFCB200525160 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E1F250AFCB200525160 /* UpdateView.swift */; };
|
||||||
50153E22250DECA300525160 /* SecretListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListItemView.swift */; };
|
50153E22250DECA300525160 /* SecretListItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListItemView.swift */; };
|
||||||
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501578122E6C0479004A37D0 /* XPCInputParser.swift */; };
|
501578132E6C0479004A37D0 /* XPCInputParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 501578122E6C0479004A37D0 /* XPCInputParser.swift */; };
|
||||||
5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; };
|
5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; };
|
||||||
|
502452F92FE2026E009EE753 /* com.maxgoedjen.Secretive.SecretAgent.plist in Copy SecretAgent plist */ = {isa = PBXBuildFile; fileRef = 502452F32FE1FF89009EE753 /* com.maxgoedjen.Secretive.SecretAgent.plist */; };
|
||||||
504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; };
|
504788F22E681F3A00B4556F /* Instructions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F12E681F3A00B4556F /* Instructions.swift */; };
|
||||||
504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; };
|
504788F42E681F6900B4556F /* ToolConfigurationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F32E681F6900B4556F /* ToolConfigurationView.swift */; };
|
||||||
504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
|
504788F62E68206F00B4556F /* GettingStartedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 504788F52E68206F00B4556F /* GettingStartedView.swift */; };
|
||||||
@@ -181,6 +182,17 @@
|
|||||||
name = "Embed XPC Services";
|
name = "Embed XPC Services";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
502452F82FE2024D009EE753 /* Copy SecretAgent plist */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = Contents/Library/LaunchAgents;
|
||||||
|
dstSubfolderSpec = 1;
|
||||||
|
files = (
|
||||||
|
502452F92FE2026E009EE753 /* com.maxgoedjen.Secretive.SecretAgent.plist in Copy SecretAgent plist */,
|
||||||
|
);
|
||||||
|
name = "Copy SecretAgent plist";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
50617DBF23FCE4AB0099B055 /* Embed Frameworks */ = {
|
50617DBF23FCE4AB0099B055 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -201,14 +213,15 @@
|
|||||||
name = "Embed Frameworks";
|
name = "Embed Frameworks";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
50C385AF240E438B00AF2719 /* CopyFiles */ = {
|
50C385AF240E438B00AF2719 /* Copy SecretAgent */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
dstPath = Contents/Library/LoginItems;
|
dstPath = Contents/Library/LoginItems;
|
||||||
dstSubfolderSpec = 1;
|
dstSubfolderSpec = 1;
|
||||||
files = (
|
files = (
|
||||||
501421652781268000BBAA70 /* SecretAgent.app in CopyFiles */,
|
501421652781268000BBAA70 /* SecretAgent.app in Copy SecretAgent */,
|
||||||
);
|
);
|
||||||
|
name = "Copy SecretAgent";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
@@ -224,6 +237,7 @@
|
|||||||
50153E21250DECA300525160 /* SecretListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretListItemView.swift; sourceTree = "<group>"; };
|
50153E21250DECA300525160 /* SecretListItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecretListItemView.swift; sourceTree = "<group>"; };
|
||||||
501578122E6C0479004A37D0 /* XPCInputParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCInputParser.swift; sourceTree = "<group>"; };
|
501578122E6C0479004A37D0 /* XPCInputParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCInputParser.swift; sourceTree = "<group>"; };
|
||||||
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
|
5018F54E24064786002EB505 /* Notifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Notifier.swift; sourceTree = "<group>"; };
|
||||||
|
502452F32FE1FF89009EE753 /* com.maxgoedjen.Secretive.SecretAgent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = com.maxgoedjen.Secretive.SecretAgent.plist; sourceTree = "<group>"; };
|
||||||
504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; };
|
504788F12E681F3A00B4556F /* Instructions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Instructions.swift; sourceTree = "<group>"; };
|
||||||
504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; };
|
504788F32E681F6900B4556F /* ToolConfigurationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolConfigurationView.swift; sourceTree = "<group>"; };
|
||||||
504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
|
504788F52E68206F00B4556F /* GettingStartedView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GettingStartedView.swift; sourceTree = "<group>"; };
|
||||||
@@ -445,6 +459,7 @@
|
|||||||
508BF28D25B4F005009EFB7E /* InternetAccessPolicy.plist */,
|
508BF28D25B4F005009EFB7E /* InternetAccessPolicy.plist */,
|
||||||
50E4C4C72E777E4200C73783 /* AppIcon.icon */,
|
50E4C4C72E777E4200C73783 /* AppIcon.icon */,
|
||||||
50617D8F23FCE48E0099B055 /* Secretive.entitlements */,
|
50617D8F23FCE48E0099B055 /* Secretive.entitlements */,
|
||||||
|
502452F32FE1FF89009EE753 /* com.maxgoedjen.Secretive.SecretAgent.plist */,
|
||||||
5008C23D2E525D8200507AC2 /* Localizable.xcstrings */,
|
5008C23D2E525D8200507AC2 /* Localizable.xcstrings */,
|
||||||
50617D8823FCE48E0099B055 /* Preview Content */,
|
50617D8823FCE48E0099B055 /* Preview Content */,
|
||||||
);
|
);
|
||||||
@@ -569,7 +584,8 @@
|
|||||||
50617D7C23FCE48D0099B055 /* Frameworks */,
|
50617D7C23FCE48D0099B055 /* Frameworks */,
|
||||||
50617D7D23FCE48D0099B055 /* Resources */,
|
50617D7D23FCE48D0099B055 /* Resources */,
|
||||||
50617DBF23FCE4AB0099B055 /* Embed Frameworks */,
|
50617DBF23FCE4AB0099B055 /* Embed Frameworks */,
|
||||||
50C385AF240E438B00AF2719 /* CopyFiles */,
|
50C385AF240E438B00AF2719 /* Copy SecretAgent */,
|
||||||
|
502452F82FE2024D009EE753 /* Copy SecretAgent plist */,
|
||||||
501577C92E6BC5B4004A37D0 /* Embed XPC Services */,
|
501577C92E6BC5B4004A37D0 /* Embed XPC Services */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
@@ -1523,7 +1539,7 @@
|
|||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -1560,7 +1576,7 @@
|
|||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
@@ -1598,7 +1614,7 @@
|
|||||||
ENABLE_APP_SANDBOX = YES;
|
ENABLE_APP_SANDBOX = YES;
|
||||||
ENABLE_ENHANCED_SECURITY = YES;
|
ENABLE_ENHANCED_SECURITY = YES;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
ENABLE_INCOMING_NETWORK_CONNECTIONS = NO;
|
ENABLE_INCOMING_NETWORK_CONNECTIONS = YES;
|
||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = NO;
|
||||||
ENABLE_POINTER_AUTHENTICATION = YES;
|
ENABLE_POINTER_AUTHENTICATION = YES;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
|
|||||||
@@ -70,7 +70,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
launchStyle = "0"
|
launchStyle = "1"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
debugDocumentVersioning = "YES"
|
debugDocumentVersioning = "YES"
|
||||||
|
|||||||
@@ -87,6 +87,9 @@
|
|||||||
ReferencedContainer = "container:Secretive.xcodeproj">
|
ReferencedContainer = "container:Secretive.xcodeproj">
|
||||||
</BuildableReference>
|
</BuildableReference>
|
||||||
</BuildableProductRunnable>
|
</BuildableProductRunnable>
|
||||||
|
<MetalAPIValidationSettings
|
||||||
|
isEnabled = "No">
|
||||||
|
</MetalAPIValidationSettings>
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
|||||||
@@ -1,14 +1,31 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
@unsafe @preconcurrency import ServiceManagement
|
||||||
import SecretKit
|
import SecretKit
|
||||||
import SecureEnclaveSecretKit
|
import SecureEnclaveSecretKit
|
||||||
import SmartCardSecretKit
|
import SmartCardSecretKit
|
||||||
import Brief
|
import Brief
|
||||||
import CertificateKit
|
import CertificateKit
|
||||||
|
|
||||||
|
@Observable
|
||||||
|
final class LaunchService: Sendable {
|
||||||
|
private let service = SMAppService.agent(plistName: "com.maxgoedjen.Secretive.SecretAgent.plist")
|
||||||
|
var status: SMAppService.Status {
|
||||||
|
service.status
|
||||||
|
}
|
||||||
|
|
||||||
|
func configure() {
|
||||||
|
try? service.unregister()
|
||||||
|
try! service.register()
|
||||||
|
}
|
||||||
|
|
||||||
|
func disable() {
|
||||||
|
try? service.unregister()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@main
|
@main
|
||||||
struct Secretive: App {
|
struct Secretive: App {
|
||||||
|
|
||||||
@Environment(\.agentLaunchController) var agentLaunchController
|
|
||||||
@Environment(\.justUpdatedChecker) var justUpdatedChecker
|
@Environment(\.justUpdatedChecker) var justUpdatedChecker
|
||||||
|
|
||||||
@SceneBuilder var body: some Scene {
|
@SceneBuilder var body: some Scene {
|
||||||
@@ -16,18 +33,8 @@ struct Secretive: App {
|
|||||||
ContentView()
|
ContentView()
|
||||||
.environment(EnvironmentValues._secretStoreList)
|
.environment(EnvironmentValues._secretStoreList)
|
||||||
.environment(EnvironmentValues._certificateStore)
|
.environment(EnvironmentValues._certificateStore)
|
||||||
.onReceive(NotificationCenter.default.publisher(for: NSApplication.didBecomeActiveNotification)) { _ in
|
.onAppear {
|
||||||
Task {
|
EnvironmentValues._launchService.configure()
|
||||||
@AppStorage("defaultsHasRunSetup") var hasRunSetup = false
|
|
||||||
@AppStorage("explicitlyDisabled") var explicitlyDisabled = false
|
|
||||||
guard hasRunSetup && !explicitlyDisabled else { return }
|
|
||||||
agentLaunchController.check()
|
|
||||||
guard !agentLaunchController.developmentBuild else { return }
|
|
||||||
if justUpdatedChecker.justUpdatedBuild || !agentLaunchController.running {
|
|
||||||
// Relaunch the agent, since it'll be running from earlier update still
|
|
||||||
try await agentLaunchController.forceLaunch()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.commands {
|
.commands {
|
||||||
@@ -115,6 +122,9 @@ extension EnvironmentValues {
|
|||||||
private static let _justUpdatedChecker = JustUpdatedChecker()
|
private static let _justUpdatedChecker = JustUpdatedChecker()
|
||||||
@Entry var justUpdatedChecker: any JustUpdatedCheckerProtocol = _justUpdatedChecker
|
@Entry var justUpdatedChecker: any JustUpdatedCheckerProtocol = _justUpdatedChecker
|
||||||
|
|
||||||
|
fileprivate static let _launchService = LaunchService()
|
||||||
|
@Entry var launchService: LaunchService = _launchService
|
||||||
|
|
||||||
@MainActor var secretStoreList: SecretStoreList {
|
@MainActor var secretStoreList: SecretStoreList {
|
||||||
EnvironmentValues._secretStoreList
|
EnvironmentValues._secretStoreList
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import SwiftUI
|
|||||||
|
|
||||||
struct AgentStatusView: View {
|
struct AgentStatusView: View {
|
||||||
|
|
||||||
@Environment(\.agentLaunchController) private var agentLaunchController: any AgentLaunchControllerProtocol
|
@Environment(\.launchService) private var launchService
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if agentLaunchController.running {
|
if launchService.status == .enabled {
|
||||||
AgentRunningView()
|
AgentRunningView()
|
||||||
} else {
|
} else {
|
||||||
AgentNotRunningView()
|
AgentNotRunningView()
|
||||||
@@ -14,54 +14,53 @@ struct AgentStatusView: View {
|
|||||||
}
|
}
|
||||||
struct AgentRunningView: View {
|
struct AgentRunningView: View {
|
||||||
|
|
||||||
@Environment(\.agentLaunchController) private var agentLaunchController: any AgentLaunchControllerProtocol
|
@Environment(\.launchService) private var launchService
|
||||||
@AppStorage("explicitlyDisabled") var explicitlyDisabled = false
|
@AppStorage("explicitlyDisabled") var explicitlyDisabled = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
if let process = agentLaunchController.process {
|
// if let process = agentLaunchController.process {
|
||||||
ConfigurationItemView(
|
// ConfigurationItemView(
|
||||||
title: .agentDetailsLocationTitle,
|
// title: .agentDetailsLocationTitle,
|
||||||
value: process.bundleURL!.path(),
|
// value: process.bundleURL!.path(),
|
||||||
action: .revealInFinder(process.bundleURL!.path()),
|
// action: .revealInFinder(process.bundleURL!.path()),
|
||||||
)
|
// )
|
||||||
ConfigurationItemView(
|
ConfigurationItemView(
|
||||||
title: .agentDetailsSocketPathTitle,
|
title: .agentDetailsSocketPathTitle,
|
||||||
value: URL.socketPath,
|
value: URL.socketPath,
|
||||||
action: .copy(URL.socketPath),
|
action: .copy(URL.socketPath),
|
||||||
)
|
)
|
||||||
ConfigurationItemView(
|
// ConfigurationItemView(
|
||||||
title: .agentDetailsVersionTitle,
|
// title: .agentDetailsVersionTitle,
|
||||||
value: Bundle(url: process.bundleURL!)!.infoDictionary!["CFBundleShortVersionString"] as! String
|
// value: Bundle(url: process.bundleURL!)!.infoDictionary!["CFBundleShortVersionString"] as! String
|
||||||
)
|
// )
|
||||||
if let launchDate = process.launchDate {
|
// if let launchDate = process.launchDate {
|
||||||
ConfigurationItemView(
|
// ConfigurationItemView(
|
||||||
title: .agentDetailsRunningSinceTitle,
|
// title: .agentDetailsRunningSinceTitle,
|
||||||
value: launchDate.formatted()
|
// value: launchDate.formatted()
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} header: {
|
} header: {
|
||||||
Text(.agentRunningNoticeDetailTitle)
|
Text(.agentReadyNoticeDetailTitle)
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.padding(.top)
|
.padding(.top)
|
||||||
} footer: {
|
} footer: {
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
Text(.agentRunningNoticeDetailDescription)
|
Text(.agentReadyNoticeDetailDescription)
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
Spacer()
|
||||||
Menu(.agentDetailsRestartAgentButton) {
|
Menu(.agentDetailsRestartAgentButton) {
|
||||||
Button(.agentDetailsDisableAgentButton) {
|
Button(.agentDetailsDisableAgentButton) {
|
||||||
Task {
|
Task {
|
||||||
explicitlyDisabled = true
|
explicitlyDisabled = true
|
||||||
try? await agentLaunchController
|
launchService.disable()
|
||||||
.uninstall()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} primaryAction: {
|
} primaryAction: {
|
||||||
Task {
|
Task {
|
||||||
try? await agentLaunchController.forceLaunch()
|
launchService.configure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +77,6 @@ struct AgentRunningView: View {
|
|||||||
|
|
||||||
struct AgentNotRunningView: View {
|
struct AgentNotRunningView: View {
|
||||||
|
|
||||||
@Environment(\.agentLaunchController) private var agentLaunchController
|
|
||||||
@State var triedRestart = false
|
@State var triedRestart = false
|
||||||
@State var loading = false
|
@State var loading = false
|
||||||
@AppStorage("explicitlyDisabled") var explicitlyDisabled = false
|
@AppStorage("explicitlyDisabled") var explicitlyDisabled = false
|
||||||
@@ -87,12 +85,12 @@ struct AgentNotRunningView: View {
|
|||||||
Form {
|
Form {
|
||||||
Section {
|
Section {
|
||||||
} header: {
|
} header: {
|
||||||
Text(.agentNotRunningNoticeTitle)
|
Text(.agentNotConfiguredNoticeTitle)
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.padding(.top)
|
.padding(.top)
|
||||||
} footer: {
|
} footer: {
|
||||||
VStack(alignment: .leading, spacing: 10) {
|
VStack(alignment: .leading, spacing: 10) {
|
||||||
Text(.agentNotRunningNoticeDetailDescription)
|
Text(.agentNotConfiguredNoticeDetailDescription)
|
||||||
HStack {
|
HStack {
|
||||||
if !triedRestart {
|
if !triedRestart {
|
||||||
Spacer()
|
Spacer()
|
||||||
@@ -100,14 +98,6 @@ struct AgentNotRunningView: View {
|
|||||||
explicitlyDisabled = false
|
explicitlyDisabled = false
|
||||||
guard !loading else { return }
|
guard !loading else { return }
|
||||||
loading = true
|
loading = true
|
||||||
Task {
|
|
||||||
try await agentLaunchController.forceLaunch()
|
|
||||||
loading = false
|
|
||||||
|
|
||||||
if !agentLaunchController.running {
|
|
||||||
triedRestart = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} label: {
|
} label: {
|
||||||
if !loading {
|
if !loading {
|
||||||
Text(.agentDetailsStartAgentButton)
|
Text(.agentDetailsStartAgentButton)
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ struct ContentView: View {
|
|||||||
@Environment(\.certificateStore) private var certificateStore
|
@Environment(\.certificateStore) private var certificateStore
|
||||||
@Environment(\.updater) private var updater
|
@Environment(\.updater) private var updater
|
||||||
@Environment(\.agentLaunchController) private var agentLaunchController
|
@Environment(\.agentLaunchController) private var agentLaunchController
|
||||||
|
@Environment(\.launchService) private var launchService
|
||||||
|
|
||||||
@AppStorage("defaultsHasRunSetup") private var hasRunSetup = false
|
@AppStorage("defaultsHasRunSetup") private var hasRunSetup = false
|
||||||
@State private var showingCreation = false
|
@State private var showingCreation = false
|
||||||
@@ -147,15 +148,15 @@ extension ContentView {
|
|||||||
showingAgentInfo = true
|
showingAgentInfo = true
|
||||||
}, label: {
|
}, label: {
|
||||||
HStack {
|
HStack {
|
||||||
if agentLaunchController.running {
|
if launchService.status == .enabled {
|
||||||
Text(.agentRunningNoticeTitle)
|
Text(.agentReadyNoticeTitle)
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
.foregroundColor(colorScheme == .light ? Color(white: 0.3) : .white)
|
.foregroundColor(colorScheme == .light ? Color(white: 0.3) : .white)
|
||||||
Circle()
|
Circle()
|
||||||
.frame(width: 10, height: 10)
|
.frame(width: 10, height: 10)
|
||||||
.foregroundColor(Color.green)
|
.foregroundColor(Color.green)
|
||||||
} else {
|
} else {
|
||||||
Text(.agentNotRunningNoticeTitle)
|
Text(.agentNotConfiguredNoticeTitle)
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
Circle()
|
Circle()
|
||||||
.frame(width: 10, height: 10)
|
.frame(width: 10, height: 10)
|
||||||
@@ -165,8 +166,8 @@ extension ContentView {
|
|||||||
})
|
})
|
||||||
.buttonStyle(
|
.buttonStyle(
|
||||||
ToolbarStatusButtonStyle(
|
ToolbarStatusButtonStyle(
|
||||||
lightColor: agentLaunchController.running ? .black.opacity(0.05) : .red.opacity(0.75),
|
lightColor: launchService.status == .enabled ? .black.opacity(0.05) : .red.opacity(0.75),
|
||||||
darkColor: agentLaunchController.running ? .white.opacity(0.05) : .red.opacity(0.5),
|
darkColor: launchService.status == .enabled ? .white.opacity(0.05) : .red.opacity(0.5),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.popover(isPresented: $showingAgentInfo, attachmentAnchor: attachmentAnchor, arrowEdge: .bottom) {
|
.popover(isPresented: $showingAgentInfo, attachmentAnchor: attachmentAnchor, arrowEdge: .bottom) {
|
||||||
|
|||||||
18
Sources/Secretive/com.maxgoedjen.Secretive.SecretAgent.plist
Normal file
18
Sources/Secretive/com.maxgoedjen.Secretive.SecretAgent.plist
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>Label</key>
|
||||||
|
<string>com.maxgoedjen.Secretive.SecretAgent</string>
|
||||||
|
<key>BundleProgram</key>
|
||||||
|
<string>Contents/Library/LoginItems/SecretAgent.app/Contents/MacOS/SecretAgent</string>
|
||||||
|
<key>Sockets</key>
|
||||||
|
<dict>
|
||||||
|
<key>SecureListener</key>
|
||||||
|
<dict>
|
||||||
|
<key>SecureSocketWithKey</key>
|
||||||
|
<string>SECRETAGENT_SOCK</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
Reference in New Issue
Block a user