summaryrefslogtreecommitdiffstats
path: root/chrome/utility/media_galleries/picasa_album_table_reader.cc
blob: 2dcfc0736dc0f83679da212d4838e9049917ede3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/utility/media_galleries/picasa_album_table_reader.h"

#include <algorithm>
#include <string>

#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/common/media_galleries/pmp_constants.h"
#include "chrome/utility/media_galleries/pmp_column_reader.h"

namespace picasa {

namespace {

// |variant_time| is specified as the number of days from Dec 30, 1899.
base::Time TimeFromMicrosoftVariantTime(double variant_time) {
  base::TimeDelta variant_delta = base::TimeDelta::FromMicroseconds(
      static_cast<int64>(variant_time * base::Time::kMicrosecondsPerDay));

  return base::Time::FromLocalExploded(kPmpVariantTimeEpoch) + variant_delta;
}

}  // namespace

PicasaAlbumTableReader::PicasaAlbumTableReader(AlbumTableFiles table_files)
    : table_files_(table_files.Pass()),
      initialized_(false) {
}

PicasaAlbumTableReader::~PicasaAlbumTableReader() {
}

const std::vector<AlbumInfo>& PicasaAlbumTableReader::folders() const {
  DCHECK(initialized_);
  return folders_;
}

const std::vector<AlbumInfo>& PicasaAlbumTableReader::albums() const {
  DCHECK(initialized_);
  return albums_;
}

bool PicasaAlbumTableReader::Init() {
  if (initialized_)
    return true;

  if (!table_files_.indicator_file.IsValid())
    return false;

  PmpColumnReader category_column, date_column, filename_column, name_column,
                  token_column, uid_column;
  if (!category_column.ReadFile(&table_files_.category_file, PMP_TYPE_UINT32) ||
      !date_column.ReadFile(&table_files_.date_file, PMP_TYPE_DOUBLE64) ||
      !filename_column.ReadFile(&table_files_.filename_file, PMP_TYPE_STRING) ||
      !name_column.ReadFile(&table_files_.name_file, PMP_TYPE_STRING) ||
      !token_column.ReadFile(&table_files_.token_file, PMP_TYPE_STRING) ||
      !uid_column.ReadFile(&table_files_.uid_file, PMP_TYPE_STRING)) {
    return false;
  }

  // In the PMP format, columns can be different lengths. The number of rows
  // in the table is max of all the columns, and short columns are NULL padded.
  uint32 row_count = 0;
  row_count = std::max(row_count, category_column.rows_read());
  row_count = std::max(row_count, date_column.rows_read());
  row_count = std::max(row_count, filename_column.rows_read());
  row_count = std::max(row_count, name_column.rows_read());
  row_count = std::max(row_count, token_column.rows_read());
  row_count = std::max(row_count, uid_column.rows_read());

  for (uint32 i = 0; i < row_count; i++) {
    uint32 category = kAlbumCategoryInvalid;
    double date = 0;
    std::string name;
    std::string uid;
    // PMP tables often contain 'garbage' rows of deleted or auto-generated
    // album-like entities. We ignore those rows.
    if (!category_column.ReadUInt32(i, &category) ||
        !date_column.ReadDouble64(i, &date) ||
        !name_column.ReadString(i, &name) || name.empty() ||
        !uid_column.ReadString(i, &uid) || uid.empty()) {
      continue;
    }

    base::Time timestamp = TimeFromMicrosoftVariantTime(date);

    if (category == kAlbumCategoryAlbum) {
      std::string token;
      if (!token_column.ReadString(i, &token) || token.empty() ||
          !StartsWithASCII(token, kAlbumTokenPrefix, false)) {
        continue;
      }

      albums_.push_back(AlbumInfo(name, timestamp, uid, base::FilePath()));
    } else if (category == kAlbumCategoryFolder) {
      std::string filename;
      if (!filename_column.ReadString(i, &filename) || filename.empty())
        continue;

      base::FilePath path =
          base::FilePath(base::FilePath::FromUTF8Unsafe(filename));

      folders_.push_back(AlbumInfo(name, timestamp, uid, path));
    }
  }

  initialized_ = true;
  return true;
}

}  // namespace picasa