MrC's Convert to 1Password Utility (mrc-converter-suite)
Comments
-
Hi @TilRoquette ,
Can you confirm that the directory
/Applications/mSecure.app/Contents/Resources
exists? It is possible that your version, mSecure 5.1.56.0, has moved the localization files.I'll likely have to install that version today to test it out.
0 -
I've installed the new version of the app from the App store. Apparently there are no language files for version 5.x, so that's why the converter fails to detect the language.
You could try adding the German language file to the location:
/Applications/mSecure.app/Contents/Resources/de.lproj/Localizable.strings
I've uploaded a zip file archive that contains the folder de.lproj and inside it, a file named Localizable.strings. It is located in Testing Bits, mentioned in the first post of the converter suite thread. The file is called de.lproj.zip.
If you have trouble getting that file installed (due to Sierra's locked down environment), you may have to export your data first, and then remove the 5.x version, and install the 3.5.x version (but hopefully you don't need to go through this trouble).
Alternatively, I could just do a quick update of the converter to read strings from my local Languages folder as well, and provide you with the strings file.
Let me know if any of this helps, or how you'd like to proceed.
0 -
Hi MrC,
thanks so much for your help!!
However, I do not understand, exactly where exactly I need to place the file Localizable.strings?
I have tried with the mSecure programm directory C:\Program Files (x86)\mSeven Software\mSecure. That did not work
I tried to install an 4.x Version, but stopped it - it seemed to overwrite the newer version.
0 -
You are correct, the 3.5.x version installer will overwrite the newer version's files; this is why I said above you should remove the 5.x version. You can always re-download/re-install version 5. I don't know anything about version 4.x; users have never mentioned export/conversion wasn't working for it specifically, so I presume it would be fine to use like 3.5.x was.
The way you get to the correct path is to Right-Click the mSecure application, and select Show Package Contents. Then you navigate down the path into Contents, then Resources. Place the de.lprog folder I provided in the zip there (not the zip file, the de.lprog folder with its contents).
The current code is looking for the localization files inside the application bundle (at the path mentioned above). If you don't want to uninstall version 5, then I could add some code to the converter so that it will also look in the converter's Languages directory for the localization files.
Edit: I've added code to look for localization files in the converter's Languages folder. I'm testing it now. However, I'm having difficulty producing data in German using version 5.x from the Mac App Store. Any hints?
0 -
Hi MrC,
I am not sure wether we are talking about the same thing. When you mentioned the Apple App Store, I realized: I didn't tell you that I was on windows plattform: Windows 10!
Probably this explains the following two points
- There is no /Applications/mSecure.app/Contents/Resources on 3.5.x at all. I just realiszed, that I am having mSecure 3.5.5 installed on the terminal server and it looks like this:
mSecure 5.1.56.0 directories look pretty much the same.
There are two files in the C:\Program Files (x86)\mSeven Software\mSecure\de directory. You may download them from here: https://dropbox.com/s/f7ojepikdxa1xtg/de.zip?dl=0 . Does this help?
- When I right-click on mSecure application, there is no option "Show Package Contents".
0 -
I'm sorry, I've been confusing two different but similar issues between you and another user. You're on WIndows, he's on OS X, and they are both about localization.
In both your cases, since your localization files don't exist (either at all, or in the expected location), I have to update the code to allow you to specify where they are.
I'm out for the remainder of the day, but will reply shortly.
Sorry for the confusion.
0 -
Were would I find the updated version?
0 -
@MrC,
a very minor comment on the CSV export/import of the testing bit. I realize that it is not your goal to have round tripping with the CSV format (i.e., that the exported CSV would be importable directly), although I must admit it would be a nice extra feature. (I used it to test what exactly the CSV should look like that I would like to import into 1Password.) But there is an, essentially, arbitrary choice that is probably easy to add to your export script and would make such testing a bit easier: at the moment, if a record has several tags, the script generates a field in the CSV file with the tags separated by a ";" character. However, the CSV import script does not recognize that (and creates a single tag for what was meant to be a list of separate tags), it needs the ',' character. Do you think this could be amended?
The other changes for round tripping are obviously a bit more complex (the record type and the creation dates are added to the output but none of those are recognized by the input and are added to a 'note' field, for example), but maybe it is worth adding that to a future ToDo list...
Thanks for the scripts, I have found now a way to import further records into 1Password with some tweaking on my own data!
0 -
@MrC, sorry for bugging, but: Were would I find the updated version?
Did you see that I uploaded 2 files in the C:\Program Files (x86)\mSeven Software\mSecure\de directory of mSecure 5.1.56.0?
0 -
@TilRoquette , @iherman ,
Sorry for the delay in reply. I've been essentially away from the keyboard for 2 days. I'm working on, and will reply to, each of your matters today.
0 -
I've placed an update to version 1.10 in Testing Bits for you to try. See the first post of this converter suite thread for its location.
Please use the
--lang de
option to specify the German language. It will pick up the language file locally.I found your version 5.x files - you can delete them from your Dropbox folder. Unfortunately, they are binary files and don't readily help me. I'd have to spend some time reverse engineering them, and today is not the right time for that.
Like other users of mSecure, if you have heavily customized your record types, conversion may not work as well as it would with stock Type definitions. However, lets see how far you get, and what might need to be done to provide you with a customized version of the converter.
I do not have version 5 installed, so have not directly tested its export. Please use your 3.5.x export.
0 -
Hi @iherman,
My comments about your post above:
a very minor comment on the CSV export/import of the testing bit. I realize that it is not your goal to have round tripping with the CSV format (i.e., that the exported CSV would be importable directly), although I must admit it would be a nice extra feature. (I used it to test what exactly the CSV should look like that I would like to import into 1Password.)
There would not be perfect round-trip fidelity, and this usage case hasn't ever been requested. CSV really is not a good export format, because the cell data is not self-defined, and cannot handle anything but simple textual flat data.
But there is an, essentially, arbitrary choice that is probably easy to add to your export script and would make such testing a bit easier: at the moment, if a record has several tags, the script generates a field in the CSV file with the tags separated by a ";" character. However, the CSV import script does not recognize that (and creates a single tag for what was meant to be a list of separate tags), it needs the ',' character. Do you think this could be amended?
The choice of semicolon wasn't so much arbitrary as it was chosen to work well with CSV. Using a comma for both the field separator and as a value separator just isn't wise. Still, it can be done.
The docs in for the CSV format in the README.pdf define what's expected in the Tags column:
You may add a column named Tags. If there is a Tags column, the cells should contain any number of comma-separated values to be stored into 1Password’s Tags.
If you want to change the Formatters/csv.pm module to output a comma instead of a semicolon, search the file for Tags and change the line of code:
add_fv_pair(\%v, $category, 'Tags', join "; ", @{$card->{'openContents'}{'tags'}}) if exists $card->{'openContents'}{'tags'};
to:
add_fv_pair(\%v, $category, 'Tags', join ", ", @{$card->{'openContents'}{'tags'}}) if exists $card->{'openContents'}{'tags'};
I don't think it makes sense to add yet another option to the converter or to the suite to handle this rather esoteric usage scenario.
The other changes for round tripping are obviously a bit more complex (the record type and the creation dates are added to the output but none of those are recognized by the input and are added to a 'note' field, for example), but maybe it is worth adding that to a future ToDo list...
I'd wondered in another thread what your ultimate goal was - you'd been implying it was not to be locked into 1Password. But this "round-trip" via CSV is outside that goal, and so yet again, I'm wondering why CSV is so important to you. It will never have the fidelity, nor be self-defined as the 1PIF export is, nor can it have the data complexity as JSON data does. So, what's the point here?
Thanks for the scripts, I have found now a way to import further records into 1Password with some tweaking on my own data!
You are very welcome, and I'm really happy you have a set of tools to help meet your needs!
0 -
Hi @MrC,
Thanks for the quick reply.
First of all, I completely agree with you that the choice of a comma as a separator for tags is not the best option. If the CSV input accepted semicolons for that role, I would be perfectly happy with that. But I guess your hands are tied by what the current 1Password implementation accepts as input. Ie, that choice has been made a while ago...
Second, you are also right that I have different motivations for using CSV, and these may have been a bit mixed up in my mails. Sorry about that. Although I do not expect any actions from you on any of my use cases below, maybe listing them below makes at least my motivations clearer and could be taken in consideration for future changes. Here they are...
- There is that "lock-in" issue that I was referring to. That issue has been solved by the new version of the exporter; the exported CSV includes all my necessary data as a fall back (and I hope I won't need that). Issue closed:-)
- I also have a large amount of data I want to get into 1Password. At the moment, that data is in Apple Number files (previously in Bento), which is fine except that using them on an iPhone is a bit difficult from a user interface point of view. Getting them into a separate vault in 1Password gives me a common user interface to handle data on my phone (or my iPad) which is a major win. (Even if, in fact, that data is not particularly secret, like the list of my books. Ie, one might consider that as a misuse of 1Password, or at least a usage that was not part of the original goals.) CSV import is my only way of doing that. My approach for planning how to do it was to create a few example records in 1Password, export these in CSV to see exactly what I would have to produce and then produce an appropriate CSV for my data. That approach failed due to the round-tripping issues, and I had to find out exactly how to massage the CSV for the original data separately. No big deal, though (and I have already done it).
- However, while doing all this, I realized that having a round tripping feature would be great for bulk changing/editing of the data, regardless of its origin. If I have a vault with a homogeneous set of data without any particular datatypes (like my set of books) then a bulk edit of the data could be done much more easily by exporting it into a format that I can either massage in a good text editor, or come up with a simple Python/Node/Perl/whatever script to do so. With a dataset of over 1000 records this is much better than doing it by hand in 1Password.
I of course realize the flaws in using CSV for my use case #3; exporting into CSV may loose, eg, the datatype of a particular field, so it works on simple data only. Ideally, 1Password could give us a more sophisticated bulk editing tool (at least some find & replace on a selected set of records, possibly with regex), but it does not. Alternatively, a JSON based export/input format would be available, that could allow for the representation of a more sophisticated set of information. The 1pif format could be the basis for this, but we then fall back to the separate discussion on whether that format will ever be properly documented. I presume the ideal approach would be to have a tailor-made JSON format containing only the relevant information for round-tripping, and that could be imported/exported to/from 1Password. But that is a separate project I guess...
Thanks for your patience with all my rants:-)
Cheers
Ivan
0 -
Hi @iherman ,
Great reply, thanks for the clarification and full scope.
Sounds like #1 is done.
Regarding #2, let me suggest instead of 1Password, you use Microsoft OneNote. It is simply awesome, is free, and the data syncs across all the platforms and the destkop/mobile apps. All of my non-security related lists, notes, etc are here. I've had hundreds of topic-specific notes in plain-text files for years (because I work on many platforms) - they are now all in OneNote. It's a MUCH richer interface than 1Password will ever have in notes or Secure Notes. Using this obviates the need for your data round-tripping.
Regarding #3, my reply above essentially touches on that too. I think you're devising an overly complicated workflow just to use 1Password's very limited notes/Secure Notes. I'd abort this path in a heart-beat.
Agilebits has expressed interest in some automation APIs, but I think this will be limited, a long way off, and geared towards corporate Teams usage, not home users with 1Password.com accounts or standalone vaults. The primary issue here is that data inside of 1Password is regarded is secure, and building APIs that retain that secrecy, or devising schemes for import/export but not using the insecure filesystem, is very difficult.
Edit: if you need to customize the Formatters/csv.pm converter to replace the semicolon to a comma, I could make this easier for you. Let me know.
FYI: semicolon is often used as a field separator in CSV for non-English locales that use comma as a numbers digit separator! So commas and semicolons in CSV both can have issues.
0 -
MrC,
I have …
… downloaded your testing version convert_to_1p4_1.10
... downlaoded and installed perl
… ran portableshell.bat and install_modules.bat
… exported the data fromm Secure 3.5.5
.. ran „perl convert_to_1p4.pl msecure -v --lang de C:\Users\roquette\Desktop\mSecure_2017-07-28.csv“Unfortunately, this didn’t work, either. I get hundrests of error messages, probalby for each of my 310 datasets more than one:
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 1 (#1)
Renamed card type ' [note text];[username];[password] is not a default type, and is being mapped to Secure Notes
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 2 (#1)
Use of uninitialized value $msecure_type in exists at Converters/Msecure.pm line 242, <$io> line 2 (#1)
Use of uninitialized value $msecure_type in concatenation (.) or string at Converters/Msecure.pm line 246, <$io> line 2 (#1)
Renamed card type '' is not a default type, and is being mapped to Secure Notes
Use of uninitialized value $msecure_type in join or string at Converters/Msecure.pm line 248, <$io> line 2 (#1)
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 3 (#1)
Renamed card type ' [Text of a note]' is not a default type, and is being mapped to Secure Notes
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 4 (#1)
Use of uninitialized value $msecure_type in exists at Converters/Msecure.pm line 242, <$io> line 4 (#1)
Use of uninitialized value $msecure_type in concatenation (.) or string at Converters/Msecure.pm line 246, <$io> line 4 (#1)
Renamed card type '' is not a default type, and is being mapped to Secure Notes… and so forth.
0 -
First, sorry for your troubles.
Something seems unexpected with your export file. Perhaps your CSV export from mSecure has exported using semicolons instead of commas ? Or did you import into a spreadsheet program, and then re-export to CSV with a semicolon separator?
One of these appears to be the case, as your text data shows a value of "' [note text];[username];[password] ".
Not only is there a semicolon here as the separator, but those fields don't align to any stock mSecure Type, so it looks like you have customized fields too.
We can easily adjust the converter to use semicolon instead of comma by changing line (approximately) 190 in Converters\mSecure.pm:
sep_char => ',',
to
sep_char => ';',
Feel free to try that (use a simple plain-text editor), but I'm still wondering what caused the semicolons.
0 -
@MrC,
I have changed "sep_char => ','" to "sep_char => ';'" in Converters\mSecure.pm.
Then i
… ran portableshell.bat and install_modules.bat
… exported the data fromm Secure 3.5.5
.. ran „perl convert_to_1p4.pl msecure -v --lang de C:\Users\roquette\Desktop\mSecure_2017-07-28.csv“Again, gazillions of error messages.
For the first data set ("Geschäftlich;Web-Anmeldungen;1&1 Hompage;Unified Messaging Fax-Nummer: +4932121429197, geht an fax@rudolf-graf.de\n;https://www.1und1.de/login?;[user name];[password]):
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 1 (#1)
Renamed card type ' geht an fax@rudolf-graf.de\n;https://www.1und1.de/login?;[user name];[password]' is not a default type, and is being mapped to Secure NotesResult: {"uuid":"789E553D1673470D9129A6AC45CC7FB6","title":"Untitled","openContents":{"tags":["Geschäftlich;Web-Anmeldungen;1&1 Hompage;Unified Messaging Fax-Nummer: +4932121429197"]},"typeName":"securenotes.SecureNote","secureContents":{"notesPlain":"Typ: geht an fax@rudolf-graf.de\n;https://www.1und1.de/login?;[username];[password]"}}
5642bee8-a5ff-11dc-8314-0800200c9a66For the second data set ("Geschäftlich;Web-Anmeldungen;1&1 MyWebsite Better English;juliane@roquette.de;;[user name];[password]")
Use of uninitialized value $notes in string ne at Converters/Msecure.pm line 234, <$io> line 2 (#1)
Use of uninitialized value $msecure_type in exists at Converters/Msecure.pm line 242, <$io> line 2 (#1)
Use of uninitialized value $msecure_type in concatenation (.) or string at Converters/Msecure.pm line 246, <$io> line 2 (#1)
Renamed card type '' is not a default type, and is being mapped to Secure NotesResult: {"uuid":"EC1445F5B3D64C8A94BAE8623440D21C","title":"Untitled","openContents":{"tags":["Geschäftlich;Web-Anmeldungen;1&1 MyWebsite Better English;juliane@roquette.de;;[user name];password"]},"typeName":"securenotes.SecureNote","secureContents":{"notesPlain":"Typ: "}}
5642bee8-a5ff-11dc-8314-0800200c9a66Also, every other data set results in "Renamed card type '' is not a default type, and is being mapped to Secure Notes"
it looks like you have customized fields too
I did not change any stock mSecure type. There are only 4 custom type data sets
These are the types, I am using:
Web-Anmeldungen (login, 231)
Registrierungscodes (registration code, 22)
Bankkonten (Bank Accounts, 15)
E-Mail-Konten (email accounts, 15)
Kreditkarten (credit cards, 10)
Mitgliedschaften (memberships, 4)
Nicht zugeordnet (not assigned / custom, 4)
Telefon-Karten (telephone cards, 2)
Vielflieger (frequent flyer, 2)
Hinweis (Secure Note, 1)0 -
Hello again @TilRoquette
I'm a little baffled by the trouble you are experiencing. I need help in understanding some things.
- Did you EDIT your exported CSV file at all before trying to convert?
- Did you still have version 5 of mSecure installed?
- Are your language and region settings both configured as German/Deutsch?
The error you are getting implies that the column separator is still the comma, and not the semicolon, because there should ALWAYS be values detected for the first 4 columns in every row (the "notes" column being column 4), and the Type being detected is the string past the first comma until the end. This means a comma is still being used, and would mean you're not using the changed converter.
When I set my WIndows 10 x32 system to German/Deutsch, install mSecure 3.5.5, create 2 login entries, export them, and run the converter using the semicolon as the separator, I get a good conversion.
Note also that I've added a new option you can use, so you don't need to edit the Msecure.pm file to change the separator (see the
--sepchar
option in use below). Also, I've added some diagnostics to help detect issues with the CSV, so you should not see so many errors. The converter will abort when it cannot find at least the minimum number of required columns in the export. Please download and use the updated 1.10 version in Testing Bits.Data:
Geschäftlich;Web-Anmeldungen;1&1 Hompage;Unified Messaging Fax-Nummer: +4932121429197, geht an fax@rudolf-graf.de;"\\n;https://www.1und1.de/login?";username;supersecretpass Geschäftlich;Web-Anmeldungen;1&1 MyWebsite Better English;juliane@roquette.de;;myusername;mypassword
Conversion:
perl convert_to_1p4.pl msecure --lang de -v -d "C:\Users\MrC\Desktop\msExpDE.csv" --sepchar ";" main : Command Line: msecure --lang de -v -d C:\Users\MrC\Desktop\msExpDE.csv --sepchar ; main : Output file: C:\Users\MrC\Desktop\1P_import.1pif print_fileinfo : Export file info print_fileinfo : size: 276 do_import : ROW: 1 do_import : field: URL => \\n;https://www.1und1.de/login? do_import : field: Username => username do_import : field: Password => supersecretpass normalize_card_data : field: URL normalize_card_data : field: Username normalize_card_data : field: Password print_record : title: 1&1 Hompage tags: Geschäftlich key(password): Password = supersecretpass key(username): Username = username key(url): URL = \\n;https://www.1und1.de/login? notes: Unified Messaging Fax-Nummer: +4932121429197, geht an fax@rudolf-graf.de do_import : ROW: 2 do_import : field: URL => do_import : field: Username => myusername do_import : field: Password => mypassword normalize_card_data : field: Username normalize_card_data : field: Password print_record : title: 1&1 MyWebsite Better English tags: Geschäftlich key(password): Password = mypassword key(username): Username = myusername notes: juliane@roquette.de Imported 2 items create_pif_record : Title: 1&1 Hompage create_pif_record : key test(url): \\n;https://www.1und1.de/login? create_pif_record : key test(username): username create_pif_record : key test(password): supersecretpass create_pif_record : notes: Unified Messaging Fax-Nummer: +4932121429197, geht an fax@rudolf-graf.de create_pif_record : tags: Geschäftlich create_pif_record : Title: 1&1 MyWebsite Better English create_pif_record : key test(username): myusername create_pif_record : key test(password): mypassword create_pif_record : notes: juliane@roquette.de create_pif_record : tags: Geschäftlich Exported 2 login items Exported 2 total items You may now import the file C:\Users\MrC\Desktop\1P_import.1pif into 1Password
Let's see what you get when you try this conversion using the new converter.
0 -
Thanks for all your support. However, I have given up and have imported almost all the datasets manually yesterday.
Did you EDIT your exported CSV file at all before trying to convert?
No.
Did you still have version 5 of mSecure installed?
I have version 5 installed locally and versoin 3.5.x installed on the terminal server. I tested with the export from both.
Are your language and region settings both configured as German/Deutsch?
Yes. With Window's Regional Settings for Germany, the semicolon (;) becomes separator instead of a colon.
The error you are getting implies that the column separator still is not correctly being applied,
I guess the script stumples over colons within the note field.
When I set my WIndows 10 x32 system to German/Deutsch
I am using Windows 10 Professional x64. I do not think that this makes the difference.
0 -
@TilRoquette ,,
It's too bad we didn't get to discover the issue.
The converter doesn't care about colons in notes. Perhaps you meant semicolons. However, I used exactly the data you provided for me, and one note does contain a colon, and the conversion worked nontheless.
Please note mSecure has problematic CSV exports, and it could be that in this case, with semicolon as the field separator, mSecure is producing a faulty export. It clearly does not properly quote its field data. The converter tries to work around some of these issues, but it can perform magic with seriously faulty exports. I just wish i could reproduce the issue you see.
0 -
I'm sorry that I was running out of time. It was a bit time consuming to generate a CSV file my new password safe could read. But now I have 90% of alle data copied, the rest I will enter manually.
I opend mSecure CSV export (from 3.5.x as well as from 5.x) with a CSV and they looked fine to me.
0 -
I browsed through a few pages to see if this had been answered before but didn't find anything - apologies if this is a common question. I'm running into the following error when running the conversion:
Can't locate Utils/PIF.pm in @INC (you may need to install the Utils::PIF module) (@INC contains: C:/myperl/perl/site/lib C:/myperl/perl/vendor/lib C:/myperl/perl/lib) at C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl line 15.
BEGIN failed--compilation aborted at C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl line 15.0 -
Hi @goneawol ,
You probably downloaded Perl version 5.26. See the last note on the first post of the converter suite thread. Use version 5.24.
Also, which conversion are you going to do (from what password manager)?
0 -
@MrC Thanks for the quick response! I did download 5.26 - downloaded 5.24 and tried it again. Confirmed after running:
C:\WINDOWS\system32>c:\myperl\portableshell.bat
Welcome to Strawberry Perl Portable Edition!
* URL - http://www.strawberryperl.com/* see README.TXT for more info
Perl executable: c:\myperl\perl\bin\perl.exe
Perl version : 5.24.2 / MSWin32-x64-multi-threadThen ran install_modules.bat, which executed successfully.
Then ran:
C:\WINDOWS\system32>perl "C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl" lastpass -v "C:\users\alewollan\Desktop\pw.csv"
Can't locate Utils/PIF.pm in @INC (you may need to install the Utils::PIF module) (@INC contains: c:/myperl/perl/site/lib c:/myperl/perl/vendor/lib c:/myperl/perl/lib .) at C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl line 15.
BEGIN failed--compilation aborted at C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl line 15.0 -
This:
C:\WINDOWS\system32>perl "C:\Users\alewollan\Desktop\convert_to_1p4\convert_to_1p4.pl" lastpass -v "C:\users\alewollan\Desktop\pw.csv"
says you are in the wrong directory. In the command shell, you need to change directories to the convert_to_1p4 folder on your Desktop.
You're trying to execute the script by using a full path to it. Don't do that.
0 -
@MrC D'oh!
C:\Users\alewollan\Desktop\convert_to_1p4>perl convert_to_1p4.pl lastpass -v ../pw.csv
Imported 210 items
Exported 4 wireless items
Exported 6 note items
Exported 200 login items
Exported 210 total items
You may now import the file C:\Users\alewollan\Desktop\1P_import.1pif into 1PasswordGot it. Thanks again for the quick response.
0 -
I'm trying to import my logins from Keychain on the Mac. Right now I have 2 txt files on my desktop, keychain.txt and pm_export.txt. At this point I went into Keychain and created a local.iCloud Keychain and attempted to copy and past into the new Keychain. I keep getting an error "An error has occurred. Unable to add an item to the current keychain." I can't figure out what I'm doing wrong. Thanks for any help.
0