From 9ff959536d50fb346a19ffbc8cadcd699c10a7b4 Mon Sep 17 00:00:00 2001 From: casey langen Date: Sun, 10 May 2020 11:34:00 -0700 Subject: [PATCH] Fix bugs around download tracks with titles that contain path separators, or tracks without metadata. --- src/musikdroid/app/build.gradle | 4 +-- .../activity/TrackDownloadActivity.kt | 34 +++++++++++++------ src/plugins/server/HttpServer.cpp | 10 ++++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/musikdroid/app/build.gradle b/src/musikdroid/app/build.gradle index 651e84ad7..a724cffb7 100644 --- a/src/musikdroid/app/build.gradle +++ b/src/musikdroid/app/build.gradle @@ -61,8 +61,8 @@ dependencies { exclude group: 'com.android.support', module: 'support-annotations' }) - implementation 'com.google.firebase:firebase-analytics:17.4.0' - implementation 'com.google.firebase:firebase-core:17.4.0' + implementation 'com.google.firebase:firebase-analytics:17.4.1' + implementation 'com.google.firebase:firebase-core:17.4.1' implementation 'com.google.firebase:firebase-crashlytics:17.0.0' implementation(name:'android-taskrunner-0.5', ext:'aar') diff --git a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/download/activity/TrackDownloadActivity.kt b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/download/activity/TrackDownloadActivity.kt index 0e7f585a2..7f398d289 100644 --- a/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/download/activity/TrackDownloadActivity.kt +++ b/src/musikdroid/app/src/main/java/io/casey/musikcube/remote/ui/download/activity/TrackDownloadActivity.kt @@ -34,6 +34,7 @@ class TrackDownloadActivity: BaseActivity() { private val httpClient = createHttpClient(Application.instance) private val mutex = Object() private var pendingCall: Call? = null + private var outputFilename: String = "" private lateinit var spinner: MaterialProgressBar private lateinit var progress: MaterialProgressBar private val handler = Handler() @@ -141,6 +142,7 @@ class TrackDownloadActivity: BaseActivity() { } } + outputFilename = getOutputFilename(response) if (it.byteStream().toFile(outputFilename, onBytesReceived)) { MediaScannerConnection.scanFile( this@TrackDownloadActivity, @@ -202,16 +204,6 @@ class TrackDownloadActivity: BaseActivity() { } } - private val outputFilename: String - get() { - val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - val title = intent.getStringExtra(EXTRA_TRACK_TITLE) - val externalId = intent.getStringExtra(EXTRA_EXTERNAL_ID) - var extension = intent.extras?.getString(EXTRA_EXTENSION, "mp3") - extension = if (extension.isNullOrBlank()) "mp3" else extension - return "$dir/musikdroid/$title-$externalId.$extension" - } - private val trackUrl: Uri get() { val ssl = prefs.getBoolean(Prefs.Key.SSL_ENABLED, Prefs.Default.SSL_ENABLED) @@ -227,6 +219,27 @@ class TrackDownloadActivity: BaseActivity() { .appendPath(intent.getStringExtra(EXTRA_EXTERNAL_ID)).build() } + private fun getOutputFilename(response: Response): String { + val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + val externalId = intent.getStringExtra(EXTRA_EXTERNAL_ID) + val rawTitle = intent.getStringExtra(EXTRA_TRACK_TITLE) + var filename = "$rawTitle-$externalId" + + /* in some cases the server may request a filename override, so we try to honor that + here if possible */ + val headers = response.headers().values(HTTP_HEADER_FILENAME_OVERRIDE) + if (headers.isNotEmpty()) { + filename = headers[0] + } + + /* strip standard path delimiters */ + filename = filename.replace("/", "_").replace("\\", "_") + + var extension = intent.extras?.getString(EXTRA_EXTENSION, "mp3") + extension = if (extension.isNullOrBlank()) "mp3" else extension + return "$dir/musikdroid/$filename.$extension" + } + class ConfirmCancelDialog: DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = AlertDialog.Builder(activity!!) @@ -274,6 +287,7 @@ class TrackDownloadActivity: BaseActivity() { private const val EXTRA_EXTERNAL_ID = "extra_external_id" private const val EXTRA_TRACK_TITLE = "extra_track_title" private const val EXTRA_EXTENSION = "extra_extension" + private const val HTTP_HEADER_FILENAME_OVERRIDE = "X-musikcube-Filename-Override" fun getStartIntent(activity: AppCompatActivity, track: ITrack): Intent { return Intent(activity, TrackDownloadActivity::class.java).apply { diff --git a/src/plugins/server/HttpServer.cpp b/src/plugins/server/HttpServer.cpp index f6b6383cc..87a7e9c46 100644 --- a/src/plugins/server/HttpServer.cpp +++ b/src/plugins/server/HttpServer.cpp @@ -433,8 +433,10 @@ int HttpServer::HandleAudioTrackRequest( } if (track) { - std::string duration = GetMetadataString(track, key::duration); - std::string filename = GetMetadataString(track, key::filename); + const std::string duration = GetMetadataString(track, key::duration); + const std::string filename = GetMetadataString(track, key::filename); + const std::string title = GetMetadataString(track, key::title, ""); + const std::string externalId = GetMetadataString(track, key::external_id, ""); track->Release(); @@ -534,6 +536,10 @@ int HttpServer::HandleAudioTrackRequest( if (response) { if (!isOnDemandTranscoder) { MHD_add_response_header(response, "Accept-Ranges", "bytes"); + + if (boost::filesystem::exists(title)) { + MHD_add_response_header(response, "X-musikcube-Filename-Override", externalId.c_str()); + } } else { MHD_add_response_header(response, "X-musikcube-Estimated-Content-Length", "true");