|  | @@ -2,6 +2,7 @@
 | 
		
	
		
			
			| 2 | 2 |  // Created by robin on 7/22/16.
 | 
		
	
		
			
			| 3 | 3 |  //
 | 
		
	
		
			
			| 4 | 4 |  
 | 
		
	
		
			
			|  | 5 | +#include <DBO/StringUtils.h>
 | 
		
	
		
			
			| 5 | 6 |  #include "FreeFareTagBusiness.h"
 | 
		
	
		
			
			| 6 | 7 |  
 | 
		
	
		
			
			| 7 | 8 |  FreeFareTagBusiness::FreeFareTagBusiness(std::shared_ptr<FreeFareTag> tag)
 | 
		
	
	
		
			
			|  | @@ -14,42 +15,6 @@ ResultBool FreeFareTagBusiness::authenticate(int sector, std::string key, int ke
 | 
		
	
		
			
			| 14 | 15 |      return _tag->authenticate(sector, key, keyType);
 | 
		
	
		
			
			| 15 | 16 |  }
 | 
		
	
		
			
			| 16 | 17 |  
 | 
		
	
		
			
			| 17 |  | -ResultString FreeFareTagBusiness::readBlock(int sector, int block, std::string key, int keyType)
 | 
		
	
		
			
			| 18 |  | -{
 | 
		
	
		
			
			| 19 |  | -    return _tag->readBlock(sector, block, key, keyType);
 | 
		
	
		
			
			| 20 |  | -}
 | 
		
	
		
			
			| 21 |  | -
 | 
		
	
		
			
			| 22 |  | -Result<SectorDbo> FreeFareTagBusiness::readSector(int sector, std::string key, int keyType)
 | 
		
	
		
			
			| 23 |  | -{
 | 
		
	
		
			
			| 24 |  | -    std::string res;
 | 
		
	
		
			
			| 25 |  | -    int lastBlock = _tag->getSectorBlockCount(sector);
 | 
		
	
		
			
			| 26 |  | -    for (int i = 0; i < lastBlock; ++i) {
 | 
		
	
		
			
			| 27 |  | -        auto data = readBlock(sector, i, key, keyType);
 | 
		
	
		
			
			| 28 |  | -        if (data) {
 | 
		
	
		
			
			| 29 |  | -            res += data.getData();
 | 
		
	
		
			
			| 30 |  | -        }
 | 
		
	
		
			
			| 31 |  | -        else {
 | 
		
	
		
			
			| 32 |  | -            return Result<SectorDbo>::error(data);
 | 
		
	
		
			
			| 33 |  | -        }
 | 
		
	
		
			
			| 34 |  | -    }
 | 
		
	
		
			
			| 35 |  | -    return Result<SectorDbo>::ok(SectorDbo(res));
 | 
		
	
		
			
			| 36 |  | -}
 | 
		
	
		
			
			| 37 |  | -
 | 
		
	
		
			
			| 38 |  | -const std::string &FreeFareTagBusiness::getUid() const
 | 
		
	
		
			
			| 39 |  | -{
 | 
		
	
		
			
			| 40 |  | -    return _tag->getUid();
 | 
		
	
		
			
			| 41 |  | -}
 | 
		
	
		
			
			| 42 |  | -
 | 
		
	
		
			
			| 43 |  | -freefare_tag_type FreeFareTagBusiness::getType() const
 | 
		
	
		
			
			| 44 |  | -{
 | 
		
	
		
			
			| 45 |  | -    return _tag->getType();
 | 
		
	
		
			
			| 46 |  | -}
 | 
		
	
		
			
			| 47 |  | -
 | 
		
	
		
			
			| 48 |  | -std::shared_ptr<FreeFareTag> FreeFareTagBusiness::getTag() const
 | 
		
	
		
			
			| 49 |  | -{
 | 
		
	
		
			
			| 50 |  | -    return _tag;
 | 
		
	
		
			
			| 51 |  | -}
 | 
		
	
		
			
			| 52 |  | -
 | 
		
	
		
			
			| 53 | 18 |  Result<MappedKeys> FreeFareTagBusiness::mapKeys(std::vector<std::string> keys, std::function<void(int, int)> cb)
 | 
		
	
		
			
			| 54 | 19 |  {
 | 
		
	
		
			
			| 55 | 20 |      MappedKeys mappedKeys;
 | 
		
	
	
		
			
			|  | @@ -82,10 +47,31 @@ Result<MappedKeys> FreeFareTagBusiness::mapKeys(std::vector<std::string> keys, s
 | 
		
	
		
			
			| 82 | 47 |      return Result<MappedKeys>::ok(mappedKeys);
 | 
		
	
		
			
			| 83 | 48 |  }
 | 
		
	
		
			
			| 84 | 49 |  
 | 
		
	
		
			
			| 85 |  | -Result<std::vector<SectorDbo>> FreeFareTagBusiness::dump(MappedKeys keys, std::function<void(int, int)> cb)
 | 
		
	
		
			
			|  | 50 | +ResultString FreeFareTagBusiness::readBlock(int sector, int block, std::string key, int keyType)
 | 
		
	
		
			
			|  | 51 | +{
 | 
		
	
		
			
			|  | 52 | +    return _tag->readBlock(sector, block, key, keyType);
 | 
		
	
		
			
			|  | 53 | +}
 | 
		
	
		
			
			|  | 54 | +
 | 
		
	
		
			
			|  | 55 | +Result<SectorDbo> FreeFareTagBusiness::readSector(int sector, std::string key, int keyType)
 | 
		
	
		
			
			|  | 56 | +{
 | 
		
	
		
			
			|  | 57 | +    std::string res;
 | 
		
	
		
			
			|  | 58 | +    int lastBlock = _tag->getSectorBlockCount(sector);
 | 
		
	
		
			
			|  | 59 | +    for (int i = 0; i < lastBlock; ++i) {
 | 
		
	
		
			
			|  | 60 | +        auto data = readBlock(sector, i, key, keyType);
 | 
		
	
		
			
			|  | 61 | +        if (data) {
 | 
		
	
		
			
			|  | 62 | +            res += data.getData();
 | 
		
	
		
			
			|  | 63 | +        }
 | 
		
	
		
			
			|  | 64 | +        else {
 | 
		
	
		
			
			|  | 65 | +            return Result<SectorDbo>::error(data);
 | 
		
	
		
			
			|  | 66 | +        }
 | 
		
	
		
			
			|  | 67 | +    }
 | 
		
	
		
			
			|  | 68 | +    return Result<SectorDbo>::ok(SectorDbo(res));
 | 
		
	
		
			
			|  | 69 | +}
 | 
		
	
		
			
			|  | 70 | +
 | 
		
	
		
			
			|  | 71 | +Result<std::vector<SectorDbo>> FreeFareTagBusiness::read(MappedKeys keys, std::function<void(int, int)> cb)
 | 
		
	
		
			
			| 86 | 72 |  {
 | 
		
	
		
			
			| 87 | 73 |      if (keys.size() != 16) {
 | 
		
	
		
			
			| 88 |  | -        return Result<std::vector<SectorDbo>>::error("Must have 16 sectors");
 | 
		
	
		
			
			|  | 74 | +        return Result<std::vector<SectorDbo>>::error("Must have 16 sectors keys");
 | 
		
	
		
			
			| 89 | 75 |      }
 | 
		
	
		
			
			| 90 | 76 |      int done = 0;
 | 
		
	
		
			
			| 91 | 77 |      int total = 4 * keys.size();
 | 
		
	
	
		
			
			|  | @@ -164,11 +150,112 @@ Result<std::vector<SectorDbo>> FreeFareTagBusiness::dump(MappedKeys keys, std::f
 | 
		
	
		
			
			| 164 | 150 |      return Result<std::vector<SectorDbo>>::ok(sectors);
 | 
		
	
		
			
			| 165 | 151 |  }
 | 
		
	
		
			
			| 166 | 152 |  
 | 
		
	
		
			
			| 167 |  | -Result<std::vector<SectorDbo>> FreeFareTagBusiness::dump(std::vector<std::string> keys, std::function<void(int, int)> mapCb, std::function<void(int, int)> dumpCb)
 | 
		
	
		
			
			|  | 153 | +Result<std::vector<SectorDbo>> FreeFareTagBusiness::read(std::vector<std::string> keys, std::function<void(int, int)> mapCb,
 | 
		
	
		
			
			|  | 154 | +                                                         std::function<void(int, int)> dumpCb)
 | 
		
	
		
			
			| 168 | 155 |  {
 | 
		
	
		
			
			| 169 | 156 |      auto mappedKeysResult = mapKeys(keys, mapCb);
 | 
		
	
		
			
			| 170 | 157 |      if (!mappedKeysResult) {
 | 
		
	
		
			
			| 171 | 158 |          return Result<std::vector<SectorDbo>>::error(mappedKeysResult);
 | 
		
	
		
			
			| 172 | 159 |      }
 | 
		
	
		
			
			| 173 |  | -    return dump(mappedKeysResult.getData(), dumpCb);
 | 
		
	
		
			
			|  | 160 | +    return read(mappedKeysResult.getData(), dumpCb);
 | 
		
	
		
			
			|  | 161 | +}
 | 
		
	
		
			
			|  | 162 | +
 | 
		
	
		
			
			|  | 163 | +ResultBool FreeFareTagBusiness::writeBlock(int sector, int block, std::string key, int keyType, const std::string &data)
 | 
		
	
		
			
			|  | 164 | +{
 | 
		
	
		
			
			|  | 165 | +    return _tag->writeBlock(sector, block, key, keyType, StringUtils::ensureSize(data, 16));
 | 
		
	
		
			
			|  | 166 | +}
 | 
		
	
		
			
			|  | 167 | +
 | 
		
	
		
			
			|  | 168 | +ResultBool FreeFareTagBusiness::writeSector(int sector, std::string key, int keyType, const std::string &data)
 | 
		
	
		
			
			|  | 169 | +{
 | 
		
	
		
			
			|  | 170 | +    std::string d = StringUtils::ensureSize(data, 64);
 | 
		
	
		
			
			|  | 171 | +    std::string errors;
 | 
		
	
		
			
			|  | 172 | +    for (int b = 0; b < 4; ++b) {
 | 
		
	
		
			
			|  | 173 | +        auto result = writeBlock(sector, b, key, keyType, d.substr(b * 16, 16));
 | 
		
	
		
			
			|  | 174 | +        if (!result) {
 | 
		
	
		
			
			|  | 175 | +            errors += std::string(errors.empty() ? "" : "\n") + "Failed to write sector " + std::to_string(sector) +
 | 
		
	
		
			
			|  | 176 | +                      " block " + std::to_string(b) + " with key " + (keyType == MFC_KEY_A ? "A" : "B") + ": " + result.getError();
 | 
		
	
		
			
			|  | 177 | +        }
 | 
		
	
		
			
			|  | 178 | +    }
 | 
		
	
		
			
			|  | 179 | +    if (errors.empty()) {
 | 
		
	
		
			
			|  | 180 | +        return ResultBool::ok(true);
 | 
		
	
		
			
			|  | 181 | +    }
 | 
		
	
		
			
			|  | 182 | +    return ResultBool::error(errors);
 | 
		
	
		
			
			|  | 183 | +}
 | 
		
	
		
			
			|  | 184 | +
 | 
		
	
		
			
			|  | 185 | +ResultBool FreeFareTagBusiness::write(MappedKeys keys, const std::string &data, bool writeSector0, std::function<void(int, int)> cb)
 | 
		
	
		
			
			|  | 186 | +{
 | 
		
	
		
			
			|  | 187 | +    if (keys.size() != 16) {
 | 
		
	
		
			
			|  | 188 | +        return ResultBool::error("Must have 16 sectors keys");
 | 
		
	
		
			
			|  | 189 | +    }
 | 
		
	
		
			
			|  | 190 | +    std::string d = StringUtils::ensureSize(data, 1024);
 | 
		
	
		
			
			|  | 191 | +    std::string errors;
 | 
		
	
		
			
			|  | 192 | +    int done = 0;
 | 
		
	
		
			
			|  | 193 | +    int total = 4 * (keys.size() - (writeSector0 ? 0 : 1));
 | 
		
	
		
			
			|  | 194 | +    for (int s = writeSector0 ? 0 : 1; s < keys.size(); ++s) {
 | 
		
	
		
			
			|  | 195 | +        auto sectorKey = keys[s];
 | 
		
	
		
			
			|  | 196 | +        for (int b = 0; b < 4; ++b) {
 | 
		
	
		
			
			|  | 197 | +            std::string blockData = d.substr((s * 64) + (b * 16), 16);
 | 
		
	
		
			
			|  | 198 | +            if (cb != 0 && done < total) {
 | 
		
	
		
			
			|  | 199 | +                bool keyA = false;
 | 
		
	
		
			
			|  | 200 | +                bool keyB = false;
 | 
		
	
		
			
			|  | 201 | +                std::string sectorErrors;
 | 
		
	
		
			
			|  | 202 | +                if (!sectorKey.first.empty()) {
 | 
		
	
		
			
			|  | 203 | +                    auto resultA = writeBlock(s, b, sectorKey.first, MFC_KEY_A, blockData);
 | 
		
	
		
			
			|  | 204 | +                    if (resultA) {
 | 
		
	
		
			
			|  | 205 | +                        keyA = true;
 | 
		
	
		
			
			|  | 206 | +                    }
 | 
		
	
		
			
			|  | 207 | +                    else {
 | 
		
	
		
			
			|  | 208 | +                        sectorErrors = "Failed to write sector " + std::to_string(s) +
 | 
		
	
		
			
			|  | 209 | +                                       " block " + std::to_string(b) + " with key A: " + resultA.getError();
 | 
		
	
		
			
			|  | 210 | +                    }
 | 
		
	
		
			
			|  | 211 | +                }
 | 
		
	
		
			
			|  | 212 | +                if (!keyA && !sectorKey.second.empty()) {
 | 
		
	
		
			
			|  | 213 | +                    auto resultB = writeBlock(s, b, sectorKey.first, MFC_KEY_A, blockData);
 | 
		
	
		
			
			|  | 214 | +                    if (resultB) {
 | 
		
	
		
			
			|  | 215 | +                        keyB = true;
 | 
		
	
		
			
			|  | 216 | +                    }
 | 
		
	
		
			
			|  | 217 | +                    else {
 | 
		
	
		
			
			|  | 218 | +                        sectorErrors = std::string(sectorErrors.empty() ? "" : "\n") + "Failed to write sector " + std::to_string(s) +
 | 
		
	
		
			
			|  | 219 | +                                       " block " + std::to_string(b) + " with key B: " + resultB.getError();
 | 
		
	
		
			
			|  | 220 | +                    }
 | 
		
	
		
			
			|  | 221 | +                }
 | 
		
	
		
			
			|  | 222 | +                if (!keyA && !keyB) {
 | 
		
	
		
			
			|  | 223 | +                    errors += std::string(errors.empty() ? "" : "\n") + sectorErrors;
 | 
		
	
		
			
			|  | 224 | +                }
 | 
		
	
		
			
			|  | 225 | +                cb(++done, total);
 | 
		
	
		
			
			|  | 226 | +            }
 | 
		
	
		
			
			|  | 227 | +        }
 | 
		
	
		
			
			|  | 228 | +    }
 | 
		
	
		
			
			|  | 229 | +    if (cb != 0 && done < total) {
 | 
		
	
		
			
			|  | 230 | +        cb(total, total);
 | 
		
	
		
			
			|  | 231 | +    }
 | 
		
	
		
			
			|  | 232 | +    if (errors.empty()) {
 | 
		
	
		
			
			|  | 233 | +        return ResultBool::ok(true);
 | 
		
	
		
			
			|  | 234 | +    }
 | 
		
	
		
			
			|  | 235 | +    return ResultBool::error(errors);
 | 
		
	
		
			
			|  | 236 | +}
 | 
		
	
		
			
			|  | 237 | +
 | 
		
	
		
			
			|  | 238 | +ResultBool FreeFareTagBusiness::write(std::vector<std::string> keys, const std::string &data, bool writeSector0,
 | 
		
	
		
			
			|  | 239 | +                                      std::function<void(int, int)> mapCb, std::function<void(int, int)> dumpCb)
 | 
		
	
		
			
			|  | 240 | +{
 | 
		
	
		
			
			|  | 241 | +    auto mappedKeysResult = mapKeys(keys, mapCb);
 | 
		
	
		
			
			|  | 242 | +    if (!mappedKeysResult) {
 | 
		
	
		
			
			|  | 243 | +        return ResultBool::error(mappedKeysResult);
 | 
		
	
		
			
			|  | 244 | +    }
 | 
		
	
		
			
			|  | 245 | +    return write(mappedKeysResult.getData(), data, writeSector0, dumpCb);
 | 
		
	
		
			
			|  | 246 | +}
 | 
		
	
		
			
			|  | 247 | +
 | 
		
	
		
			
			|  | 248 | +const std::string &FreeFareTagBusiness::getUid() const
 | 
		
	
		
			
			|  | 249 | +{
 | 
		
	
		
			
			|  | 250 | +    return _tag->getUid();
 | 
		
	
		
			
			|  | 251 | +}
 | 
		
	
		
			
			|  | 252 | +
 | 
		
	
		
			
			|  | 253 | +freefare_tag_type FreeFareTagBusiness::getType() const
 | 
		
	
		
			
			|  | 254 | +{
 | 
		
	
		
			
			|  | 255 | +    return _tag->getType();
 | 
		
	
		
			
			|  | 256 | +}
 | 
		
	
		
			
			|  | 257 | +
 | 
		
	
		
			
			|  | 258 | +std::shared_ptr<FreeFareTag> FreeFareTagBusiness::getTag() const
 | 
		
	
		
			
			|  | 259 | +{
 | 
		
	
		
			
			|  | 260 | +    return _tag;
 | 
		
	
		
			
			| 174 | 261 |  }
 |