base64 img src в WebUI приводит к ошибке

Вот проблемная часть шаблона:

<ul id="list">
  <template iterate='file in convertedfiles.files'>
    <li>{{file.filename}}
    <template if='file.isImage'>
      <img src="{{file.src}}" alt="{{file.filename}}"><br/>
      Source: {{file.src}}
     </template>
    </li>
  </template>
</ul>

convertfiles — это список AndroidFile:

class AndroidFile {
File _file;  

String filename;
String src;
bool isImage;

AndroidFile(this._file) : isImage = false {
    filename = htmlEscape(_file.name);

    // If the file is an image, read and display its thumbnail.
    if (_file.type.startsWith('image')) {
    FileReader reader = new FileReader();
    reader.on.load.add((e) {
        src = reader.result.toString().trim();

        // prints the correct URL (data:image/png;base64,...)
        print(src);
        isImage = true;  
        watcher.dispatch();
      });

    reader.readAsDataUrl(_file);  
    }
  }
}

Шаблон отображается. Он показывает имя файла, он показывает источник, но тег изображения выглядит так:

 <img alt="screenshot-1179.png" src="#"> 

Хэш подчеркнут (в исходном представлении Chromium), и если я нажму на него, появится сообщение «Файл не найден: /web/out/»

Преобразованный в JS в Chrome говорится: «Ресурс интерпретируется как изображение, но передается с типом MIME text/html».

Исходный код находится на GitHub
Есть подсказки?


person Mike Mitterer    schedule 30.12.2012    source источник


Ответы (2)


Обратите внимание: если вы знаете, что работаете с безопасным URI, который не уязвим для XSS, вы можете обойти эту проблему, используя оболочку SafeUri (импортированную из web_ui/web_ui.dart). Например, измените свой шаблон с:

<img src="{{file.src}}" alt="{{file.filename}}">

to:

<img src="{{new SafeUri.unsafe(file.src)}}" alt="{{file.filename}}">

Или измените файл file.src внутри, чтобы сохранить SafeUri.

person Siggi Cherem    schedule 02.01.2013
comment
Спасибо Сигги! Отличная поддержка. - person Mike Mitterer; 03.01.2013
comment
В моем случае (SDK 0.2.9.9_r16323 и WebUI 0.2.9) мне пришлось использовать: import 'package:web_ui/safe_html.dart'; safeuri = новый SafeUri.unsafe(src); для хранения SafeUri. Есть только этот именованный конструктор. А вот с этим - работает просто идеально. - person Mike Mitterer; 03.01.2013
comment
В настоящее время это new SafeUri.unsafe(). Я обновлю ответ. - person Kai Sellgren; 08.02.2013

Я нашел проблему.

Это потому, что URI дезинфицируется из соображений безопасности. Дезинфицирующее средство превращает недопустимые URI в хэш #.

От web_ui/templating.dart:

/**
 * Ensure that [usiString] is a safe URI. Otherwise, return a '#' URL.
 *
 * The logic in this method was based on the GWT implementation located at:
 * http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/gwt/safehtml/shared/UriUtils.java
 */
String sanitizeUri(uri) {
  if (uri is SafeUri) return uri.toString();
  uri = uri.toString();
  return _isSafeUri(uri) ? uri : '#';
}

const _SAFE_SCHEMES = const ["http", "https", "ftp", "mailto"];

bool _isSafeUri(String uri) {
  var scheme = new Uri(uri).scheme;
  if (scheme == '') return true;

  // There are two checks for mailto to correctly handle the Turkish locale.
  //   i -> to upper in Turkish locale -> İ
  //   I -> to lower in Turkish locale -> ı
  // For details, see: http://www.i18nguy.com/unicode/turkish-i18n.html
  return _SAFE_SCHEMES.contains(scheme.toLowerCase()) ||
      "MAILTO" == scheme.toUpperCase();
}

Таким образом, дезинфицирующее средство превращает ваш URI схемы data: в #. URI данных можно использовать для XSS, но, насколько мне известно, проверку можно улучшить, разрешив URI данных, когда тип содержимого URI данных равен image/*.

Может быть, написать отчет об ошибке?

person Kai Sellgren    schedule 31.12.2012
comment
Здесь github.com/dart-lang/web-ui/issues/286 это проблема, если кто-то хочет следовать... - person Mike Mitterer; 01.01.2013