|
41 | 41 | import java.util.*; |
42 | 42 | import java.util.logging.Level; |
43 | 43 | import java.util.logging.Logger; |
| 44 | +import java.util.regex.Matcher; |
| 45 | +import java.util.regex.Pattern; |
44 | 46 |
|
45 | 47 | /** |
46 | 48 | * |
@@ -2281,6 +2283,11 @@ public void usesClassMethod(String cls, String method) { |
2281 | 2283 |
|
2282 | 2284 | addLocalizedIconsBuildSetting(pbxprojFile); |
2283 | 2285 |
|
| 2286 | + String teamId = request.getArg("ios.teamId", ""); |
| 2287 | + injectDevelopmentTeam(pbxprojFile, |
| 2288 | + request.getArg("ios.debug.teamId", teamId), |
| 2289 | + request.getArg("ios.release.teamId", teamId)); |
| 2290 | + |
2284 | 2291 | } catch (Exception ex) { |
2285 | 2292 | throw new BuildException("Failed to inject into plist"); |
2286 | 2293 | } |
@@ -3486,6 +3493,66 @@ private void writeAlternateAppIconContentsJson(File contentsJson, |
3486 | 3493 | } |
3487 | 3494 | } |
3488 | 3495 |
|
| 3496 | + // Apple Team IDs are 10-character alphanumeric strings (e.g. "2K4UGY23XQ"). |
| 3497 | + // Anything outside that range is rejected to avoid corrupting the pbxproj. |
| 3498 | + private static final Pattern TEAM_ID_PATTERN = Pattern.compile("[A-Za-z0-9]+"); |
| 3499 | + |
| 3500 | + private void injectDevelopmentTeam(File pbx, String debugTeam, String releaseTeam) throws IOException { |
| 3501 | + debugTeam = sanitizeTeamId(debugTeam, "ios.debug.teamId"); |
| 3502 | + releaseTeam = sanitizeTeamId(releaseTeam, "ios.release.teamId"); |
| 3503 | + if (debugTeam.isEmpty() && releaseTeam.isEmpty()) { |
| 3504 | + return; |
| 3505 | + } |
| 3506 | + String contents = readFileToString(pbx); |
| 3507 | + // Anchor on each XCBuildConfiguration's "buildSettings { ... }; name = Debug|Release;" |
| 3508 | + // boundary so we can route the right value per configuration when ios.debug.teamId |
| 3509 | + // and ios.release.teamId differ. DEVELOPMENT_TEAM is injected at the project level |
| 3510 | + // (the configurations that declare SDKROOT) so it inherits to every target. |
| 3511 | + Pattern blockPattern = Pattern.compile( |
| 3512 | + "buildSettings = \\{.*?\\};\\s*name = (Debug|Release);", |
| 3513 | + Pattern.DOTALL); |
| 3514 | + Matcher m = blockPattern.matcher(contents); |
| 3515 | + StringBuffer out = new StringBuffer(); |
| 3516 | + boolean modified = false; |
| 3517 | + while (m.find()) { |
| 3518 | + String block = m.group(0); |
| 3519 | + String configName = m.group(1); |
| 3520 | + String team = "Debug".equals(configName) ? debugTeam : releaseTeam; |
| 3521 | + if (team.isEmpty() |
| 3522 | + || block.contains("DEVELOPMENT_TEAM") |
| 3523 | + || !block.contains("SDKROOT = iphoneos;")) { |
| 3524 | + m.appendReplacement(out, Matcher.quoteReplacement(block)); |
| 3525 | + continue; |
| 3526 | + } |
| 3527 | + String injected = block.replace( |
| 3528 | + "SDKROOT = iphoneos;", |
| 3529 | + "SDKROOT = iphoneos;\n\t\t\t\tDEVELOPMENT_TEAM = " + team + ";"); |
| 3530 | + m.appendReplacement(out, Matcher.quoteReplacement(injected)); |
| 3531 | + modified = true; |
| 3532 | + } |
| 3533 | + m.appendTail(out); |
| 3534 | + if (modified) { |
| 3535 | + try (Writer w = new OutputStreamWriter(Files.newOutputStream(pbx.toPath()), StandardCharsets.UTF_8)) { |
| 3536 | + w.write(out.toString()); |
| 3537 | + } |
| 3538 | + } |
| 3539 | + } |
| 3540 | + |
| 3541 | + private String sanitizeTeamId(String raw, String hint) { |
| 3542 | + if (raw == null) { |
| 3543 | + return ""; |
| 3544 | + } |
| 3545 | + String trimmed = raw.trim(); |
| 3546 | + if (trimmed.isEmpty()) { |
| 3547 | + return ""; |
| 3548 | + } |
| 3549 | + if (!TEAM_ID_PATTERN.matcher(trimmed).matches()) { |
| 3550 | + log("Ignoring " + hint + "='" + raw + "': expected an alphanumeric Apple Team ID"); |
| 3551 | + return ""; |
| 3552 | + } |
| 3553 | + return trimmed; |
| 3554 | + } |
| 3555 | + |
3489 | 3556 | private void addLocalizedIconsBuildSetting(File pbx) throws IOException { |
3490 | 3557 | if (localizedIcons.isEmpty()) { |
3491 | 3558 | return; |
|
0 commit comments