Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
=========


## Version 48 (130) - 2026-04-04
- Switch between English, German, Spanish, French, Korean, Chinese, Japanese, Polish and Portuguese (Brazil)

## Version 47 (129) - 2026-04-01
- Switch between English, German, Spanish, French, Korean, Chinese, Japanese and Portuguese (Brazil)
- Keep-map button to play a generated map even if it does not meet difficulty settings
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG_de.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ Changelog Deutsch
=================


## Version 48 (2026-04-04)
- Jetzt in Englisch, Deutsch, Spanisch, Französisch, Koreanisch, Chinesisch, Japanisch, Polnisch und Portugiesisch (Brasilien)

## Version 47 (129)
- Jetzt in Englisch, Deutsch, Spanisch, Französisch, Koreanisch, Chinesisch, Japanisch und Portugiesisch (Brasilien)
- Map behalten-Button um eine generierte Map trotz nicht passender Schwierigkeit zu spielen
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "de.z11.roboyard"
minSdkVersion 21
targetSdkVersion 36
versionCode 129
versionName "47"
versionCode 130
versionName "48"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

Expand Down
30 changes: 30 additions & 0 deletions app/src/main/java/roboyard/ui/activities/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,13 @@ public void onNewIntent(Intent intent) {
/** Current supported deep-link protocol version. Increment when breaking changes are introduced. */
private static final int DEEPLINK_API_VERSION = 1;

// Size limits for deep-link map data to prevent denial-of-service via crafted links
private static final int DEEPLINK_MAX_WIDTH = 200;
private static final int DEEPLINK_MAX_HEIGHT = 200;
private static final int DEEPLINK_MAX_CELLS = 40_000;
private static final int DEEPLINK_MAX_ROBOTS = 50;
private static final int DEEPLINK_MAX_TARGETS = 50;

private void handleIntent(Intent intent) {
String action = intent.getAction();
Uri data = intent.getData();
Expand Down Expand Up @@ -290,6 +297,11 @@ private void handleIntent(Intent intent) {
if (mapData.startsWith("name:") || mapData.contains("mh") || mapData.contains("mv")) {
Timber.d("[DEEPLINK_FORMAT] Detected web format, converting to app format");
String convertedMapData = convertWebFormatToAppFormat(mapData);
if (convertedMapData == null) {
Timber.e("[DEEPLINK] Map data rejected: size limits exceeded");
android.widget.Toast.makeText(this, R.string.deeplink_map_too_large, android.widget.Toast.LENGTH_LONG).show();
return;
}
Timber.d("[DEEPLINK_CONVERT] Converted map data preview: %s",
convertedMapData.substring(0, Math.min(100, convertedMapData.length())));

Expand Down Expand Up @@ -372,6 +384,16 @@ private String convertWebFormatToAppFormat(String webFormatData) {
}
}
}

// Validate board dimensions before allocating any data structures
if (width <= 0 || height <= 0
|| width > DEEPLINK_MAX_WIDTH
|| height > DEEPLINK_MAX_HEIGHT
|| (long) width * height > DEEPLINK_MAX_CELLS) {
Timber.e("[DEEPLINK_CONVERT] Board dimensions out of range: %dx%d (max %dx%d, max cells %d)",
width, height, DEEPLINK_MAX_WIDTH, DEEPLINK_MAX_HEIGHT, DEEPLINK_MAX_CELLS);
return null;
}

// Start building the app format
appFormat.append("#MAPNAME:").append(mapName)
Expand All @@ -397,6 +419,10 @@ private String convertWebFormatToAppFormat(String webFormatData) {
for (String part : parts) {
if (part.startsWith("target_")) {
targetParts.add(part);
if (targetParts.size() > DEEPLINK_MAX_TARGETS) {
Timber.e("[DEEPLINK_CONVERT] Too many targets (max %d)", DEEPLINK_MAX_TARGETS);
return null;
}
}
}

Expand Down Expand Up @@ -510,6 +536,10 @@ private String convertWebFormatToAppFormat(String webFormatData) {
for (String part : parts) {
if (part.startsWith("robot_")) {
robotParts.add(part);
if (robotParts.size() > DEEPLINK_MAX_ROBOTS) {
Timber.e("[DEEPLINK_CONVERT] Too many robots (max %d)", DEEPLINK_MAX_ROBOTS);
return null;
}
}
}

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-de/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -802,4 +802,5 @@
<string name="settings_logout_confirm_message">Das Abmelden löscht alle lokalen Achievements, Level-Fortschritte, Spielhistorie und Streaks von diesem Gerät. Ihre Daten sind auf dem Server gespeichert und werden beim nächsten Login wiederhergestellt.</string>
<string name="settings_logging_out">Abmelden…</string>
<string name="needs_update_toast">Ihre App benötigt ein Update, um diese Funktion zu verwenden.</string>
<string name="deeplink_map_too_large">Diese Karte ist zu groß zum Öffnen (Größenlimits überschritten).</string>
</resources>
1 change: 1 addition & 0 deletions app/src/main/res/values-es/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@
<string name="settings_logout_confirm_message">Cerrar sesión borrará todos los logros locales, progreso de niveles, historial de juegos y rachas de este dispositivo. Tus datos están guardados en el servidor y se restaurarán en el próximo inicio de sesión.</string>
<string name="settings_logging_out">Cerrando sesión…</string>
<string name="needs_update_toast">Tu aplicación necesita una actualización para usar esta función.</string>
<string name="deeplink_map_too_large">Este mapa es demasiado grande para abrirse (supera los límites de tamaño).</string>
<string name="login_dialog_title">Iniciar Sesión en Roboyard</string>
<string name="login_dialog_email">Email</string>
<string name="login_dialog_email_or_username">Email, usuario o ID de usuario</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-fr/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@
<string name="settings_logout_confirm_message">La déconnexion effacera tous les succès locaux, la progression des niveaux, l\'historique des jeux et les séries de cet appareil. Vos données sont sauvegardées sur le serveur et seront restaurées à la prochaine connexion.</string>
<string name="settings_logging_out">Déconnexion…</string>
<string name="needs_update_toast">Votre application a besoin d\'une mise à jour pour utiliser cette fonctionnalité.</string>
<string name="deeplink_map_too_large">Cette carte est trop grande pour être ouverte (limites de taille dépassées).</string>
<string name="login_dialog_title">Connexion à Roboyard</string>
<string name="login_dialog_email">Email</string>
<string name="login_dialog_email_or_username">Email, nom d\'utilisateur ou ID utilisateur</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
<string name="settings_logout_confirm_message">ログアウトすると、このデバイスからすべてのローカル実績、レベル進行状況、ゲーム履歴、連続記録がクリアされます。データはサーバーに保存されており、次回ログイン時に復元されます。</string>
<string name="settings_logging_out">ログアウト中…</string>
<string name="needs_update_toast">この機能を使用するにはアプリの更新が必要です。</string>
<string name="deeplink_map_too_large">このマップは大きすぎて開けません(サイズ制限超過)。</string>
<string name="login_dialog_title">Roboyardにログイン</string>
<string name="login_dialog_email">メール</string>
<string name="login_dialog_email_or_username">メール、ユーザー名、またはユーザーID</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-ko/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@
<string name="settings_logout_confirm_message">로그아웃하면 이 기기에서 모든 로컬 성취, 레벨 진행 상황, 게임 기록 및 연속 기록이 삭제됩니다. 데이터는 서버에 저장되어 있으며 다음 로그인 시 복원됩니다.</string>
<string name="settings_logging_out">로그아웃 중…</string>
<string name="needs_update_toast">이 기능을 사용하려면 앱을 업데이트해야 합니다.</string>
<string name="deeplink_map_too_large">이 지도는 너무 커서 열 수 없습니다(크기 제한 초과).</string>
<string name="login_dialog_title">Roboyard 로그인</string>
<string name="login_dialog_email">이메일</string>
<string name="login_dialog_email_or_username">이메일, 사용자 이름 또는 사용자 ID</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-pl/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@
<string name="settings_logout_confirm_message">Wylogowanie usunie wszystkie lokalne osiągnięcia, postęp poziomów, historię gier i serie z tego urządzenia. Twoje dane są zapisane na serwerze i zostaną przywrócone przy następnym logowaniu.</string>
<string name="settings_logging_out">Wylogowywanie…</string>
<string name="needs_update_toast">Twoja aplikacja wymaga aktualizacji, aby korzystać z tej funkcji.</string>
<string name="deeplink_map_too_large">Ta mapa jest za duża, aby ją otworzyć (przekroczono limity rozmiaru).</string>
<string name="login_dialog_title">Zaloguj się do Roboyard</string>
<string name="login_dialog_email">E-mail</string>
<string name="login_dialog_email_or_username">E-mail, nazwa użytkownika lub ID użytkownika</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-pt-rBR/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,7 @@
<string name="settings_logout_confirm_message">Fazer logout limpará todas as conquistas locais, progresso de níveis, histórico de jogos e sequências deste dispositivo. Seus dados são salvos no servidor e serão restaurados no próximo login.</string>
<string name="settings_logging_out">Fazendo logout…</string>
<string name="needs_update_toast">Seu aplicativo precisa de uma atualização para usar este recurso.</string>
<string name="deeplink_map_too_large">Este mapa é grande demais para ser aberto (limites de tamanho excedidos).</string>
<string name="login_dialog_title">Login no Roboyard</string>
<string name="login_dialog_email">Email</string>
<string name="login_dialog_email_or_username">Email, nome de usuário ou ID do usuário</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values-zh/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@
<string name="settings_logout_confirm_message">登出将清除此设备上的所有本地成就、关卡进度、游戏历史和连续记录。您的数据已保存在服务器上,将在下次登录时恢复。</string>
<string name="settings_logging_out">登出中…</string>
<string name="needs_update_toast">您的应用需要更新才能使用此功能。</string>
<string name="deeplink_map_too_large">此地图太大,无法打开(超出大小限制)。</string>
<string name="login_dialog_title">登录 Roboyard</string>
<string name="login_dialog_email">邮箱</string>
<string name="login_dialog_email_or_username">邮箱、用户名或用户ID</string>
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@
<string name="settings_logout_confirm_message">Logging out will clear all local achievements, level progress, game history, and streaks from this device. Your data is saved on the server and will be restored on next login.</string>
<string name="settings_logging_out">Logging out…</string>
<string name="needs_update_toast">Your app needs an update to use this feature.</string>
<string name="deeplink_map_too_large">This map is too large to open (exceeds size limits).</string>
<string name="login_dialog_title">Login to Roboyard</string>
<string name="login_dialog_email">Email</string>
<string name="login_dialog_email_or_username">Email, Username, or User ID</string>
Expand Down
2 changes: 0 additions & 2 deletions dev/scripts/add_changelog.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,12 @@ check_length() {
# German Changelog (for CHANGELOG_de.md - without link)
DE_CHANGES=$(cat << EOF
- Jetzt in Englisch, Deutsch, Spanisch, Französisch, Koreanisch, Chinesisch, Japanisch, Polnisch und Portugiesisch (Brasilien)
- Map behalten-Button um eine generierte Map trotz nicht passender Schwierigkeit zu spielen
EOF
)

# English Changelog (for CHANGELOG.md - without link)
EN_CHANGES=$(cat << EOF
- Switch between English, German, Spanish, French, Korean, Chinese, Japanese, Polish and Portuguese (Brazil)
- Keep-map button to play a generated map even if it does not meet difficulty settings

EOF
)
Expand Down
Binary file added download/Roboyard_v48.apk
Binary file not shown.
2 changes: 2 additions & 0 deletions fastlane/metadata/android/de/changelogs/130.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Jetzt in Englisch, Deutsch, Spanisch, Französisch, Koreanisch, Chinesisch, Japanisch, Polnisch und Portugiesisch (Brasilien)
- komplettes Changelog auf https://github.com/Eastcoast-Laboratories/Roboyard/blob/master/CHANGELOG_de.md
2 changes: 2 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/130.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Switch between English, German, Spanish, French, Korean, Chinese, Japanese, Polish and Portuguese (Brazil)
- Full changelog on https://github.com/Eastcoast-Laboratories/Roboyard/blob/master/CHANGELOG.md
10 changes: 10 additions & 0 deletions fastlane/metadata/android/playstore/changelog_130.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Play Store Changelogs für Version 48 (versionCode: 130)

<en-GB>
- Switch between English, German, Spanish, French, Korean, Chinese, Japanese, Polish and Portuguese (Brazil)
- Full changelog on https://github.com/Eastcoast-Laboratories/Roboyard/blob/master/CHANGELOG.md
</en-GB>
<de-DE>
- Jetzt in Englisch, Deutsch, Spanisch, Französisch, Koreanisch, Chinesisch, Japanisch, Polnisch und Portugiesisch (Brasilien)
- komplettes Changelog auf https://github.com/Eastcoast-Laboratories/Roboyard/blob/master/CHANGELOG_de.md
</de-DE>