31
31
import java .util .Map ;
32
32
import java .util .Queue ;
33
33
import java .util .Set ;
34
- import java .util .regex .Pattern ;
35
34
35
+ import org .w3c .epubcheck .constants .MIMEType ;
36
+ import org .w3c .epubcheck .url .URLFragment ;
36
37
import org .w3c .epubcheck .url .URLUtils ;
37
38
38
39
import com .adobe .epubcheck .api .EPUBLocation ;
@@ -126,6 +127,7 @@ public static final class Builder
126
127
private OPFItem item = null ;
127
128
private boolean hasItemFallback = false ;
128
129
private boolean hasImageFallback = false ;
130
+ public String mimetype ;
129
131
130
132
public Builder url (URL url )
131
133
{
@@ -137,6 +139,13 @@ public Builder item(OPFItem item)
137
139
{
138
140
this .url = item .getURL ();
139
141
this .item = item ;
142
+ this .mimetype = item .getMimeType ();
143
+ return this ;
144
+ }
145
+
146
+ public Builder mimetype (String mimetype )
147
+ {
148
+ this .mimetype = mimetype ;
140
149
return this ;
141
150
}
142
151
@@ -231,8 +240,6 @@ public boolean isInSpine()
231
240
}
232
241
}
233
242
234
- private static final Pattern REGEX_SVG_VIEW = Pattern .compile ("svgView\\ (.*\\ )" );
235
-
236
243
private final Map <URL , Resource > resources = new HashMap <URL , Resource >();
237
244
238
245
private final Set <URL > undeclared = new HashSet <URL >();
@@ -281,7 +288,7 @@ public Optional<OPFItem> getResource(URL url)
281
288
* @param path
282
289
* the path to a publication resource
283
290
* @return an immutable {@link EnumSet} containing the types of references to
284
- * {@code path}.
291
+ * {@code path}.
285
292
*/
286
293
public Set <Type > getTypes (URL resource )
287
294
{
@@ -413,9 +420,15 @@ public void checkReferences()
413
420
private void checkReference (URLReference reference )
414
421
{
415
422
Resource hostResource = resources .get (reference .location .url );
416
- Resource targetResource = resources .get (reference .targetDoc );
423
+
424
+ // Retrieve the Resource instance representing the targeted document
417
425
// If the resource was not declared in the manifest,
418
426
// we build a new Resource object for the data URL.
427
+ Resource targetResource = resources .get (reference .targetDoc );
428
+ String targetMimetype = (targetResource != null ) ? targetResource .getMimeType () : "" ;
429
+
430
+ // Parse the URL fragment
431
+ URLFragment fragment = URLFragment .parse (reference .url , targetMimetype );
419
432
420
433
// Check remote resources
421
434
if (container .isRemote (reference .url )
@@ -470,15 +483,18 @@ else if (!undeclared.contains(reference.targetDoc)
470
483
return ;
471
484
}
472
485
473
- String mimetype = targetResource .getMimeType ();
474
-
475
486
// Type-specific checks
476
487
switch (reference .type )
477
488
{
478
489
case HYPERLINK :
490
+ if ("epubcfi" .equals (fragment .getScheme ()))
491
+ {
492
+ break ; // EPUB CFI is not supported
493
+ }
479
494
// if mimeType is null, we should have reported an error already
480
- if (!OPFChecker .isBlessedItemType (mimetype , version )
481
- && !OPFChecker .isDeprecatedBlessedItemType (mimetype ) && !targetResource .hasItemFallback ())
495
+ if (!OPFChecker .isBlessedItemType (targetMimetype , version )
496
+ && !OPFChecker .isDeprecatedBlessedItemType (targetMimetype )
497
+ && !targetResource .hasItemFallback ())
482
498
{
483
499
report .message (MessageId .RSC_010 ,
484
500
reference .location .context (container .relativize (reference .url )));
@@ -494,31 +510,35 @@ else if (!undeclared.contains(reference.targetDoc)
494
510
case IMAGE :
495
511
case PICTURE_SOURCE :
496
512
case PICTURE_SOURCE_FOREIGN :
497
- if (reference .url .fragment () != null && !mimetype .equals ("image/svg+xml" ))
513
+ if ("epubcfi" .equals (fragment .getScheme ()))
514
+ {
515
+ break ; // EPUB CFI is not supported
516
+ }
517
+ if (fragment .exists () && !MIMEType .SVG .is (targetMimetype ))
498
518
{
499
519
report .message (MessageId .RSC_009 ,
500
520
reference .location .context (container .relativize (reference .url )));
501
521
return ;
502
522
}
503
523
// if mimeType is null, we should have reported an error already
504
- if (!OPFChecker .isBlessedImageType (mimetype , version ))
524
+ if (!OPFChecker .isBlessedImageType (targetMimetype , version ))
505
525
{
506
526
if (version == EPUBVersion .VERSION_3 && reference .type == Type .PICTURE_SOURCE )
507
527
{
508
528
report .message (MessageId .MED_007 , reference .location ,
509
- container .relativize (reference .targetDoc ), mimetype );
529
+ container .relativize (reference .targetDoc ), targetMimetype );
510
530
return ;
511
531
}
512
532
else if (reference .type == Type .IMAGE && !targetResource .hasImageFallback ())
513
533
{
514
534
report .message (MessageId .MED_003 , reference .location ,
515
- container .relativize (reference .targetDoc ), mimetype );
535
+ container .relativize (reference .targetDoc ), targetMimetype );
516
536
}
517
537
}
518
538
break ;
519
539
case SEARCH_KEY :
520
540
// TODO update when we support EPUB CFI
521
- if ((reference . url . fragment () == null || !reference . url . fragment (). startsWith ( "epubcfi(" ))
541
+ if ((! fragment . exists () || !"epubcfi" . equals ( fragment . getScheme () ))
522
542
&& !targetResource .isInSpine ())
523
543
{
524
544
report .message (MessageId .RSC_021 , reference .location ,
@@ -527,7 +547,7 @@ else if (reference.type == Type.IMAGE && !targetResource.hasImageFallback())
527
547
}
528
548
break ;
529
549
case STYLESHEET :
530
- if (reference . url . fragment () != null )
550
+ if (fragment . exists () )
531
551
{
532
552
report .message (MessageId .RSC_013 ,
533
553
reference .location .context (container .relativize (reference .url )));
@@ -551,7 +571,7 @@ else if (reference.type == Type.IMAGE && !targetResource.hasImageFallback())
551
571
case SVG_CLIP_PATH :
552
572
case SVG_PAINT :
553
573
case SVG_SYMBOL :
554
- if (reference . url . fragment () == null )
574
+ if (! fragment . exists () )
555
575
{
556
576
report .message (MessageId .RSC_015 , reference .location .context (reference .url ));
557
577
return ;
@@ -562,32 +582,32 @@ else if (reference.type == Type.IMAGE && !targetResource.hasImageFallback())
562
582
}
563
583
564
584
// Fragment integrity checks
565
- String fragment = reference .url .fragment ();
566
- if (fragment != null && !fragment .isEmpty ())
585
+ if (fragment .exists () && !fragment .isEmpty ())
567
586
{
568
587
// EPUB CFI
569
- if (fragment . startsWith ( "epubcfi(" ))
588
+ if ("epubcfi" . equals ( fragment . getScheme () ))
570
589
{
590
+ // FIXME HOT should warn if in MO
571
591
// FIXME epubcfi currently not supported (see issue 150).
572
592
return ;
573
593
}
574
594
// Media fragments in Data Navigation Documents
575
- else if (fragment .contains ( "=" ) && hostResource != null && hostResource .hasItem ()
595
+ else if (fragment .isMediaFragment ( ) && hostResource != null && hostResource .hasItem ()
576
596
&& hostResource .getItem ().getProperties ()
577
597
.contains (PackageVocabs .ITEM_VOCAB .get (PackageVocabs .ITEM_PROPERTIES .DATA_NAV )))
578
598
{
579
599
// Ignore,
580
600
return ;
581
601
}
582
- // SVG view fragments are ignored
583
- else if (mimetype . equals ( "image/svg+xml" ) && REGEX_SVG_VIEW . matcher ( fragment ). matches ())
602
+ // Non-ID-based fragments are ignored
603
+ else if (fragment . getId (). isEmpty ())
584
604
{
585
605
return ;
586
606
}
587
607
// Fragment Identifier (by default)
588
608
else if (!container .isRemote (reference .targetDoc ))
589
609
{
590
- ID anchor = targetResource .ids .get (fragment );
610
+ ID anchor = targetResource .ids .get (fragment . getId () );
591
611
if (anchor == null )
592
612
{
593
613
report .message (MessageId .RSC_012 , reference .location .context (reference .url .toString ()));
@@ -674,7 +694,8 @@ private void checkReadingOrder(Queue<URLReference> references, int lastSpinePosi
674
694
}
675
695
676
696
// check that the fragment is in document order
677
- int targetAnchorPosition = res .getIDPosition (ref .url .fragment ());
697
+ URLFragment fragment = URLFragment .parse (ref .url , res .getMimeType ());
698
+ int targetAnchorPosition = res .getIDPosition (fragment .getId ());
678
699
if (targetAnchorPosition < lastAnchorPosition )
679
700
{
680
701
String orderContext = LocalizedMessages .getInstance (locale ).getSuggestion (MessageId .NAV_011 ,
0 commit comments