Guest User

Untitled

a guest
Jan 13th, 2019
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.33 KB | None | 0 0
  1. void Main()
  2. {
  3. var outputPath = $@"./bitwarden_import/bitwarden_importdata{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.json";
  4. var teamsidPersonalCsv = @"./teamsid_export/indivisual_records_2019-01-12 20_08_36.csv";
  5. var teamsidOrganizationCsv = @"./teamsid_export/Organization_records_2019-01-12 21_20_10.csv";
  6. var teamsidCsvs = new[] { teamsidPersonalCsv, teamsidOrganizationCsv };
  7. var bitwardenFolderDefinitionJson = @"./bitwarden_export/bitwarden_export_folder_definition.json";
  8.  
  9. // deserialize folder definitions
  10. BitwardenFolderDefinition DeserializeFolderJson(string path)
  11. {
  12. using (var stream = File.OpenRead(path))
  13. {
  14. var folders = Utf8Json.JsonSerializer.Deserialize<BitwardenFolderDefinition>(stream);
  15. return folders;
  16. }
  17. }
  18. var folderDefinition = DeserializeFolderJson(bitwardenFolderDefinitionJson);
  19.  
  20. // convert teamsid to bitwarden
  21. var combinedResult = teamsidCsvs.SelectMany(json =>
  22. {
  23. var parser = new CsvParser(json);
  24. var teamsIdDatas = parser.Parse<TeamsId>();
  25. var bitwardenItems = new BitwardenConverter().Convert(teamsIdDatas, folderDefinition, "Socials");
  26. return bitwardenItems;
  27. })
  28. .ToArray();
  29.  
  30. combinedResult.Dump();
  31. // serialize bitwarden import data
  32. var importData = new BitwardenDefinition
  33. {
  34. folders = folderDefinition.folders,
  35. items = combinedResult,
  36. };
  37. var jsonBytes = Utf8Json.JsonSerializer.Serialize<BitwardenDefinition>(importData);
  38.  
  39. // output json
  40. File.WriteAllBytes(outputPath, jsonBytes);
  41. }
  42.  
  43. public class BitwardenConverter
  44. {
  45. private class FieldRecord
  46. {
  47. public string Url { get; set; }
  48. public string Email { get; set; }
  49. public string UserName { get; set; }
  50. public string Password { get; set; }
  51. public (string key, string value)[] SecureFields { get; set; }
  52. public (string key, string value)[] Fields { get; set; }
  53. public string Group { get; set; }
  54. }
  55.  
  56. public BitwardenItem[] Convert(TeamsId[] from, BitwardenFolderDefinition folderDefinition, string defaultGroup = null)
  57. {
  58. var records = from
  59. .Select(record =>
  60. {
  61. // reflection to check fieldXX and get valueXX
  62. var t = record.GetType();
  63. var props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
  64. var description = GetPropertyValue(record, t, "description");
  65. var note = GetPropertyValue(record, t, "note");
  66. var fieldRecord = ParseFieldRecord(props, t, record, defaultGroup);
  67.  
  68. // generate typed item
  69. var bitwarden = new BitwardenItem
  70. {
  71. id = Guid.NewGuid().ToString(),
  72. organizationId = null,
  73. collectionIds = null,
  74. type = 1,
  75. name = description,
  76. login = new BitwardenLogin
  77. {
  78. username = fieldRecord.UserName,
  79. password = fieldRecord.Password,
  80. uris = new[] {
  81. new BitwardenUri
  82. {
  83. uri = fieldRecord.Url,
  84. match = null,
  85. }
  86. }
  87. },
  88. favorite = false,
  89. notes = note,
  90. folderId = folderDefinition.GetId(fieldRecord.Group),
  91. };
  92. // initialize fields
  93. var customField = fieldRecord.Fields == null
  94. ? Array.Empty<BitwardenField>()
  95. : fieldRecord.Fields.Select(x => new BitwardenField { name = x.key, value = x.value, type = 0 });
  96. var customSecretField = fieldRecord.SecureFields == null
  97. ? Array.Empty<BitwardenField>()
  98. : fieldRecord.SecureFields.Select(x => new BitwardenField { name = x.key, value = x.value, type = 1 });
  99. var fields = customField.Concat(customSecretField).ToArray();
  100. if (fields.Any())
  101. {
  102. bitwarden.fields = fields;
  103. }
  104. return bitwarden;
  105. })
  106. .ToArray();
  107. return records;
  108. }
  109.  
  110. private FieldRecord ParseFieldRecord(PropertyInfo[] props, Type t, TeamsId source, string defaultGroup = null)
  111. {
  112. var fieldRecord = new FieldRecord();
  113. // get FieldXX properties via reflection
  114. var fieldRecords = props
  115. .Where(x => Match(x.Name, @"Field\d+"))
  116. .Where(x => GetPropertyValue(source, t, x.Name) != "")
  117. .Select(x => (key: GetPropertyValue(source, t, x.Name), value: GetPropertyValue(source, t, x.Name.Replace("Field", "Value"))))
  118. .ToArray();
  119.  
  120. // get field's value and categolize each via field name regex pattern
  121. var secureMemoList = new List<(string, string)>();
  122. var memoList = new List<(string, string)>();
  123. foreach (var record in fieldRecords)
  124. {
  125. switch (record.key)
  126. {
  127. case var _ when Match(record.key, "url") && fieldRecord.Url == null:
  128. fieldRecord.Url = record.value;
  129. break;
  130. case var _ when Match(record.key, "email|e-mail") && fieldRecord.Email == null:
  131. fieldRecord.Email = record.value;
  132. break;
  133. case var _ when Match(record.key, "username") && fieldRecord.UserName == null:
  134. fieldRecord.UserName = record.value;
  135. break;
  136. case var _ when Match(record.key, "password") && fieldRecord.Password == null:
  137. fieldRecord.Password = record.value;
  138. break;
  139. case var _ when Match(record.key, "pass|access|secret|pin|token|enctypt"):
  140. secureMemoList.Add((record.key, record.value));
  141. break;
  142. case var _ when Match(record.key, "group"):
  143. fieldRecord.Group = record.value;
  144. break;
  145. default:
  146. memoList.Add((record.key, record.value));
  147. break;
  148. }
  149. }
  150. // group fallback
  151. if (defaultGroup != null && string.IsNullOrWhiteSpace(fieldRecord.Group))
  152. {
  153. fieldRecord.Group = defaultGroup;
  154. }
  155. fieldRecord.Fields = memoList.ToArray();
  156. fieldRecord.SecureFields = secureMemoList.ToArray();
  157. return fieldRecord;
  158. }
  159.  
  160. private bool Match(string text, string pattern)
  161. {
  162. return Regex.IsMatch(text, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
  163. }
  164.  
  165. private string GetPropertyValue(TeamsId record, Type t, string propertyField)
  166. {
  167. return (string)t.GetProperty(propertyField).GetValue(record);
  168. }
  169. }
  170.  
  171. public class CsvParser
  172. {
  173. private readonly string path;
  174.  
  175. public CsvParser(string path)
  176. {
  177. this.path = path;
  178. }
  179.  
  180. public T[] Parse<T>() where T : class
  181. {
  182. using (var reader = new StreamReader(path))
  183. using (var csv = new CsvReader(reader))
  184. {
  185. csv.Configuration.MissingFieldFound = null;
  186. var records = csv.GetRecords<T>();
  187. return records.ToArray();
  188. }
  189. }
  190. }
  191.  
  192. public class BitwardenDefinition
  193. {
  194. public BitwardenFolder[] folders { get; set; }
  195. public BitwardenItem[] items {get;set;}
  196. }
  197.  
  198. public class BitwardenItem
  199. {
  200. public string id { get; set; }
  201. public string organizationId { get; set; }
  202. public string collectionIds { get; set; }
  203. public bool favorite { get; set; }
  204. public string folderId { get; set; }
  205. // login = 1, card = 3
  206. public int type { get; set; }
  207. public string name { get; set; }
  208. public string notes { get; set; }
  209. public BitwardenField[] fields { get; set; }
  210. public BitwardenLogin login { get; set; }
  211. }
  212.  
  213. public class BitwardenLogin
  214. {
  215. public BitwardenUri[] uris { get; set; }
  216. public string username { get; set; }
  217. public string password { get; set; }
  218. // authenticator = null (premium only)
  219. public string totp { get; set; }
  220. }
  221.  
  222. public class BitwardenUri
  223. {
  224. // default = null
  225. public object match { get; set; }
  226. public string uri { get; set; }
  227. }
  228.  
  229. public class BitwardenField
  230. {
  231. public string name { get; set; }
  232. public string value { get; set; }
  233. // custom = 0, hidden = 1, boolean = 2
  234. public int type { get; set; }
  235. }
  236.  
  237. public class BitwardenFolderDefinition
  238. {
  239. public BitwardenFolder[] folders { get; set; }
  240.  
  241. private static readonly string defaultIdName = "Social";
  242. public string GetId(string name)
  243. {
  244. if (folders == null || !folders.Any()) return defaultIdName;
  245. return folders.FirstOrDefault(x => x.name == name)?.id ?? defaultIdName;
  246. }
  247. }
  248.  
  249. public class BitwardenFolder
  250. {
  251. public string id { get; set; }
  252. public string name { get; set; }
  253. }
  254.  
  255. public class TeamsId
  256. {
  257. public string description { get; set; }
  258. public string note { get; set; }
  259. public string Field0 { get; set; }
  260. public string Type0 { get; set; }
  261. public string Value0 { get; set; }
  262. public string Field1 { get; set; }
  263. public string Type1 { get; set; }
  264. public string Value1 { get; set; }
  265. public string Field2 { get; set; }
  266. public string Type2 { get; set; }
  267. public string Value2 { get; set; }
  268. public string Field3 { get; set; }
  269. public string Type3 { get; set; }
  270. public string Value3 { get; set; }
  271. public string Field4 { get; set; }
  272. public string Type4 { get; set; }
  273. public string Value4 { get; set; }
  274. public string Field5 { get; set; }
  275. public string Type5 { get; set; }
  276. public string Value5 { get; set; }
  277. public string Field6 { get; set; }
  278. public string Type6 { get; set; }
  279. public string Value6 { get; set; }
  280. public string Field7 { get; set; }
  281. public string Type7 { get; set; }
  282. public string Value7 { get; set; }
  283. public string Field8 { get; set; }
  284. public string Type8 { get; set; }
  285. public string Value8 { get; set; }
  286. public string Field9 { get; set; }
  287. public string Type9 { get; set; }
  288. public string Value9 { get; set; }
  289. public string Field10 { get; set; }
  290. public string Type10 { get; set; }
  291. public string Value10 { get; set; }
  292. public string Field11 { get; set; }
  293. public string Type11 { get; set; }
  294. public string Value11 { get; set; }
  295. public string Field12 { get; set; }
  296. public string Type12 { get; set; }
  297. public string Value12 { get; set; }
  298. }
Add Comment
Please, Sign In to add comment