8000 Add version history and old app version download support by koraytutuncu · Pull Request #370 · majd/ipatool · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add version history and old app version download support #370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jun 8, 2025

Conversation

koraytutuncu
Copy link
Contributor
@koraytutuncu koraytutuncu commented Jun 7, 2025

Summary

This PR adds support for viewing app version history and downloading specific (old) versions of iOS apps from the App Store. Users can now access historical versions of apps that are no longer available in the current App Store listing.

New Features

Version History Command

  • New version-history command to list all available versions of an app
  • Support for both App ID and Bundle ID lookup
  • Configurable ordering (oldest-first or newest-first)
  • Concurrent version detail fetching with progress tracking
  • Formatted table output showing version strings and version IDs
  • Configurable maximum number of versions to fetch

Old Version Download Support

  • New --version-id flag for the download command
  • Download any historical version using its version ID
  • Seamless integration with existing download workflow
  • Automatic file naming with version information
  • Backwards compatible (defaults to latest version when no version ID specified)

Usage Examples

# Get version history for an app
ipatool version-history --bundle-identifier com.example.app --max-versions 20 --oldest-first

# Download a specific old version
ipatool download --bundle-identifier com.example.app --version-id 123456789

ipatool-PR-example_optimized-4

Implementation Details

  • Concurrent processing: Version details are fetched concurrently with configurable limits
  • Progress tracking: Real-time progress display during version fetching
  • Error handling: Comprehensive error handling with retry logic
  • Logging: Detailed logging for debugging and monitoring
  • File naming: Smart destination path resolution including version info

Technical Changes

  • Added VersionHistory interface method to AppStore
  • Implemented appstore_version_history.go with core logic
  • Extended download functionality to support version-specific requests
  • Updated CLI with new commands and flags
  • Added comprehensive documentation and usage examples

Testing & Quality

  • ✅ All unit tests passing (go test ./...)
  • ✅ All linting checks passing (golangci-lint run)
  • ✅ Code formatted with gofmt
  • ✅ No breaking changes to existing functionality
  • ✅ Backwards compatible with existing workflows

Additional Improvements

  • Fixed empty storefront handling in countryCodeFromStoreFront
  • Cleaned up accidentally committed binary files
  • Added ipatool binary to .gitignore to prevent future commits
  • Resolved all code formatting and style issues

Documentation

  • Updated README with comprehensive usage examples
  • Added complete workflow documentation for version history and old version downloads
  • Included flag descriptions and usage patterns

This feature enables users to access the full history of iOS app versions, addressing a common need for developers, researchers, and users who need access to specific app versions for compatibility or analysis purposes.

EDIT 1:

Technical Mechanism - Direct Apple API Integration

How Version History Retrieval Works (No Third-Party APIs)

This implementation leverages Apple's private App Store APIs directly, the same APIs used by iTunes and the App Store applications themselves. Here's the technical breakdown:

Discovery Process

  1. Initial Metadata Request: Make a request to Apple's private download API endpoint without specifying a version ID

    POST https://p25-buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/volumeStoreDownloadProduct
    
  2. Version Enumeration: The response contains a crucial field softwareVersionExternalIdentifiers - an array of ALL available version IDs for the app:

    {
      "metadata": {
        "softwareVersionExternalIdentifiers": [822340413, 822555253, 822629924, ...]
      }
    }
  3. Concurrent Version Detail Fetching: For each version ID, make parallel authenticated requests to retrieve specific version metadata:

    <plist>
      <dict>
        <key>externalVersionId</key>
        <string>822340413</string>
        <key>salableAdamId</key>
        <integer>1241932094</integer>
      </dict>
    </plist>

Authentication & Request Structure

  • Same auth mechanism as existing download functionality
  • Apple ID credentials passed via iCloud-DSID headers
  • Device identification using MAC address-based GUID
  • XML payload format matching iTunes protocol specifications

