Mercurial > mplayer.hg
comparison libmpdvdkit2/libdvdcss.c @ 16630:954cdf2171f6
upgrade to libdvdcss 1.2.9
author | diego |
---|---|
date | Sat, 01 Oct 2005 17:19:33 +0000 |
parents | c2ddedd0619e |
children | 0af14c5fee82 |
comparison
equal
deleted
inserted
replaced
16629:045e93202e4a | 16630:954cdf2171f6 |
---|---|
3 * Authors: Stéphane Borel <stef@via.ecp.fr> | 3 * Authors: Stéphane Borel <stef@via.ecp.fr> |
4 * Samuel Hocevar <sam@zoy.org> | 4 * Samuel Hocevar <sam@zoy.org> |
5 * Håkan Hjort <d95hjort@dtek.chalmers.se> | 5 * Håkan Hjort <d95hjort@dtek.chalmers.se> |
6 * | 6 * |
7 * Copyright (C) 1998-2002 VideoLAN | 7 * Copyright (C) 1998-2002 VideoLAN |
8 * | |
9 * Modified for use with MPlayer, changes contained in libdvdcss_changes.diff. | |
10 * detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/ | |
11 * $Id$ | 8 * $Id$ |
12 * | 9 * |
13 * This program is free software; you can redistribute it and/or modify | 10 * This program is free software; you can redistribute it and/or modify |
14 * it under the terms of the GNU General Public License as published by | 11 * it under the terms of the GNU General Public License as published by |
15 * the Free Software Foundation; either version 2 of the License, or | 12 * the Free Software Foundation; either version 2 of the License, or |
23 * You should have received a copy of the GNU General Public License | 20 * You should have received a copy of the GNU General Public License |
24 * along with this program; if not, write to the Free Software | 21 * along with this program; if not, write to the Free Software |
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. | 22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. |
26 */ | 23 */ |
27 | 24 |
28 /* | 25 /** |
29 * \mainpage libdvdcss developer documentation | 26 * \mainpage libdvdcss developer documentation |
30 * | 27 * |
31 * \section intro Introduction | 28 * \section intro Introduction |
32 * | 29 * |
33 * \e libdvdcss is a simple library designed for accessing DVDs like a block | 30 * \e libdvdcss is a simple library designed for accessing DVDs like a block |
103 #include <string.h> | 100 #include <string.h> |
104 #include <sys/types.h> | 101 #include <sys/types.h> |
105 #include <sys/stat.h> | 102 #include <sys/stat.h> |
106 #include <fcntl.h> | 103 #include <fcntl.h> |
107 #include <errno.h> | 104 #include <errno.h> |
108 #include <unistd.h> | 105 # include <unistd.h> |
109 #include <limits.h> | 106 # include <limits.h> |
110 | 107 |
111 #include "dvdcss.h" | 108 #include "dvdcss.h" |
112 | 109 |
113 #include "common.h" | 110 #include "common.h" |
114 #include "css.h" | 111 #include "css.h" |
190 */ | 187 */ |
191 if( psz_verbose != NULL ) | 188 if( psz_verbose != NULL ) |
192 { | 189 { |
193 int i = atoi( psz_verbose ); | 190 int i = atoi( psz_verbose ); |
194 | 191 |
195 if( i >= 2 ) dvdcss->b_debug = 1; | 192 if( i >= 2 ) dvdcss->b_debug = i; |
196 if( i >= 1 ) dvdcss->b_errors = 1; | 193 if( i >= 1 ) dvdcss->b_errors = 1; |
197 } | 194 } |
198 | 195 |
199 /* | 196 /* |
200 * Find method from DVDCSS_METHOD environment variable | 197 * Find method from DVDCSS_METHOD environment variable |
213 { | 210 { |
214 dvdcss->i_method = DVDCSS_METHOD_TITLE; | 211 dvdcss->i_method = DVDCSS_METHOD_TITLE; |
215 } | 212 } |
216 else | 213 else |
217 { | 214 { |
218 _dvdcss_error( dvdcss, "unknown decrypt method, please choose " | 215 print_error( dvdcss, "unknown decrypt method, please choose " |
219 "from 'title', 'key' or 'disc'" ); | 216 "from 'title', 'key' or 'disc'" ); |
220 free( dvdcss->psz_device ); | 217 free( dvdcss->psz_device ); |
221 free( dvdcss ); | 218 free( dvdcss ); |
222 return NULL; | 219 return NULL; |
223 } | 220 } |
224 } | 221 } |
222 | |
223 #if 0 /* MPlayer caches keys in its own configuration directory */ | |
224 | |
225 /* | |
226 * If DVDCSS_CACHE was not set, try to guess a default value | |
227 */ | |
228 if( psz_cache == NULL || psz_cache[0] == '\0' ) | |
229 { | |
230 #ifdef HAVE_DIRECT_H | |
231 typedef HRESULT( WINAPI *SHGETFOLDERPATH ) | |
232 ( HWND, int, HANDLE, DWORD, LPTSTR ); | |
233 | |
234 # define CSIDL_FLAG_CREATE 0x8000 | |
235 # define CSIDL_APPDATA 0x1A | |
236 # define SHGFP_TYPE_CURRENT 0 | |
237 | |
238 char psz_home[MAX_PATH]; | |
239 HINSTANCE p_dll; | |
240 SHGETFOLDERPATH p_getpath; | |
241 | |
242 *psz_home = '\0'; | |
243 | |
244 /* Load the shfolder dll to retrieve SHGetFolderPath */ | |
245 p_dll = LoadLibrary( "shfolder.dll" ); | |
246 if( p_dll ) | |
247 { | |
248 p_getpath = (void*)GetProcAddress( p_dll, "SHGetFolderPathA" ); | |
249 if( p_getpath ) | |
250 { | |
251 /* Get the "Application Data" folder for the current user */ | |
252 if( p_getpath( NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, | |
253 NULL, SHGFP_TYPE_CURRENT, psz_home ) == S_OK ) | |
254 { | |
255 FreeLibrary( p_dll ); | |
256 } | |
257 else | |
258 { | |
259 *psz_home = '\0'; | |
260 } | |
261 } | |
262 FreeLibrary( p_dll ); | |
263 } | |
264 | |
265 /* Cache our keys in | |
266 * C:\Documents and Settings\$USER\Application Data\dvdcss\ */ | |
267 if( *psz_home ) | |
268 { | |
269 snprintf( psz_buffer, PATH_MAX, "%s/dvdcss", psz_home ); | |
270 psz_buffer[PATH_MAX-1] = '\0'; | |
271 psz_cache = psz_buffer; | |
272 } | |
273 #else | |
274 char *psz_home = NULL; | |
275 # ifdef HAVE_PWD_H | |
276 struct passwd *p_pwd; | |
277 | |
278 /* Try looking in password file for home dir. */ | |
279 p_pwd = getpwuid(getuid()); | |
280 if( p_pwd ) | |
281 { | |
282 psz_home = p_pwd->pw_dir; | |
283 } | |
284 # endif | |
285 | |
286 if( psz_home == NULL ) | |
287 { | |
288 psz_home = getenv( "HOME" ); | |
289 } | |
290 | |
291 /* Cache our keys in ${HOME}/.dvdcss/ */ | |
292 if( psz_home ) | |
293 { | |
294 snprintf( psz_buffer, PATH_MAX, "%s/.dvdcss", psz_home ); | |
295 psz_buffer[PATH_MAX-1] = '\0'; | |
296 psz_cache = psz_buffer; | |
297 } | |
298 #endif | |
299 } | |
300 | |
301 #endif /* 0 */ | |
225 | 302 |
226 /* | 303 /* |
227 * Find cache dir from the DVDCSS_CACHE environment variable | 304 * Find cache dir from the DVDCSS_CACHE environment variable |
228 */ | 305 */ |
229 if( psz_cache != NULL ) | 306 if( psz_cache != NULL ) |
230 { | 307 { |
231 if( psz_cache[0] == '\0' ) | 308 if( psz_cache[0] == '\0' || !strcmp( psz_cache, "off" ) ) |
232 { | 309 { |
233 psz_cache = NULL; | 310 psz_cache = NULL; |
234 } | 311 } |
235 /* Check that we can add the ID directory and the block filename */ | 312 /* Check that we can add the ID directory and the block filename */ |
236 else if( strlen( psz_cache ) + 1 + 32 + 1 + 10 + 1 > PATH_MAX ) | 313 else if( strlen( psz_cache ) + 1 + 32 + 1 + (KEY_SIZE * 2) + 10 + 1 |
237 { | 314 > PATH_MAX ) |
238 _dvdcss_error( dvdcss, "cache directory name is too long" ); | 315 { |
316 print_error( dvdcss, "cache directory name is too long" ); | |
239 psz_cache = NULL; | 317 psz_cache = NULL; |
240 } | 318 } |
241 } | 319 } |
242 else psz_cache = get_path( "DVDKeys" ); | 320 else psz_cache = get_path( "DVDKeys" ); |
243 | 321 |
259 { | 337 { |
260 i_ret = _dvdcss_test( dvdcss ); | 338 i_ret = _dvdcss_test( dvdcss ); |
261 if( i_ret < 0 ) | 339 if( i_ret < 0 ) |
262 { | 340 { |
263 /* Disable the CSS ioctls and hope that it works? */ | 341 /* Disable the CSS ioctls and hope that it works? */ |
264 _dvdcss_debug( dvdcss, | 342 print_debug( dvdcss, |
265 "could not check whether the disc was scrambled" ); | 343 "could not check whether the disc was scrambled" ); |
266 dvdcss->b_ioctls = 0; | 344 dvdcss->b_ioctls = 0; |
267 } | 345 } |
268 else | 346 else |
269 { | 347 { |
270 _dvdcss_debug( dvdcss, i_ret ? "disc is scrambled" | 348 print_debug( dvdcss, i_ret ? "disc is scrambled" |
271 : "disc is unscrambled" ); | 349 : "disc is unscrambled" ); |
272 dvdcss->b_scrambled = i_ret; | 350 dvdcss->b_scrambled = i_ret; |
273 } | 351 } |
274 } | 352 } |
275 | 353 |
276 /* If disc is CSS protected and the ioctls work, authenticate the drive */ | 354 /* If disc is CSS protected and the ioctls work, authenticate the drive */ |
285 free( dvdcss ); | 363 free( dvdcss ); |
286 return NULL; | 364 return NULL; |
287 } | 365 } |
288 } | 366 } |
289 | 367 |
368 /* If the cache is enabled, write the cache directory tag */ | |
369 if( psz_cache ) | |
370 { | |
371 char *psz_tag = "Signature: 8a477f597d28d172789f06886806bc55\r\n" | |
372 "# This file is a cache directory tag created by libdvdcss.\r\n" | |
373 "# For information about cache directory tags, see:\r\n" | |
374 "# http://www.brynosaurus.com/cachedir/\r\n"; | |
375 unsigned char psz_tagfile[PATH_MAX+1+12+1]; | |
376 int i_fd; | |
377 | |
378 sprintf( psz_tagfile, "%s/CACHEDIR.TAG", psz_cache ); | |
379 i_fd = open( psz_tagfile, O_RDWR|O_CREAT, 0644 ); | |
380 if( i_fd >= 0 ) | |
381 { | |
382 write( i_fd, psz_tag, strlen(psz_tag) ); | |
383 close( i_fd ); | |
384 } | |
385 } | |
386 | |
290 /* If the cache is enabled, extract a unique disc ID */ | 387 /* If the cache is enabled, extract a unique disc ID */ |
291 if( psz_cache ) | 388 if( psz_cache ) |
292 { | 389 { |
293 uint8_t p_sector[DVDCSS_BLOCK_SIZE]; | 390 uint8_t p_sector[DVDCSS_BLOCK_SIZE]; |
294 unsigned char psz_debug[PATH_MAX+30]; | 391 unsigned char psz_debug[PATH_MAX+30]; |
392 unsigned char psz_key[1 + KEY_SIZE * 2 + 1]; | |
295 unsigned char * psz_title, * psz_serial; | 393 unsigned char * psz_title, * psz_serial; |
296 int i; | 394 int i; |
297 | 395 |
298 /* We read sector 0. If it starts with 0x000001ba (BE), we are | 396 /* We read sector 0. If it starts with 0x000001ba (BE), we are |
299 * reading a VOB file, and we should not cache anything. */ | 397 * reading a VOB file, and we should not cache anything. */ |
356 /* Check that all characters are digits, otherwise convert. */ | 454 /* Check that all characters are digits, otherwise convert. */ |
357 for( i = 0 ; i < 16 ; i++ ) | 455 for( i = 0 ; i < 16 ; i++ ) |
358 { | 456 { |
359 if( psz_serial[i] < '0' || psz_serial[i] > '9' ) | 457 if( psz_serial[i] < '0' || psz_serial[i] > '9' ) |
360 { | 458 { |
361 sprintf( psz_serial, | 459 unsigned char psz_tmp[16 + 1]; |
362 "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X", | 460 sprintf( psz_tmp, |
461 "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", | |
363 psz_serial[0], psz_serial[1], psz_serial[2], | 462 psz_serial[0], psz_serial[1], psz_serial[2], |
364 psz_serial[3], psz_serial[4], psz_serial[5], | 463 psz_serial[3], psz_serial[4], psz_serial[5], |
365 psz_serial[6], psz_serial[7] ); | 464 psz_serial[6], psz_serial[7] ); |
465 memcpy( psz_serial, psz_tmp, 16 ); | |
366 break; | 466 break; |
367 } | 467 } |
468 } | |
469 | |
470 /* Get disk key, since some discs have got same title, manufacturing | |
471 * date and serial number, but different keys */ | |
472 if( dvdcss->b_scrambled ) | |
473 { | |
474 psz_key[0] = '-'; | |
475 for( i = 0; i < KEY_SIZE; i++ ) | |
476 { | |
477 sprintf( &psz_key[1+i*2], "%.2x", dvdcss->css.p_disc_key[i] ); | |
478 } | |
479 psz_key[1 + KEY_SIZE * 2] = '\0'; | |
480 } | |
481 else | |
482 { | |
483 psz_key[0] = 0; | |
368 } | 484 } |
369 | 485 |
370 /* We have a disc name or ID, we can create the cache dir */ | 486 /* We have a disc name or ID, we can create the cache dir */ |
371 i = sprintf( dvdcss->psz_cachefile, "%s", psz_cache ); | 487 i = sprintf( dvdcss->psz_cachefile, "%s", psz_cache ); |
372 #if !defined( WIN32 ) || defined( SYS_CYGWIN ) | 488 #if !defined( WIN32 ) || defined( SYS_CYGWIN ) |
374 #else | 490 #else |
375 i_ret = mkdir( dvdcss->psz_cachefile ); | 491 i_ret = mkdir( dvdcss->psz_cachefile ); |
376 #endif | 492 #endif |
377 if( i_ret < 0 && errno != EEXIST ) | 493 if( i_ret < 0 && errno != EEXIST ) |
378 { | 494 { |
379 _dvdcss_error( dvdcss, "failed creating cache directory" ); | 495 print_error( dvdcss, "failed creating cache directory" ); |
380 dvdcss->psz_cachefile[0] = '\0'; | 496 dvdcss->psz_cachefile[0] = '\0'; |
381 goto nocache; | 497 goto nocache; |
382 } | 498 } |
383 i += sprintf( dvdcss->psz_cachefile + i, "/"); | 499 i += sprintf( dvdcss->psz_cachefile + i, "/"); |
384 | 500 |
385 // i += sprintf( dvdcss->psz_cachefile + i, "/%s", psz_data ); | 501 // i += sprintf( dvdcss->psz_cachefile + i, "/%s", psz_data ); |
386 i += sprintf( dvdcss->psz_cachefile + i, "/%s#%s", psz_title, psz_serial ); | 502 i += sprintf( dvdcss->psz_cachefile + i, "/%s#%s", psz_title, psz_serial ); |
387 #if !defined( WIN32 ) || defined( SYS_CYGWIN ) | 503 #if !defined( WIN32 ) || defined( SYS_CYGWIN ) |
388 i_ret = mkdir( dvdcss->psz_cachefile, 0755 ); | 504 i_ret = mkdir( dvdcss->psz_cachefile, 0755 ); |
389 #else | 505 #else |
390 i_ret = mkdir( dvdcss->psz_cachefile ); | 506 i_ret = mkdir( dvdcss->psz_cachefile ); |
391 #endif | 507 #endif |
392 if( i_ret < 0 && errno != EEXIST ) | 508 if( i_ret < 0 && errno != EEXIST ) |
393 { | 509 { |
394 _dvdcss_error( dvdcss, "failed creating cache subdirectory" ); | 510 print_error( dvdcss, "failed creating cache subdirectory" ); |
395 dvdcss->psz_cachefile[0] = '\0'; | 511 dvdcss->psz_cachefile[0] = '\0'; |
396 goto nocache; | 512 goto nocache; |
397 } | 513 } |
398 i += sprintf( dvdcss->psz_cachefile + i, "/"); | 514 i += sprintf( dvdcss->psz_cachefile + i, "/"); |
399 | 515 |
400 /* Pointer to the filename we will use. */ | 516 /* Pointer to the filename we will use. */ |
401 dvdcss->psz_block = dvdcss->psz_cachefile + i; | 517 dvdcss->psz_block = dvdcss->psz_cachefile + i; |
402 | 518 |
403 sprintf( psz_debug, "using CSS key cache dir: %s", | 519 sprintf( psz_debug, "using CSS key cache dir: %s", |
404 dvdcss->psz_cachefile ); | 520 dvdcss->psz_cachefile ); |
405 _dvdcss_debug( dvdcss, psz_debug ); | 521 print_debug( dvdcss, psz_debug ); |
406 } | 522 } |
407 nocache: | 523 nocache: |
408 | 524 |
409 #ifndef WIN32 | 525 #ifndef WIN32 |
410 if( psz_raw_device != NULL ) | 526 if( psz_raw_device != NULL ) |
520 * check that there are no encrypted blocks */ | 636 * check that there are no encrypted blocks */ |
521 for( i_index = i_ret; i_index; i_index-- ) | 637 for( i_index = i_ret; i_index; i_index-- ) |
522 { | 638 { |
523 if( ((uint8_t*)p_buffer)[0x14] & 0x30 ) | 639 if( ((uint8_t*)p_buffer)[0x14] & 0x30 ) |
524 { | 640 { |
525 _dvdcss_error( dvdcss, "no key but found encrypted block" ); | 641 print_error( dvdcss, "no key but found encrypted block" ); |
526 /* Only return the initial range of unscrambled blocks? */ | 642 /* Only return the initial range of unscrambled blocks? */ |
527 /* or fail completely? return 0; */ | 643 /* or fail completely? return 0; */ |
528 break; | 644 break; |
529 } | 645 } |
530 p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); | 646 p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE); |