7 Replies Latest reply on Dec 12, 2011 10:16 PM by areohbee

    how to set string (user/pass) to file or other way in exporter plugin?

    meir242

      Hi (im begginer )

      im building exporter plugin , and need to sighin to web site to whom i export the photos,

      from within the plugin i need to set my user/pass and then save it somewhere in text file mybe

      so the user will not set the user/password all the time . my question is .

      do i need to save it to text file ?

      or the object LrPrefs will do it for me ?

      this is untill the user remove the plugin .

      Thanks

        • 1. Re: how to set string (user/pass) to file or other way in exporter plugin?
          areohbee Level 5

          Consider using LrPassword.

          1 person found this helpful
          • 3. Re: how to set string (user/pass) to file or other way in exporter plugin?
            areohbee Level 5

            Still figuring out how to use that Android?

            • 4. Re: how to set string (user/pass) to file or other way in exporter plugin?
              DawMatt Level 3

              Sigh.

               

              Let's try that again. Seems Jive doesn't like selectively quoted replies sent via email, or allowing me to edit the emailed reply via the web interface. Editing must be possible though because Rob's colloquialism is no longer in this thread.

               

              On Tue, Dec 13, 2011 at 11:57 AM, Rob Cole <forums@adobe.com> wrote:

              Consider using LrPassword.


              To finish the suggestion...

               

              Consider using LrPassword to ensure the password is stored in a safe manner that won't make it too easy for others to discover your user's password. Keep in mind that contrary to the API Reference doco this namespace was added in LR3 so your plugin wouldn't be usable in LR2 if you use the namespace, in case you were planning to make it backwards compatible (probably not worth the effort now).

               

              LrPrefs is probably the best bet for storing the username associated with the service.

              Matt

              • 5. Re: how to set string (user/pass) to file or other way in exporter plugin?
                areohbee Level 5

                An idea:

                 

                When specifying a password view, allow the binding object to be for encrypted password storage, instead of property table, in which case passwords are auto-linked to encrypted storage - no additional effort required...

                 

                Then one could get rid of the "password stored with preset in plain text" warning in the ftp settings dialog too .

                 

                Rob

                • 6. Re: how to set string (user/pass) to file or other way in exporter plugin?
                  meir242 Level 1

                  Hi and thanks for the replay's

                  so to use LrPassword for the password and LrPrefs for the user name ?

                  and then i just check if the user Authnticated ? in some boolean value in the LrPrefs?

                  how does this flow goes in LIghtroom ?

                  • 7. Re: how to set string (user/pass) to file or other way in exporter plugin?
                    areohbee Level 5

                    There is no limit to what strings can be stored via LrPassword.

                     

                    I store username in lr-prefs, and password in lr-password storage, key'd with "protocol_server_username".

                     

                    Then, use "password_field" for editing.

                     

                    i.e. there should be only one password for a given server/user/protocol. and it should be reusable, like a preset.

                     

                    Code example:

                    --- Serves same purpose as Lr-FTP version - prompt user for password if not provided in the settings.
                    --  

                    --      Motivation:     Lightroom's version just says "gimme a password" without stating what the password is for. --                      This is one of my all time pet peeves in modern software - I suppose if you are the kind --                      of person that uses the same password for everything and dont care what its for when you --                      are asked for one, it doesn't much matter - I am not that kind of person. -- --                      Its completely unacceptable for Photooey since passwords may be needed for two different servers. -- 

                    -- --  @param      ftpSettings (table, required) can be user-created lua table (as long as required members are present),
                    --                          or that created by binding to make-ftp-preset-popup. -- --  @usage This function indicates the password request is for ftp user on specified server. --  @usage Use in conjunction with view--observe-Ftp-Property-Changes, since it will set up the encrypted password store. -- --  @return     ok (boolean) true iff valid password entered. -- function Ftp:queryForPasswordIfNeeded( ftpSettings )     local s, m = pcall( function()         if ftpSettings == nil then             assert( self ~= nil, "no ftp settings" )             assert( self.server ~= nil, "bad ftp settings" )             return self         else             return ftpSettings         end     end )     if s then         ftpSettings = m     else         app:error( "unable to obtain ftp settings" )     end     local password     local name = str:fmt( "^1_^2_ftp", ftpSettings.server, ftpSettings.username ) -- server, user, protocol-type.     local unencrypted = LrPasswords.retrieve( name )     local plain = ftpSettings.password         if str:is( plain ) and not str:is( unencrypted ) then         password = plain         app:logVerbose( "Accepting plain password, since encrypted store has no entry for server-username combo." )     elseif str:is( unencrypted ) and not str:is( plain ) then         password = unencrypted         app:logVerbose( "Accepting encrypted password for server-username combo." )     elseif str:is( plain ) and str:is( unencrypted ) then -- both         if plain == unencrypted then             app:logVerbose( "Encrypted password same as password stored in plain text." )             password = unencrypted         else             app:logWarning( "Ambiguous password entries: encrypted password and another from preset stored in plain text - warrants a prompt... - to remedy, I suggest blankening the plain text password, once the encrypted password is correct." )         end     else -- neither         app:logVerbose( "No password stored for server-username combo - prompting..." )     end         if str:is( password ) then         ftpSettings.password = password         return true     end     local ok     LrFunctionContext.callWithContext( "queryForPasswordIfNeeded", function( context )         local props = LrBinding.makePropertyTable( context )         props.password = ''         props.encrypt = true         local c = { vf:column {                spacing = vf:dialog_spacing(),             vf:row {                 vf:static_text {                        title = str:fmt( "Server: ^1", ftpSettings.server ),                 },             },             vf:row {                 vf:static_text {                        alignment = "left",                        title = "FTP Password: ",                 },                 vf:password_field {                     bind_to_object = props,                     immediate = true, -- ###3 - probably required for password to take without tabbing out on Mac(?)                     value = bind 'password',                     width_in_chars = 15,                 },             },             vf:spacer{ height = 1 },             vf:column {                 spacing = vf:label_spacing(),                 vf:checkbox {                     bind_to_object = props,                     title = 'Store encrypted for future - you will have to',                     tooltip = 'Encryption mechanism depends on operating system, and is recommended...',                     value = bind 'encrypt',                 },                 vf:static_text {                     title = "use the Publishing Manager to change."                 },             },         }}                 repeat             local answer = app:show{ confirm="Enter password for user ^1",                 subs = ftpSettings.username,                 viewItems = c,                 -- additional acc-items not supported.                 buttons = { dia:btn( "OK", 'ok' ) },             }             if answer == 'ok' then                 if str:is( props.password ) then                     if props.encrypt then                         LrPasswords.store( name, props.password )                     else                         LrPasswords.store( name, "" ) -- maybe should store 'nil'? ###1                     end                     ftpSettings.password = props.password                     ok = true                     break                 else                     app:show{ warning="Password can not be blank." }                 end             else                 ok =  false                 break             end         until false                 end )         return ok     end --- Observe ftp setting property changes. -- --  @param object (table, required) must include 'observeFtpPropertyChanges' table with a named member set to boolean 'true' for each property to be observed. --  @param props (property-table, required) ftp-settings. --  @param ftpSettingsName (string, required) name of ftp-settings property. --  @param checkSetting (function( ftpProps, name, prev, value ), optional) can be used to check the values being set, and return true for 'OK' or false and a warning message if not. -- --  @usage Call when starting dialog box containing ftp settings. --  @usage This function was designed to be used in conjunction with
                    --         the framework object's version of ftp-query-for-password-if-needed, since it will look
                    --         in the encrypted store for the password saved by this function. -- function View:observeFtpPropertyChanges( object, props, ftpSettingsName, checkSetting )     app:call( Call:new{ name="handle password storage", async=true, guard=App.guardSilent, main=function( call )    --[[ Typical FTP Settings:     path = "/testfolder",     protocol = "ftp",     storePassword = true,     password = "dsf",     passive = "normal",     title = "Untitled FTP",     username = "fb159e0f",     port = 21,     server = "ftp.imemine.com"} --]]            assert( object.observeFtpPropertyChanges ~= nil, "no property specs" )         assert( type( object.observeFtpPropertyChanges ) == 'table', "property specs should be table" )         assert( props[ftpSettingsName] ~= nil, "no ftp settings in props" )         assert( props[ftpSettingsName].server ~= nil, "no server specified in ftp settings" )         assert( props[ftpSettingsName].username ~= nil, "username must be specified in ftp settings." )         assert( props[ftpSettingsName].storePassword ~= nil, "bad props for password storage" )                 local saved = tab:copy( props[ftpSettingsName] ) -- make a shallow copy of ftp properties.                 -- note password property is cleared when first editing via popup.         repeat             if object.observeFtpPropertyChanges['path'] ~= nil then break end             if object.observeFtpPropertyChanges['protocol'] ~= nil then break end             if object.observeFtpPropertyChanges['storePassword'] ~= nil then break end             if object.observeFtpPropertyChanges['password'] ~= nil then break end             if object.observeFtpPropertyChanges['passive'] ~= nil then break end             if object.observeFtpPropertyChanges['title'] ~= nil then break end             if object.observeFtpPropertyChanges['username'] ~= nil then break end             if object.observeFtpPropertyChanges['port'] ~= nil then break end             if object.observeFtpPropertyChanges['server'] ~= nil then break end             app:callingError( "No ftp properties to observe" )         until true         if checkSetting == nil then             checkSetting = function( ftpProps, name, prev, value )                 return true -- , value - second return obsolete.             end         end                 local function processChange( name, prevValue, newValue )                     local sts, msg = checkSetting( props[ftpSettingsName], name, prevValue, newValue )             if sts then                 -- setting approved.             else                 -- props[ftpSettingsName] = prevValue - this does not do any good, since its after the fact -                     -- lightroom zeros everything out upon entry, then re-populates upon 'OK' button, at which time,                     -- the ftp properties are locked in.                 if str:is( msg ) then                     app:show{ warning=msg }                 -- else ignore setting change without complaint.                 end                 return             end             if name == 'password' then                            local pswd = newValue -- convenience var                 -- Note: unlike the other properties, password property is cleared when ftp settings dialog box is opened, and                 -- then set when user closes the form.                 if prevValue ~= nil and pswd == nil then                     return                 end                 if pswd == nil then                     pswd = ""                 end                                 local chars = pswd:len()                 local charsUi                 if app:isVerbose() then                     charsUi = str:fmt( " (^1 character) ", chars )                 else                     charsUi = " "                 end                 local key = str:fmt( "^1_^2_ftp", props[ftpSettingsName].server, props[ftpSettingsName].username ) -- update for sftp support. ###3 must match ftp module.                 local unc = LrPasswords.retrieve( key )                 if unc ~= pswd then                     local answer                     if chars > 0 then                         if str:is( unc ) then                             answer = app:show{ info="Overwrite password in encrypted store with newly entered^3value (for future ftp to '^1' as '^2')? It is recommended to do so, instead of saving a preset with ftp password in plain text.",                                 subs = { props[ftpSettingsName].server, props[ftpSettingsName].username, charsUi },                                 buttons = { dia:btn( "Yes - use encrypted store", 'ok' ), dia:btn( "No - use preset instead", 'other', false ), }, --  dia:btn( "No", 'cancel' ) },                                 actionPrefKey = "Save password in encrypted store",                             }                         elseif props[ftpSettingsName].storePassword then                             answer = 'ok' -- taking the liberty here - if never been stored in encrypted store, and user is entering a password and is presently willing to store unencrypted...                         else                             answer = app:show{ info="Save^3password in encrypted store (for future ftp to '^1' as '^2')? It is recommended to do so, instead of saving a preset with ftp password in plain text.",                                 subs = { props[ftpSettingsName].server, props[ftpSettingsName].username, charsUi },                                 buttons = { dia:btn( "Yes", 'ok' ), dia:btn( "No", 'cancel', false ) },                                 actionPrefKey = "Save password in encrypted store",                             }                         end                     else                         if str:is( unc ) then                             local ans = app:show{ info="Clear encrypted password too? - not recommended, unless it is your intention to eliminate all password storage and enter the password each time.",                                 buttons = { dia:btn( "Yes", 'ok' ), dia:btn( "No", 'cancel', false ) },                                 actionPrefKey = "Clear blankened password in encrypted store",                             }                             if ans == 'ok' then                                 answer = 'other'                             else                                 app:logVerbose( "User elected not to clear blankened password in encrypted store." )                                 return                             end                         else                             app:logVerbose( "Don't trip - user will be prompted for password on demand and have option to save encrypted or not." )                             app:show{ info="No passwords will be stored - you will be prompted each time.",                                 actionPrefKey = "No password stored - prompt instead",                             }                             return                         end                     end                     if answer == 'ok' then                         assert( pswd:len() > 0, "unexpected blank password" )                         LrPasswords.store( key, pswd )                         assert( LrPasswords.retrieve( key ) == pswd, "no crypt upd" ) -- will not work if pswd is nil.                         app:logVerbose( "Entered password saved in encrypted storage." )                         app:show{ info="Entered password^1has been saved in encrypted storage. If password has already been saved as plain text in a preset, now would be a good time to go blanken it (or uncheck 'Store password in preset') and then update the preset.",                             subs = charsUi,                             actionPrefKey = "Entered password saved in encrypted storage",                         }                     elseif answer == 'other' then                         LrPasswords.store( key, "" )                         assert( not str:is( LrPasswords.retrieve( key ) ), "no crypt clr" )                         app:logVerbose( "Password that was in encrypted storage has been removed." )                         app:show{ info="Password that was in encrypted storage has been removed.",                             actionPrefKey = "Password that was in encrypted storage has been removed",                         }                     elseif answer == 'cancel' then                         app:logVerbose( "User elected not to store password in encrypted store." )                     else                         app:error( "bad answer" )                     end                                        else                     app:logVerbose( "Password is already in encrypted store." ) -- ###1                 end                end -- password                         -- protocol is handled via check function.                     end                 while not shutdown and object.observeFtpPropertyChanges do             LrTasks.sleep( .1 ) -- its possible (has happened) that watcher gets cleared while sleeping                         if object.observeFtpPropertyChanges ~= nil then                 for k, v in pairs( object.observeFtpPropertyChanges ) do                     local newValue = props[ftpSettingsName][k]                     if newValue ~= saved[k] then                         processChange( k, saved[k], newValue )                         saved[k] = newValue                     end                 end             end                     end -- while             end, finale=function( call, status, message )         if not status then             app:show{ error=message }         end     end } ) end

                    --- Discontinue observation of ftp setting changes.

                    --

                    --  @usage This must be called when dialog box is ended.

                    --

                    function View:unobserveFtpPropertyChanges( object )

                        object.observeFtpPropertyChanges = nil

                    end

                     

                     

                    1 person found this helpful