Key Technical Advantages

  • No external dependencies - Uses only Apple's official infrastructure
  • Complete version coverage - Access to ALL versions Apple has on record
  • Real-time data - Direct from Apple's servers, always up-to-date
  • Authenticated access - Respects user's App Store account permissions
  • Rate limiting friendly - Concurrent requests with semaphore control

Version-Specific Downloads

When downloading old versions, the same download API is used but with the externalVersionId parameter:

<key>externalVersionId</key>
<string>822340413</string>  <!-- Specific version ID -->

This tells Apple's servers to serve the exact historical IPA file for that version, not the current one.

Why This Approach Works

  • Official API usage: We're using the same endpoints that iTunes and App Store use
  • No API violations: Following the same protocol as official Apple clients
  • Historical data access: Apple maintains version history internally for compatibility and legal reasons
  • Authenticated requests: Proper user authentication ensures legitimate access

This implementation essentially reverse-engineers the iTunes protocol to expose version history functionality that was always available but never exposed in consumer interfaces.

… - Move empty storefront check before error return - Prevents unnecessary error when storefront is empty - Improves error handling flow in storefront processing
…command to retrieve app version history - Support both app ID and bundle identifier lookup - Implement concurrent version detail fetching with progress tracking - Add formatted output with version and version ID table - Support oldest-first and newest-first ordering - Include comprehensive error handling and retry logic - Add logging for successful operations and debugging
…om go.sum - Restore go.sum to proper state without redundant module dependencies
…on-id flag to download command for specifying app version - Integrate version ID parameter in download request payload - Update destination path resolution to include version info - Add comprehensive README documentation for version history and old version download workflow - Remove accidentally committed ipatool binary - Add ipatool binary to .gitignore to prevent future commits
…g issues in version history files - Add required blank lines before return statements (nlreturn) - Fix whitespace linter issues (wsl) for proper code spacing - Ensure all unit tests pass and code meets project standards
@koraytutuncu koraytutuncu marked this pull request as ready for review June 7, 2025 16:30
…versions flag to fetch complete app version history - Override --max-versions when --all-versions is used - Support proper ordering (oldest-first/newest-first) for all versions - Enhance user feedback with 'Fetching ALL version details' message - Add allVersions boolean to logging for debugging - Maintain backward compatibility with existing --max-versions behavior - Update flag descriptions to clarify interactions between flags
@csc-EricWu
Copy link

I'm glad to see this. Can you compile a binary in your repository? I want to test it immediately.

…go version from 1.23.0 to 1.19 to match GitHub workflow - Remove toolchain directive (not supported in Go 1.19) - Fixes build errors in GitHub Actions workflow
@majd
Copy link
Owner
majd commented Jun 8, 2025

Thanks, this seems to work well. I do have some concerns:

  • Resolving the external version numbers from internal numbers by sending numerous requests in parallel might cause throttling or getting the IP address blocklisted.
  • The printing of the version numbers using Print statements, which will break some automations that currently use ipatool.

Let's get this merged first as I would like to do some small adjustments afterwards.

@majd majd merged commit 0bb134e into majd:main Jun 8, 2025
13 checks passed
@gingerbeardman
Copy link

I'm glad to see this. Can you compile a binary in your repository? I want to test it immediately.

It's there now https://github.com/koraytutuncu/ipatool/releases/tag/v0.1.2-beta-test

@koraytutuncu
Copy link
Contributor Author

@majd

Thank you for building such a great tool!

I had those concerns in mind too, but as someone new to this, I just tried to make it work with some help from AI.

I really appreciate the feedback, and I’ll be more mindful next time for sure.

@majd
Copy link
Owner
majd commented Jun 8, 2025

@koraytutuncu No worries. Thank you for the valuable contribution. Out of curiosity, what AI tools/models did you use for this?

@koraytutuncu
Copy link
Contributor Author
koraytutuncu commented Jun 8, 2025

@majd Cursor -- I've started using AI code editors from the beginning and Cursor is the best among all.

Edit:
And I'm currently only using the new model Claude Sonnet 4.

@kuras12345
Copy link

Hello how too install linux instruction plus IPATool

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0