def wrapper(cls, **kwargs): try: filename = kwargs['filename'] except KeyError: filename = cls.filename res = func(cls, **kwargs) file_mode_checker(filename, mode=0o600) return res
def save_botpasswords(botpasswords, _fncpass): """Write botpasswords to file.""" if botpasswords: # Save user-password.py if necessary # user-config.py is already created at this point # therefore pywikibot.tools can be imported safely from pywikibot.tools import file_mode_checker try: # First create an empty file with good permissions, before writing # in it with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write('') file_mode_checker(_fncpass, mode=0o600, quiet=True) with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write(PASSFILE_CONFIG.format(botpasswords=botpasswords)) file_mode_checker(_fncpass, mode=0o600) pywikibot.output("'{0}' written.".format(_fncpass)) except EnvironmentError: os.remove(_fncpass) raise
def readPassword(self): """ Read passwords from a file. DO NOT FORGET TO REMOVE READ ACCESS FOR OTHER USERS!!! Use chmod 600 password-file. All lines below should be valid Python tuples in the form (code, family, username, password), (family, username, password) or (username, password) to set a default password for an username. The last matching entry will be used, so default usernames should occur above specific usernames. For BotPasswords the password should be given as a BotPassword object. The file must be either encoded in ASCII or UTF-8. Example:: ('my_username', 'my_default_password') ('my_sysop_user', 'my_sysop_password') ('wikipedia', 'my_wikipedia_user', 'my_wikipedia_pass') ('en', 'wikipedia', 'my_en_wikipedia_user', 'my_en_wikipedia_pass') ('my_username', BotPassword( 'my_BotPassword_suffix', 'my_BotPassword_password')) """ # Set path to password file relative to the user_config # but fall back on absolute path for backwards compatibility password_file = os.path.join(config.base_dir, config.password_file) if not os.path.isfile(password_file): password_file = config.password_file # We fix password file permission first. file_mode_checker(password_file, mode=config.private_files_permission) with codecs.open(password_file, encoding='utf-8') as f: lines = f.readlines() line_nr = len(lines) + 1 for line in reversed(lines): line_nr -= 1 if not line.strip() or line.startswith('#'): continue try: entry = eval(line) except SyntaxError: entry = None if type(entry) is not tuple: warn('Invalid tuple in line {0}'.format(line_nr), _PasswordFileWarning) continue if not 2 <= len(entry) <= 4: warn( 'The length of tuple in line {0} should be 2 to 4 ({1} ' 'given)'.format(line_nr, entry), _PasswordFileWarning) continue code, family, username, password = ( self.site.code, self.site.family.name)[:4 - len(entry)] + entry if (normalize_username(username) == self.username and family == self.site.family.name and code == self.site.code): if isinstance(password, UnicodeType): self.password = password break elif isinstance(password, BotPassword): self.password = password.password self.login_name = password.login_name(self.username) break else: warn('Invalid password format', _PasswordFileWarning)
def test_auto_chmod_not_OK(self): """Chmod files that do not have mode private_files_permission.""" self.stat.return_value.st_mode = 0o100644 # regular file tools.file_mode_checker(self.file, mode=0o600) self.stat.assert_called_with(self.file) self.chmod.assert_called_once_with(self.file, 0o600)
def test_auto_chmod_OK(self): """Do not chmod files that have mode private_files_permission.""" self.stat.return_value.st_mode = 0o100600 # regular file tools.file_mode_checker(self.file, mode=0o600) self.stat.assert_called_with(self.file) self.assertFalse(self.chmod.called)
"""Initialize the class.""" super(PywikibotCookieJar, self).__init__(*args, **kwargs) @mode_check_decorator def load(self, **kwargs): """Load cookies from file.""" super(PywikibotCookieJar, self).load() @mode_check_decorator def save(self, **kwargs): """Save cookies to file.""" super(PywikibotCookieJar, self).save() cookie_file_path = config.datafilepath('pywikibot.lwp') file_mode_checker(cookie_file_path, create=True) cookie_jar = cookielib.LWPCookieJar(cookie_file_path) try: cookie_jar.load() except cookielib.LoadError: debug('Loading cookies failed.', _logger) else: debug('Loaded cookies from file.', _logger) session = requests.Session() session.cookies = cookie_jar # Prepare flush on quit def _flush(): log('Closing network session.')
def create_user_config(main_family, main_code, main_username, force=False): """ Create a user-config.py in base_dir. Create a user-password.py if necessary. """ _fnc = os.path.join(base_dir, USER_BASENAME) _fncpass = os.path.join(base_dir, PASS_BASENAME) useritem = namedtuple('useritem', 'family, code, name') userlist = [] if force and not config.verbose_output: if main_username: userlist = [useritem(main_family, main_code, main_username)] else: while True: userlist += [ useritem(*get_site_and_lang( main_family, main_code, main_username, force=force)) ] if not pywikibot.input_yn('Do you want to add any other projects?', force=force, default=False, automatic_quit=False): break # For each different username entered, ask if user wants to save a # BotPassword (username, BotPassword name, BotPassword pass) msg = fill('See {}/BotPasswords to know how to get codes.' 'Please note that plain text in {} and anyone with read ' 'access to that directory will be able read the file.'.format( __url__, _fncpass)) botpasswords = [] userset = {user.name for user in userlist} for username in userset: if pywikibot.input_yn( 'Do you want to add a BotPassword for {}?'.format(username), force=force, default=False): if msg: pywikibot.output(msg) msg = None message = 'BotPassword\'s "bot name" for {}'.format(username) botpasswordname = pywikibot.input(message, force=force) message = 'BotPassword\'s "password" for "{}" ' \ '(no characters will be shown)' \ .format(botpasswordname) botpasswordpass = pywikibot.input(message, force=force, password=True) if botpasswordname and botpasswordpass: botpasswords.append( (username, botpasswordname, botpasswordpass)) if not userlist: # Show a sample usernames = "# usernames['{}']['{}'] = u'MyUsername'".format( main_family, main_code) else: usernames = '\n'.join( "usernames['{user.family}']['{user.code}'] = u'{user.name}'". format(user=user) for user in userlist) # Arbitrarily use the first key as default settings main_family, main_code = userlist[0].family, userlist[0].code botpasswords = '\n'.join( "('{0}', BotPassword('{1}', '{2}'))".format(*botpassword) for botpassword in botpasswords) config_text = copy_sections() if config_text: config_content = EXTENDED_CONFIG else: pywikibot.output('Creating a small variant of user-config.py') config_content = SMALL_CONFIG try: # Finally save user-config.py with codecs.open(_fnc, 'w', 'utf-8') as f: f.write( config_content.format(main_family=main_family, main_code=main_code, usernames=usernames, config_text=config_text, botpasswords='password_file = ' + ('"{}"'.format(PASS_BASENAME) if botpasswords else 'None'))) pywikibot.output("'%s' written." % _fnc) except BaseException: if os.path.exists(_fnc): os.remove(_fnc) raise if botpasswords: # Save user-password.py if necessary # user-config.py is already created at this point # therefore pywikibot.tools can be imported safely from pywikibot.tools import file_mode_checker try: # First create an empty file with good permissions, before writing # in it with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write('') file_mode_checker(_fncpass, mode=0o600, quiet=True) with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write(PASSFILE_CONFIG.format(botpasswords=botpasswords)) file_mode_checker(_fncpass, mode=0o600) pywikibot.output("'{0}' written.".format(_fncpass)) except EnvironmentError: os.remove(_fncpass) raise
def create_user_config(main_family, main_code, main_username, force=False): """ Create a user-config.py in base_dir. Create a user-password.py if necessary. """ _fnc = os.path.join(base_dir, USER_BASENAME) _fncpass = os.path.join(base_dir, PASS_BASENAME) useritem = namedtuple('useritem', 'family, code, name') userlist = [] if force and not config.verbose_output: if main_username: userlist = [useritem(main_family, main_code, main_username)] else: while True: userlist += [useritem(*get_site_and_lang( main_family, main_code, main_username, force=force))] if not pywikibot.input_yn('Do you want to add any other projects?', force=force, default=False, automatic_quit=False): break # For each different username entered, ask if user wants to save a # BotPassword (username, BotPassword name, BotPassword pass) msg = fill('See {}/BotPasswords to know how to get codes.' 'Please note that plain text in {} and anyone with read ' 'access to that directory will be able read the file.' .format(__url__, _fncpass)) botpasswords = [] userset = {user.name for user in userlist} for username in userset: if pywikibot.input_yn('Do you want to add a BotPassword for {}?' .format(username), force=force, default=False): if msg: pywikibot.output(msg) msg = None message = 'BotPassword\'s "bot name" for {}'.format(username) botpasswordname = pywikibot.input(message, force=force) message = 'BotPassword\'s "password" for "{}" ' \ '(no characters will be shown)' \ .format(botpasswordname) botpasswordpass = pywikibot.input(message, force=force, password=True) if botpasswordname and botpasswordpass: botpasswords.append((username, botpasswordname, botpasswordpass)) if not userlist: # Show a sample usernames = "# usernames['{}']['{}'] = u'MyUsername'".format( main_family, main_code) else: usernames = '\n'.join( "usernames['{user.family}']['{user.code}'] = u'{user.name}'" .format(user=user) for user in userlist) # Arbitrarily use the first key as default settings main_family, main_code = userlist[0].family, userlist[0].code botpasswords = '\n'.join( "('{0}', BotPassword('{1}', '{2}'))".format(*botpassword) for botpassword in botpasswords) config_text = copy_sections() if config_text: config_content = EXTENDED_CONFIG else: pywikibot.output('Creating a small variant of user-config.py') config_content = SMALL_CONFIG try: # Finally save user-config.py with codecs.open(_fnc, 'w', 'utf-8') as f: f.write(config_content.format( main_family=main_family, main_code=main_code, usernames=usernames, config_text=config_text, botpasswords='password_file = ' + ('"{}"'.format(PASS_BASENAME) if botpasswords else 'None'))) pywikibot.output("'%s' written." % _fnc) except BaseException: if os.path.exists(_fnc): os.remove(_fnc) raise if botpasswords: # Save user-password.py if necessary # user-config.py is already created at this point # therefore pywikibot.tools can be imported safely from pywikibot.tools import file_mode_checker try: # First create an empty file with good permissions, before writing # in it with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write('') file_mode_checker(_fncpass, mode=0o600, quiet=True) with codecs.open(_fncpass, 'w', 'utf-8') as f: f.write(PASSFILE_CONFIG.format(botpasswords=botpasswords)) file_mode_checker(_fncpass, mode=0o600) pywikibot.output("'{0}' written.".format(_fncpass)) except EnvironmentError: os.remove(_fncpass) raise
def readPassword(self): """ Read passwords from a file. DO NOT FORGET TO REMOVE READ ACCESS FOR OTHER USERS!!! Use chmod 600 password-file. All lines below should be valid Python tuples in the form (code, family, username, password), (family, username, password) or (username, password) to set a default password for an username. The last matching entry will be used, so default usernames should occur above specific usernames. For BotPasswords the password should be given as a BotPassword object. The file must be either encoded in ASCII or UTF-8. Example:: ('my_username', 'my_default_password') ('my_sysop_user', 'my_sysop_password') ('wikipedia', 'my_wikipedia_user', 'my_wikipedia_pass') ('en', 'wikipedia', 'my_en_wikipedia_user', 'my_en_wikipedia_pass') ('my_username', BotPassword( 'my_BotPassword_suffix', 'my_BotPassword_password')) """ # Set path to password file relative to the user_config # but fall back on absolute path for backwards compatibility password_file = os.path.join(config.base_dir, config.password_file) if not os.path.isfile(password_file): password_file = config.password_file # We fix password file permission first. file_mode_checker(password_file, mode=config.private_files_permission) with codecs.open(password_file, encoding='utf-8') as f: lines = f.readlines() line_nr = len(lines) + 1 for line in reversed(lines): line_nr -= 1 if not line.strip() or line.startswith('#'): continue try: entry = eval(line) except SyntaxError: entry = None if type(entry) is not tuple: warn('Invalid tuple in line {0}'.format(line_nr), _PasswordFileWarning) continue if not 2 <= len(entry) <= 4: warn('The length of tuple in line {0} should be 2 to 4 ({1} ' 'given)'.format(line_nr, entry), _PasswordFileWarning) continue code, family, username, password = ( self.site.code, self.site.family.name)[:4 - len(entry)] + entry if (normalize_username(username) == self.username and family == self.site.family.name and code == self.site.code): if isinstance(password, UnicodeType): self.password = password break elif isinstance(password, BotPassword): self.password = password.password self.login_name = password.login_name(self.username) break else: warn('Invalid password format', _PasswordFileWarning)
def readPassword(self): """ Read passwords from a file. DO NOT FORGET TO REMOVE READ ACCESS FOR OTHER USERS!!! Use chmod 600 password-file. All lines below should be valid Python tuples in the form (code, family, username, password), (family, username, password) or (username, password) to set a default password for an username. The last matching entry will be used, so default usernames should occur above specific usernames. For BotPasswords the password should be given as a BotPassword object. The file must be either encoded in ASCII or UTF-8. Example: (u"my_username", u"my_default_password") (u"my_sysop_user", u"my_sysop_password") (u"wikipedia", u"my_wikipedia_user", u"my_wikipedia_pass") (u"en", u"wikipedia", u"my_en_wikipedia_user", u"my_en_wikipedia_pass") (u"my_username", BotPassword(u"my_BotPassword_suffix", u"my_BotPassword_password")) """ # Set path to password file relative to the user_config # but fall back on absolute path for backwards compatibility password_file = os.path.join(config.base_dir, config.password_file) if not os.path.isfile(password_file): password_file = config.password_file # We fix password file permission first. file_mode_checker(password_file, mode=config.private_files_permission) password_f = codecs.open(password_file, encoding='utf-8') for line_nr, line in enumerate(password_f): if not line.strip(): continue try: entry = eval(line) except SyntaxError: entry = None if type(entry) is not tuple: warn('Invalid tuple in line {0}'.format(line_nr), _PasswordFileWarning) continue if not 2 <= len(entry) <= 4: warn( 'The length of tuple in line {0} should be 2 to 4 ({1} ' 'given)'.format(line_nr, entry), _PasswordFileWarning) continue # When the tuple is inverted the default family and code can be # easily appended which makes the next condition easier as it does # not need to know if it's using the default value or not. entry = list(entry[::-1]) + [ self.site.family.name, self.site.code ][len(entry) - 2:] if (normalize_username(entry[1]) == self.username and entry[2] == self.site.family.name and entry[3] == self.site.code): if isinstance(entry[0], basestring): self.password = entry[0] elif isinstance(entry[0], BotPassword): self.password = entry[0].password self.login_name = entry[0].login_name(self.username) else: warn('Invalid password format', _PasswordFileWarning) password_f.close()
def readPassword(self): """ Read passwords from a file. DO NOT FORGET TO REMOVE READ ACCESS FOR OTHER USERS!!! Use chmod 600 password-file. All lines below should be valid Python tuples in the form (code, family, username, password), (family, username, password) or (username, password) to set a default password for an username. The last matching entry will be used, so default usernames should occur above specific usernames. For BotPasswords the password should be given as a BotPassword object. The file must be either encoded in ASCII or UTF-8. Example: (u"my_username", u"my_default_password") (u"my_sysop_user", u"my_sysop_password") (u"wikipedia", u"my_wikipedia_user", u"my_wikipedia_pass") (u"en", u"wikipedia", u"my_en_wikipedia_user", u"my_en_wikipedia_pass") (u"my_username", BotPassword(u"my_BotPassword_suffix", u"my_BotPassword_password")) """ # Set path to password file relative to the user_config # but fall back on absolute path for backwards compatibility password_file = os.path.join(config.base_dir, config.password_file) if not os.path.isfile(password_file): password_file = config.password_file # We fix password file permission first. file_mode_checker(password_file, mode=config.private_files_permission) password_f = codecs.open(password_file, encoding='utf-8') for line_nr, line in enumerate(password_f): if not line.strip(): continue try: entry = eval(line) except SyntaxError: entry = None if type(entry) is not tuple: warn('Invalid tuple in line {0}'.format(line_nr), _PasswordFileWarning) continue if not 2 <= len(entry) <= 4: warn('The length of tuple in line {0} should be 2 to 4 ({1} ' 'given)'.format(line_nr, entry), _PasswordFileWarning) continue # When the tuple is inverted the default family and code can be # easily appended which makes the next condition easier as it does # not need to know if it's using the default value or not. entry = list(entry[::-1]) + [self.site.family.name, self.site.code][len(entry) - 2:] if (normalize_username(entry[1]) == self.username and entry[2] == self.site.family.name and entry[3] == self.site.code): if isinstance(entry[0], basestring): self.password = entry[0] elif isinstance(entry[0], BotPassword): self.password = entry[0].password self.login_name = entry[0].login_name(self.username) else: warn('Invalid password format', _PasswordFileWarning) password_f.close()