save_bookmark (Raggle::Interfaces::NcursesInterface)

    # File raggle, line 3961
          def NcursesInterface::save_bookmark

            # grab bookmark settings
            bm = $config['bookmark']
            return unless bm && bm.kind_of?(Array)

            # was the bookmark saved?
            was_saved = true

            # get feed categories
            item = $config['feeds'].get($a_feed)
            feed_cats = ' ' << (item['category'] || '')

            # get actual item
            desc_win = $wins[NcursesInterface::get_win_id('desc')]
            item = desc_win.items[desc_win.active_item]

            # get item information
            return unless item && item['title'] && (item['url'] || item['site'])
            title = item['title']
            time = Time.now.xmlschema
            url = item['site'] || item['url']

            NcursesInterface::set_status($config['msg_bm_saving'] % [title])

            # check to see if we need to get extended information
            get_ext = bm.any? { |bmb| !bmb[:no_desc] }
            get_tag = bm.any? { |bmb| !bmb[:no_tags] }

            ext, user_tags = '', ''
            ext = NcursesInterface::get_input('bm_desc') if get_ext
            user_tags = NcursesInterface::get_input('bm_tag') if get_tag

            # iterate over bookmark backends and save bookmark to each one
            bm.each do |bmb|
              # get tags, add feed categories (unless disabled)
              tags = user_tags
              unless bmb.key?(:inherit_tags) && bmb[:inherit_tags] == false
                tags += feed_cats
              end

              case bmb[:type]
              when :csv_file
                # expand bookmark file path
                path = Engine::expand_str(bmb[:path])

                # save title and bookmark to file
                begin
                  # create CSV line from title, time, and URL
                  csv_line = [title, url, time, ext, tags].map { |str|
                    '"' << str.gsub(/"/, '""') << '"'
                  }.join(',')

                  # if the CSV doesn't exist, then prepend the columns
                  unless File::exists?(path)
                    csv_line = "title,url,time,description,tags\n" << csv_line
                  end

                  # append to CSV file
                  File::open(path, 'a') { |file| file.puts(csv_line) }
                rescue Exception => err
                  # couldn't write to bookmark file, set status
                  was_saved = false
                  status = $config['msg_bm_file_err'] % [path, err.to_s]
                  NcursesInterface::set_status(status)
                end
              when :exec
                fork {
                  system(bmb[:path], title, url, tags, ext)
                }
              when :db
                # build query
                cols, args = [], []
                { :title  => title,
                  :url    => url,
                  :tags   => tags,
                  :desc   => ext,
                }.each_pair do |col_key, val|
                  if bmb[:fields][col_key]
                    cols << bmb[:fields][col_key]
                    args << val
                  end
                end

                begin
                  db, quote_meth = nil, nil

                  # database-specific connection stuff
                  case bmb[:dbtype]
                  when :mysql
                    unless $HAVE_LIB['mysql']
                      raise $config['msg_bm_db_missing'] % 'Mysql'
                    end

                    # connect to database, set quote method
                    db = Mysql::connect(bmb[:host], bmb[:user], bmb[:pass])
                    db.select_db(bmb[:dbname])
                    quote_meth = Mysql::method(:escape_string)
                  when :sqlite
                    unless $HAVE_LIB['sqlite']
                      raise $config['msg_bm_db_missing'] % 'SQLite'
                    end

                    # connect to database, set quote method
                    path = Engine::expand_str(bmb[:path])
                    db = SQLite::Database.new(path)
                    quote_meth = SQLite::Database.method(:quote)
                  else
                    # unknown database type
                    raise $config['msg_bm_bad_db_type']
                  end

                  # build query
                  query = "INSERT INTO #{bmb[:table]}(#{cols.join(',')})
                           VALUES " << '(' << args.map { |arg|
                    "'" << quote_meth.call(arg) << "'"
                  }.join(',') << ')'

                  # execute query
                  db.query(query)
                rescue Exception => err
                  was_saved = false
                  status = $config['msg_bm_db_err'] % [err.to_s]
                  NcursesInterface::set_status(status)
                end
              else
                # bad bookmark type
                was_saved = false
                status = $config['msg_bm_bad_type'] % [bmb[:type].to_s]
                NcursesInterface::set_status(status)
              end

              # set status indicating success
              status = $config['msg_bm_saved'] % [title]
              NcursesInterface::set_status(status) if was_saved
            end
          end